0% found this document useful (0 votes)
8 views22 pages

Ethereum Price Analysis 2016-2022

The document analyzes Ethereum price data from 2016 to 2022, highlighting significant volatility and growth with a price range from $6.68 to $4808.34. Various data visualizations, including time series plots, histograms, boxplots, and violin plots, illustrate trends in closing, opening, high, low prices, and trading volume, indicating a long-term upward trend and extreme fluctuations. The analysis reveals that the majority of prices and trading volumes are concentrated below $500, with notable outliers during market turmoil.

Uploaded by

pkc11960
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views22 pages

Ethereum Price Analysis 2016-2022

The document analyzes Ethereum price data from 2016 to 2022, highlighting significant volatility and growth with a price range from $6.68 to $4808.34. Various data visualizations, including time series plots, histograms, boxplots, and violin plots, illustrate trends in closing, opening, high, low prices, and trading volume, indicating a long-term upward trend and extreme fluctuations. The analysis reveals that the majority of prices and trading volumes are concentrated below $500, with notable outliers during market turmoil.

Uploaded by

pkc11960
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

KONG Runzhi email:krzRyan@163.

com

[Link] Statistics and Data Visualization

The data selected here is the price data of Ethereum from 2016 to 2022, and the
data source is [Link]
cryptocurrencies-historical-dataset.

In [90]: import pandas as pd


import [Link] as plt
import seaborn as sns
import numpy as np

In [92]: [Link](style="whitegrid")
file_path = r'C:\Users\kingr\Desktop\coin\[Link]'
# load data
df = pd.read_csv(file_path)

In [94]: # Data cleaning

# Check for missing values


print([Link]().sum())

# Drop rows containing missing values


df = [Link]()

# Convert the 'Date' column to datetime type


df['Date'] = pd.to_datetime(df['Date'])

print([Link])

Date 0
Open 0
High 0
Low 0
Close 0
Volume 0
Currency 0
dtype: int64
Date datetime64[ns]
Open float64
High float64
Low float64
Close float64
Volume int64
Currency object
dtype: object

In [96]: # Data exploration

pd.set_option('display.max_columns', None)
pd.set_option('[Link]', 1000)
print([Link]()) # Get descriptive statistics for the dataset
Date Open High Low
Close Volume
count 2358 2358.000000 2358.000000 2358.000000
2358.000000 2.358000e+03
mean 2019-06-01 11:59:59.999999744 847.608083 877.386828 813.515225
848.270513 1.269467e+07
min 2016-03-10 00:00:00 6.680000 7.320000 5.860000
6.700000 0.000000e+00
25% 2017-10-20 06:00:00 138.767500 144.417500 134.780000
138.990000 5.465530e+05
50% 2019-06-01 12:00:00 279.165000 288.000000 266.885000
280.115000 1.429778e+06
75% 2021-01-10 18:00:00 1124.007500 1170.885000 1045.820000
1127.730000 7.717627e+06
max 2022-08-23 00:00:00 4808.340000 4864.060000 4715.430000
4808.380000 1.792561e+09
std NaN 1150.297624 1186.544788 1107.868923
1150.261834 1.014013e+08

From the data, we can understand that the lowest price of Ethereum was $6.68,
which occurred on March 10, 2016; the highest price was $4808.34, which
occurred on August 23, 2022; the price range from $6.68 to $4808.34 indicates
significant volatility and growth.

The standard deviation of Ethereum's opening price, highest price, lowest price,
and closing price are all very high, indicating that the price of Ethereum
fluctuated greatly during this period.

The median date of the dataset is June 1, 2019, which indicates that the dataset
is balanced in time and does not favor any specific time period.

In [99]: # Create a canvas with a specified size and a grid of subplots


fig, axs = [Link](4, 1, figsize=(14, 12)) # 4 rows, 1 column

# Define a color palette


color_Close = (105/255, 158/255, 212/255)

# First subplot: Time series plot for Ethereum Close Price Over Time
[Link](data=df, x='Date', y='Close', ax=axs[0], label='Close Price', c
axs[0].set_title('Ethereum Close Price Over Time')
axs[0].set_ylabel('Price (USD)')
axs[0].set_xlabel('Date')

# Second subplot: Histogram to view the distribution of Ethereum Close Price


[Link](df['Close'], bins=30, kde=True, ax=axs[1], color=color_Close,al
axs[1].set_title('Distribution of Ethereum Close Prices')
axs[1].set_ylabel('Frequency')
axs[1].set_xlabel('Price (USD)')

# Third subplot: Boxplot to view the distribution and outliers of Ethereum C


[Link](x=df['Close'], ax=axs[2],color=color_Close)
axs[2].set_title('Boxplot of Ethereum Close Prices')
axs[2].set_ylabel('Price (USD)')
# Fourth subplot: Violin plot to view the distribution and density of Ethere
[Link](x=df['Close'], ax=axs[3],color=color_Close)
axs[3].set_title('Violin Plot of Ethereum Close Prices')
axs[3].set_ylabel('Price (USD)')

# Remove grid lines from all subplots


for ax in axs:
[Link](False)

# Adjust the spacing between the subplots to ensure labels and titles are vi
plt.tight_layout()

# Display the plot with all subplots


[Link]()

Ethereum Close Prices show a long-term upward trend, especially in 2017 and
2021, which coincides with the bull market cycles in the cryptocurrency market.
The frequency distribution chart indicates that Ethereum's closing prices are
mainly concentrated below 500 USD. The boxplot reveals the median, quartiles
(Q1 and Q3), and outliers of Ethereum's closing prices. There are many outliers
in the chart, indicating extreme price fluctuations during periods of market
turmoil. The violin plot has a long tail, suggesting a higher frequency of extreme
price fluctuations.

In [102… # Create a canvas with a specified size and a grid of subplots (4 rows, 1 co
fig, axs = [Link](4, 1, figsize=(14, 12)) # 4 rows, 1 column

# Define a color palette


color_open = (251/255, 180/255, 93/255)

# First subplot: Time series plot for Ethereum Open Price Over Time
[Link](data=df, x='Date', y='Open', ax=axs[0], label='Open Price', col
axs[0].set_title('Ethereum Open Price Over Time')
axs[0].set_ylabel('Price (USD)')
axs[0].set_xlabel('Date')
axs[0].fill_between(df['Date'], df['Open'], color=color_open, alpha=0.1) #

# Second subplot: Histogram to view the distribution of Ethereum Open Prices


[Link](df['Open'], bins=30, kde=True, ax=axs[1], color=color_open, alp
axs[1].set_title('Distribution of Ethereum Open Prices')
axs[1].set_ylabel('Frequency')
axs[1].set_xlabel('Price (USD)')

# Third subplot: Boxplot to view the distribution and outliers of Ethereum O


[Link](x=df['Open'], ax=axs[2], color=color_open)
axs[2].set_title('Boxplot of Ethereum Open Prices')
axs[2].set_ylabel('Price (USD)')

# Fourth subplot: Violin plot to view the distribution and density of Ethere
[Link](x=df['Open'], ax=axs[3], color=color_open)
axs[3].set_title('Violin Plot of Ethereum Open Prices')
axs[3].set_ylabel('Price (USD)')

# Remove grid lines from all subplots


for ax in axs:
[Link](False)

# Adjust the spacing between the subplots to ensure labels and titles are vi
plt.tight_layout()

# Display the plot with all subplots


[Link]()
Ethereum Open Prices exhibit a clear long-term upward trend, with the price
distribution relatively concentrated below 500 USD, and are prone to extreme
fluctuations during periods of market turmoil, with the data distribution showing
skewness.

In [105… # Create a canvas with a specified size and a grid of subplots (4 rows, 1 co
fig, axs = [Link](4, 1, figsize=(14, 12)) # 4 rows, 1 column

# Define a color palette


color_high = (239/255, 129/255, 131/255)

# First subplot: Time series plot for Ethereum High Price Over Time
[Link](data=df, x='Date', y='High', ax=axs[0], label='High Price', col
axs[0].set_title('Ethereum High Price Over Time')
axs[0].set_ylabel('Price (USD)')
axs[0].set_xlabel('Date')
# axs[0].fill_between(df['Date'], df['High'], color=color_high, alpha=0.1)

# Second subplot: Histogram to view the distribution of Ethereum High Prices


[Link](df['High'], bins=30, kde=True, ax=axs[1], color=color_high, alp
axs[1].set_title('Distribution of Ethereum High Prices')
axs[1].set_ylabel('Frequency')
axs[1].set_xlabel('Price (USD)')
# Third subplot: Boxplot to view the distribution and outliers of Ethereum H
[Link](x=df['High'], ax=axs[2], color=color_high)
axs[2].set_title('Boxplot of Ethereum High Prices')
axs[2].set_ylabel('Price (USD)')

# Fourth subplot: Violin plot to view the distribution and density of Ethere
[Link](x=df['High'], ax=axs[3], color=color_high)
axs[3].set_title('Violin Plot of Ethereum High Prices')
axs[3].set_ylabel('Price (USD)')

# Remove grid lines from all subplots


for ax in axs:
[Link](False)

# Adjust the spacing between the subplots to ensure labels and titles are vi
plt.tight_layout()

# Display the plot with all subplots


[Link]()

Ethereum High Prices have shown a consistent long-term growth pattern, with
the majority of prices concentrated at lower values. The data distribution
exhibits signs of market volatility and skewness, with a higher frequency of
extreme price movements.

In [108… # Create a canvas with a specified size and a grid of subplots (4 rows, 1 co
fig, axs = [Link](4, 1, figsize=(14, 12)) # 4 rows, 1 column

# Define a color palette


color_low = (184/255, 140/255, 192/255)

# First subplot: Time series plot for Ethereum Low Price Over Time
[Link](data=df, x='Date', y='Low', ax=axs[0], label='Low Price', color
axs[0].set_title('Ethereum Low Price Over Time')
axs[0].set_ylabel('Price (USD)')
axs[0].set_xlabel('Date')
# axs[0].fill_between(df['Date'], df['Low'], color=color_low, alpha=0.1) #

# Second subplot: Histogram to view the distribution of Ethereum Low Prices


[Link](df['Low'], bins=30, kde=True, ax=axs[1], color=color_low, alpha
axs[1].set_title('Distribution of Ethereum Low Prices')
axs[1].set_ylabel('Frequency')
axs[1].set_xlabel('Price (USD)')

# Third subplot: Boxplot to view the distribution and outliers of Ethereum L


[Link](x=df['Low'], ax=axs[2], color=color_low)
axs[2].set_title('Boxplot of Ethereum Low Prices')
axs[2].set_ylabel('Price (USD)')

# Fourth subplot: Violin plot to view the distribution and density of Ethere
[Link](x=df['Low'], ax=axs[3], color=color_low)
axs[3].set_title('Violin Plot of Ethereum Low Prices')
axs[3].set_ylabel('Price (USD)')

# Remove grid lines from all subplots


for ax in axs:
[Link](False)

# Adjust the spacing between the subplots to ensure labels and titles are vi
plt.tight_layout()

# Display the plot with all subplots


[Link]()
Ethereum Low Prices shows a long-term increasing trend over time, particularly
evident during the bull markets of 2017 and 2021. The price distribution is
mainly concentrated below 500 USD, and the long-tailed violin plot along with
the outliers in the boxplot together indicate extreme price fluctuations and
skewness in the distribution of Ethereum prices during periods of market turmoil.

In [111… # Create a canvas with a specified size and a grid of subplots (4 rows, 1 co
fig, axs = [Link](4, 1, figsize=(14, 12)) # 4 rows, 1 column

# Define a color palette


color_volume = (164/255, 217/255, 187/255)

# First subplot: Time series plot for Ethereum Volume Over Time
[Link](data=df, x='Date', y='Volume', ax=axs[0], label='Volume', color
axs[0].set_title('Ethereum Volume Over Time')
axs[0].set_ylabel('Volume')
axs[0].set_xlabel('Date')
# axs[0].fill_between(df['Date'], df['Volume'], color=color_volume, alpha=0.

# Second subplot: Histogram to view the distribution of Ethereum Volume


[Link](df['Volume'], bins=30, kde=True, ax=axs[1], color=color_volume,
axs[1].set_title('Distribution of Ethereum Volume')
axs[1].set_ylabel('Frequency')
axs[1].set_xlabel('Volume')

# Third subplot: Boxplot to view the distribution and outliers of Ethereum V


[Link](x=df['Volume'], ax=axs[2], color=color_volume)
axs[2].set_title('Boxplot of Ethereum Volume')
axs[2].set_ylabel('Volume')

# Fourth subplot: Violin plot to view the distribution and density of Ethere
[Link](x=df['Volume'], ax=axs[3], color=color_volume)
axs[3].set_title('Violin Plot of Ethereum Volume')
axs[3].set_ylabel('Volume')

# Remove grid lines from all subplots


for ax in axs:
[Link](False)

# Adjust the spacing between the subplots to ensure labels and titles are vi
plt.tight_layout()

# Display the plot with all subplots


[Link]()

In 2016, the trading volume was relatively low, but it gradually increased over
time, reaching a peak in 2022, indicating an increase in market activity. From the
perspective of quartiles, 50% of the data falls between 546,553 and 7,717,627 in
trading volume. This suggests that the distribution of trading volume is relatively
concentrated, but there are also some very high trading volume values.

In [130… # Calculate the difference between Open and Close prices


df['Open_Minus_Close'] = df['Open'] - df['Close']

# Calculate the difference between High and Low prices


df['High_Minus_Low'] = df['High'] - df['Low']

# Create a figure for plotting


[Link](figsize=(14, 7))

# Plot the time series for Open - Close


[Link](2, 1, 1) # Parameters indicate (number of rows, number of colum
[Link]([Link], df['Open_Minus_Close'], label='Open - Close')
[Link]('Open - Close Time Series')
[Link]('Date')
[Link]('Value')
[Link]()
[Link](False)

# Plot the time series for High - Low


[Link](2, 1, 2)
[Link]([Link], df['High_Minus_Low'], label='High - Low', color='orange')
[Link]('High - Low Time Series')
[Link]('Date')
[Link]('Value')
[Link]()
[Link](False)
# Adjust the spacing between subplots
plt.tight_layout()

# Display the plot


[Link]()
Ethereum experienced significant fluctuations in the difference between opening
and closing prices in 2018, and between 2021-2022, indicating high market
volatility. The difference between the highest and lowest prices in 2018, and
from 2021 to 2022, increased over time, which may suggest that market
volatility is on the rise, reflecting extreme market sentiment. The larger price
differences may indicate a significant divergence of opinions among market
participants.

In [133… # Create a figure for plotting


[Link](figsize=(14, 7))

# Plot the frequency distribution histogram for Open_Minus_Close


[Link](1, 2, 1) # Parameters indicate (number of rows, number of colum
[Link](df['Open_Minus_Close'], bins=30, kde=True, color='blue', stat='
[Link]('Frequency Distribution of Open - Close')
[Link]('Open - Close Value')
[Link]('Density')
[Link](False)

# Plot the frequency distribution histogram for High_Minus_Low


[Link](1, 2, 2)
[Link](df['High_Minus_Low'], bins=30, kde=True, color='green', stat='d
[Link]('Frequency Distribution of High - Low')
[Link]('High - Low Value')
[Link]('Density')
[Link](False)
# Adjust the spacing between subplots
plt.tight_layout()

# Display the plot


[Link]()

The fluctuation range of the opening price minus the closing price is between
-200 and 200, while the fluctuation range of the highest price minus the lowest
price is between 0 and 400. Although the prices seem concentrated, this range
of fluctuation is quite large compared to products such as bonds and stocks.

In [135… # Calculate the correlation between the closing price and trading volume
correlation = df['Close'].corr(df['Volume'])

# Print the correlation coefficient


print(f"The correlation coefficient between closing price and trading volume

# Plot a scatter plot to visualize the relationship between closing price an


[Link](figsize=(10, 6))
[Link](x='Volume', y='Close', data=df)
[Link]('Scatter Plot of Closing Price vs Trading Volume')
[Link]('Trading Volume')
[Link]('Closing Price')
[Link](False)
[Link]()

The correlation coefficient between closing price and trading volume is: 0.1
0064573980115256

The closing price and trading volume show no significant correlation.

In [137… # Calculate the price range (difference between high and low prices)
df['Price_Range'] = df['High'] - df['Low']

# Calculate the correlation between trading volume and price range


correlation = df['Volume'].corr(df['Price_Range'])

# Print the correlation coefficient


print(f"The correlation coefficient between trading volume and price range i
# Plot a scatter plot to visualize the relationship between trading volume a
[Link](figsize=(10, 6))
[Link](x='Volume', y='Price_Range', data=df)
[Link]('Scatter Plot of Trading Volume vs Price Range')
[Link]('Trading Volume')
[Link]('Price Range (High - Low)')
[Link](False)
[Link]()

The correlation coefficient between trading volume and price range is: 0.060
42639593882819

There is no significant correlation between the difference between the highest


and lowest prices and the trading volume.

[Link] Prediction

In [139… import numpy as np


import pandas as pd
import [Link] as plt
import [Link] as mdates

# Define the file path for the dataset


file_path = r'C:\Users\kingr\Desktop\coin\[Link]'

# Read the data from the CSV file


data = pd.read_csv(file_path)

# Convert the 'Date' column to datetime format


data['Date'] = pd.to_datetime(data['Date'])

# Calculate the log return of the closing prices


data['Log Return'] = [Link](data['Close'] / data['Close'].shift(1))

# Set the number of days to use for volatility calculation


N = 30 # Using 30 days of data

# Calculate the annualized volatility and shift the result to align with the
data['Annualized Volatility'] = ([Link](365) *
data['Log Return'].rolling(window=N).std()

data['Adjusted Date'] = data['Date'] + [Link](months=1)

# Create a plot with a specified size


[Link](figsize=(14, 7))

# Define a color for the annualized volatility line


color_Annualized_Volatility = (105/255, 158/255, 212/255)

# Plot the annualized volatility against the adjusted date


[Link](data['Adjusted Date'], data['Annualized Volatility'],
label='Annualized Volatility', color=color_Annualized_Volatility)

# Set the title and labels for the plot


[Link]('Annualized Volatility of Cryptocurrency')
[Link]('Date')
[Link]('Volatility')

# Add a legend to the plot


[Link]()

# Enable grid lines on the plot


[Link]()

# Set the date format on the x-axis to 'Year-Month'


[Link]().xaxis.set_major_formatter([Link]('%Y-%m'))

# Set the major tick locator to every 3 months to reduce the number of ticks
[Link]().xaxis.set_major_locator([Link](interval=3))

# Automatically rotate the date labels to avoid overlap


[Link]().autofmt_xdate()

# Display the plot


[Link]()
The plot of Annualized Volatility indicates a periodic pattern and nonlinearity in
the time series. Nonlinear models, such as LSTM and BiLSTM, are suitable for
prediction due to their effectiveness in modeling complex nonlinear
relationships. These neural network architectures are chosen for their ability to
capture the intricacies of the data and forecast with greater accuracy.

Prediction

In [142… import numpy as np


import pandas as pd
import [Link] as plt
import [Link] as mdates

# Define the file path for the dataset


file_path = r'C:\Users\kingr\Desktop\coin\[Link]'

# Read the data from the CSV file


data = pd.read_csv(file_path)

# Convert the 'Date' column to datetime format


data['Date'] = pd.to_datetime(data['Date'])

# Calculate the log return of the closing prices


data['Log Return'] = [Link](data['Close'] / data['Close'].shift(1))

# Set the number of days to use for volatility calculation


N = 30 # Using 30 days of data

# Calculate the annualized volatility and shift the result to align with the
data['Annualized Volatility'] = ([Link](365) *
data['Log Return'].rolling(window=N).std()
# View basic statistical information of annualized volatility
annualized_volatility_stats = data['Annualized Volatility'].describe()
print(annualized_volatility_stats)
# View the number of annualized volatility data points
annualized_volatility_count = data['Annualized Volatility'].count()
print(f"Number of annualized volatility data points: {annualized_volatility_

count 2328.000000
mean 0.994604
std 0.384064
min 0.357432
25% 0.723471
50% 0.928119
75% 1.132257
max 2.576754
Name: Annualized Volatility, dtype: float64
Number of annualized volatility data points: 2328

In [174… import torch


import [Link] as nn
from [Link] import MinMaxScaler
import numpy as np
import pandas as pd
import [Link] as plt
from [Link] import mean_absolute_error, mean_squared_error

# Define a BiLSTM model


class BiLSTM([Link]):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(BiLSTM, self).__init__()
[Link] = [Link](input_size, hidden_size, num_layers, batch_first
[Link] = [Link](hidden_size * 2, output_size)

def forward(self, x):


out, _ = [Link](x)
out = [Link](out[:, -1, :])
return out

# Define an LSTM model


class LSTM([Link]):
def __init__(self, input_size, hidden_size, num_layers, output_size):
super(LSTM, self).__init__()
[Link] = [Link](input_size, hidden_size, num_layers, batch_first
[Link] = [Link](hidden_size, output_size)

def forward(self, x):


out, _ = [Link](x)
out = [Link](out[:, -1, :])
return out

# Data Preprocessing
data = pd.read_csv(r'C:\Users\kingr\Desktop\coin\[Link]')
data['Date'] = pd.to_datetime(data['Date'])
data['Log Return'] = [Link](data['Close'] / data['Close'].shift(1))
N = 30
data['Annualized Volatility'] = [Link](365) * data['Log Return'].rolling(wi
data = [Link](subset=['Annualized Volatility'])

volatility_data = data['Annualized Volatility'].values


scaler = MinMaxScaler(feature_range=(0, 1))
volatility_scaled = scaler.fit_transform(volatility_data.reshape(-1, 1))

def create_dataset(data, time_step=1):


X, y = [], []
for i in range(len(data) - time_step):
[Link](data[i:(i + time_step), 0])
[Link](data[i + time_step, 0])
return [Link](X), [Link](y)

time_step = 30
X, y = create_dataset(volatility_scaled, time_step)
X = [Link]([Link][0], [Link][1], 1)

train_size = int(len(X) * 0.9)


X_train, X_test = X[:train_size], X[train_size:]
y_train, y_test = y[:train_size], y[train_size:]

X_train = [Link](X_train, dtype=torch.float32)


X_test = [Link](X_test, dtype=torch.float32)
y_train = [Link](y_train, dtype=torch.float32)
y_test = [Link](y_test, dtype=torch.float32)

# Initialize models, loss function, and optimizer


input_size = 1
hidden_size = 128
num_layers = 3
output_size = 1

bilstm_model = BiLSTM(input_size, hidden_size, num_layers, output_size)


lstm_model = LSTM(input_size, hidden_size, num_layers, output_size)

criterion = [Link]()
optimizer_bilstm = [Link](bilstm_model.parameters(), lr=0.001)
optimizer_lstm = [Link](lstm_model.parameters(), lr=0.001)

# Train BiLSTM model


epochs = 100
for epoch in range(epochs):
bilstm_model.train()
outputs = bilstm_model(X_train)
loss = criterion(outputs, y_train.view(-1, 1))
optimizer_bilstm.zero_grad()
[Link]()
optimizer_bilstm.step()

if (epoch+1) % 10 == 0:
print(f'Epoch [{epoch+1}/{epochs}], BiLSTM Loss: {[Link]():.4f}')

# Train LSTM model


for epoch in range(epochs):
lstm_model.train()
outputs = lstm_model(X_train)
loss = criterion(outputs, y_train.view(-1, 1))
optimizer_lstm.zero_grad()
[Link]()
optimizer_lstm.step()

# Make predictions
bilstm_model.eval()
lstm_model.eval()

bilstm_train_preds = bilstm_model(X_train).detach().numpy()
bilstm_test_preds = bilstm_model(X_test).detach().numpy()

lstm_train_preds = lstm_model(X_train).detach().numpy()
lstm_test_preds = lstm_model(X_test).detach().numpy()

# Inverse transform the predictions and actual values


bilstm_train_preds = scaler.inverse_transform(bilstm_train_preds)
bilstm_y_train_actual = scaler.inverse_transform(y_train.view(-1, 1).numpy()

bilstm_test_preds = scaler.inverse_transform(bilstm_test_preds)
bilstm_y_test_actual = scaler.inverse_transform(y_test.view(-1, 1).numpy())

lstm_train_preds = scaler.inverse_transform(lstm_train_preds)
lstm_y_train_actual = scaler.inverse_transform(y_train.view(-1, 1).numpy())

lstm_test_preds = scaler.inverse_transform(lstm_test_preds)
lstm_y_test_actual = scaler.inverse_transform(y_test.view(-1, 1).numpy())

# Calculate MAE, MAPE, RMSE for both models


def calculate_metrics(true, predicted):
mae = mean_absolute_error(true, predicted)
mape = [Link]([Link]((true - predicted) / true)) * 100
rmse = [Link](mean_squared_error(true, predicted))
return mae, mape, rmse

# Calculate metrics for BiLSTM


bilstm_train_mae, bilstm_train_mape, bilstm_train_rmse = calculate_metrics(b
bilstm_test_mae, bilstm_test_mape, bilstm_test_rmse = calculate_metrics(bils

# Calculate metrics for LSTM


lstm_train_mae, lstm_train_mape, lstm_train_rmse = calculate_metrics(lstm_y_
lstm_test_mae, lstm_test_mape, lstm_test_rmse = calculate_metrics(lstm_y_tes

Epoch [10/100], BiLSTM Loss: 0.0301


Epoch [20/100], BiLSTM Loss: 0.0246
Epoch [30/100], BiLSTM Loss: 0.0114
Epoch [40/100], BiLSTM Loss: 0.0034
Epoch [50/100], BiLSTM Loss: 0.0022
Epoch [60/100], BiLSTM Loss: 0.0017
Epoch [70/100], BiLSTM Loss: 0.0015
Epoch [80/100], BiLSTM Loss: 0.0013
Epoch [90/100], BiLSTM Loss: 0.0015
Epoch [100/100], BiLSTM Loss: 0.0012

In [175… # Print metrics


print("BiLSTM Metrics:")
print(f"Training MAE: {bilstm_train_mae:.4f}, MAPE: {bilstm_train_mape:.2f}%
print(f"Testing MAE: {bilstm_test_mae:.4f}, MAPE: {bilstm_test_mape:.2f}%, R
print("\nLSTM Metrics:")
print(f"Training MAE: {lstm_train_mae:.4f}, MAPE: {lstm_train_mape:.2f}%, RM
print(f"Testing MAE: {lstm_test_mae:.4f}, MAPE: {lstm_test_mape:.2f}%, RMSE:

# Visualize the results


[Link](figsize=(12, 6))

# Define custom RGB colors


actual_color = (26/255, 40/255, 71/255)
bilstm_color = (16/255, 139/255, 150/255)
lstm_color = (239/255, 109/255, 61/255)

# Plot training data predictions vs actual values


[Link](1, 2, 1)
[Link](bilstm_y_train_actual, label='Actual', color=actual_color)
[Link](bilstm_train_preds, label='BiLSTM Predicted', color=bilstm_color)
[Link](lstm_train_preds, label='LSTM Predicted', color=lstm_color)
[Link]('Training Data Comparison')
[Link](False)
[Link]()

# Plot testing data predictions vs actual values


[Link](1, 2, 2)
[Link](bilstm_y_test_actual, label='Actual', color=actual_color)
[Link](bilstm_test_preds, label='BiLSTM Predicted', color=bilstm_color)
[Link](lstm_test_preds, label='LSTM Predicted', color=lstm_color)
[Link]('Testing Data Comparison')
[Link](False)
[Link]()

plt.tight_layout()
[Link]()

BiLSTM Metrics:
Training MAE: 0.0442, MAPE: 4.44%, RMSE: 0.0775
Testing MAE: 0.0330, MAPE: 3.85%, RMSE: 0.0465

LSTM Metrics:
Training MAE: 0.0738, MAPE: 7.71%, RMSE: 0.1202
Testing MAE: 0.0517, MAPE: 6.24%, RMSE: 0.0673
The analysis reveals that the BiLSTM model outperforms the LSTM model in both
training and testing scenarios, as evidenced by its lower MAE, MAPE, and RMSE
values. This superior performance suggests that BiLSTM is more adept at
capturing the underlying patterns in the data, leading to better fitting and more
accurate predictions. The BiLSTM's bidirectional architecture enables it to
leverage both past and future information, which is particularly advantageous for
time series analysis where the direction of trends is significant. Compared to
LSTM, which only considers past data, BiLSTM demonstrates a stronger
generalization capability and is less susceptible to overfitting, making it a more
reliable choice for predicting new, unseen data. The smaller gap between
training and testing metrics for BiLSTM further supports its enhanced
generalization, making it the preferred model for this predictive [Link],
the following experiments will use the BiLSTM model.

In [178… #Use all data for training and predict the next 10% length data
# Use all data for training the model
X_all, y_all = create_dataset(volatility_scaled, time_step)
X_all = X_all.reshape(X_all.shape[0], X_all.shape[1], 1)

# Convert to tensor
X_all = [Link](X_all, dtype=torch.float32)
y_all = [Link](y_all, dtype=torch.float32)

# Train the model on all data


[Link]()
for epoch in range(epochs):
outputs = model(X_all)
loss = criterion(outputs, y_all.view(-1, 1))
optimizer.zero_grad()
[Link]()
[Link]()

if (epoch+1) % 10 == 0:
print(f'All Data - Epoch [{epoch+1}/{epochs}], Loss: {[Link]():.4

# Predict next 10% of the data length


pred_len = int(len(volatility_scaled) * 0.1)
input_data = volatility_scaled[-time_step:].reshape(1, time_step, 1) # Use

[Link]()
future_preds = []
for _ in range(pred_len):
with torch.no_grad():
prediction = model([Link](input_data, dtype=torch.float32))
future_preds.append([Link]())
input_data = [Link](input_data, -1)
input_data[0, -1, 0] = [Link]()

# Inverse transform the predictions back to original scale


future_preds = scaler.inverse_transform([Link](future_preds).reshape(-1, 1

#Visualize the predicted future data


predicted_dates = pd.date_range(start=data['Date'].iloc[-1], periods=pred_le
[Link](figsize=(10, 5))
[Link](data['Date'], volatility_data, label='Actual Data', color=actual_co
[Link](predicted_dates, future_preds, label='Predicted Future Data', color
[Link]('Annualized Volatility - Actual vs Predicted Future')
[Link]('Date')
[Link]('Annualized Volatility')
[Link]()
plt.tight_layout()
[Link](False)
[Link]()

All Data - Epoch [10/100], Loss: 0.0017


All Data - Epoch [20/100], Loss: 0.0015
All Data - Epoch [30/100], Loss: 0.0014
All Data - Epoch [40/100], Loss: 0.0014
All Data - Epoch [50/100], Loss: 0.0014
All Data - Epoch [60/100], Loss: 0.0013
All Data - Epoch [70/100], Loss: 0.0012
All Data - Epoch [80/100], Loss: 0.0012
All Data - Epoch [90/100], Loss: 0.0012
All Data - Epoch [100/100], Loss: 0.0011
Based on the forecast results from the BiLSTM model, it is indicated that the
annualized volatility will show a decreasing trend in the coming period.
Compared with historical data, the predicted values are within a reasonable
range, and the statistical errors (MAE, MAPE, RMSE) demonstrate that the model
has a high level of predictive accuracy. Therefore, I suggest that it is appropriate
to moderately increase the holdings of Ethereum coins. At the same time,
continuous monitoring of market dynamics is necessary, and preparations should
be made to address adverse sudden information about Ethereum or digital
currencies in general. It is recommended to take appropriate risk mitigation
measures.

You might also like