1. 久十比特币首页
  2. 比特币
  3. 比特币价格

用于比特币价格预测的 ARIMA 模型

预测现实世界中的结果是一项具有挑战性的任务,尤其是在应对瞬息万变的未来时。以波动性和不可预测性着称的股票市场,在追求利润的过程中给投资者带来了持续的风险。人们投资于股票市场,希望获得经济利益。影响股价的因素有很多,包括供求关系、市场趋势、全球经济、公司业绩、历史数据、公众情绪、敏感的财务信息以及公司及其产品的受欢迎程度,所有这些都会影响买家的数量。尽管分析了各种因素,但在股票市场上取得持续成功并准确预测未来价格仍然很困难。即使提前一天预测特定股票的价格也是一项复杂的工作。在这篇博文中,我们专注于预测特定年份每一天的次日股票价格,并将这些预测与实际价格进行比较,以评估模型的性能。具体来说,我们的任务是使用历史时间序列数据预测比特币 (BTC) 价格,其中包括开盘价和收盘价、交易量和日期等特征。时间序列数据是指在一段时间内收集的连续数据点的集合,通常显示可辨别的模式。

可以根据时间顺序对这些数据点进行索引、列出或绘制图表。时间序列数据,也称为历史数据或过去数据,用于根据过去的观察结果预测未来值,一种称为时间序列分析的做法。时间序列数据的示例包括股票的每日收盘价、海洋潮汐高度和太阳黑子的数量。研究时间序列数据的目的多种多样,例如根据过去的知识预测未来结果,以及了解序列的潜在模式或特征。预测观察到的时间序列中的未来价格在科学、工程、金融、商业智能、经济学、气象学和电信等众多领域中起着至关重要的作用。为了根据时间序列数据预测结果,通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。海洋潮汐的高度,以及太阳黑子的数量。研究时间序列数据的目的多种多样,例如根据过去的知识预测未来结果,以及了解序列的潜在模式或特征。预测观察到的时间序列中的未来价格在科学、工程、金融、商业智能、经济学、气象学和电信等众多领域中起着至关重要的作用。为了根据时间序列数据预测结果,通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。

币安Binance

币安Binance

全球顶级交易所,手机即可买比特币,10元买比特币,1元买NFT!!!

ARIMA 模型分析历史价格以准确预测未来股票价格。海洋潮汐的高度,以及太阳黑子的数量。研究时间序列数据的目的多种多样,例如根据过去的知识预测未来结果,以及了解序列的潜在模式或特征。预测观察到的时间序列中的未来价格在科学、工程、金融、商业智能、经济学、气象学和电信等众多领域中起着至关重要的作用。为了根据时间序列数据预测结果,通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。例如根据过去的知识预测未来的结果和理解系列的潜在模式或特征。预测观察到的时间序列中的未来价格在科学、工程、金融、商业智能、经济学、气象学和电信等众多领域中起着至关重要的作用。为了根据时间序列数据预测结果,通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。例如根据过去的知识预测未来的结果和理解系列的潜在模式或特征。预测观察到的时间序列中的未来价格在科学、工程、金融、商业智能、经济学、气象学和电信等众多领域中起着至关重要的作用。为了根据时间序列数据预测结果,通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。通常采用称为自回归积分移动平均 (ARIMA) 的机器学习技术。ARIMA 模型分析历史价格以准确预测未来股票价格。

时间序列定义
时间序列是指在定义的时间段内以特定间隔记录或观察的数据点的集合。时间序列的显着特征是时间本身作为数据集中的变量之一。通常,时间序列数据是定期收集的,可以是固定的(例如,每小时、每天、每月)或不规则的(例如,偶发事件或随机采样间隔)。

时间序列数据集中的时间成分在分析和理解数据中的潜在模式、趋势和依赖性方面起着至关重要的作用。它允许检查感兴趣的变量如何随时间变化,从而能够识别时间模式、季节性和其他与时间相关的影响。

通过研究和建模时间序列数据,可以为各种应用程序获得有价值的见解,例如预测未来值、检测异常或趋势,以及根据历史模式做出数据驱动的决策。

数据什么时候是时间序列,什么时候不是?

如果预测变量依赖于其在特定时间段内的先前值,则数据被视为时间序列。例如,在预测特定位置的温度时,如果今天的温度(t)受到前一天(t-1)和前几天(t-2)、(t-3)等的影响,那么上,则它有资格作为时间序列问题。但是,如果温度取决于风、湿度等其他因素,则它不再属于时间序列问题的范畴。在这种情况下,它变成了具有因变量和自变量的回归问题。现在让我们探讨如何解决此类问题。

ARIMA(自回归综合移动平均线)模型

ARIMA(AutoRegressive Integrated Moving Average)模型是一种广泛使用的时间序列预测模型。它是 ARMA(自回归移动平均)模型的高级扩展,它结合了两个更简单的组件:

1. AR(自回归):AR 模型旨在根据过去的值预测未来值。这些模型假设时间序列的未来值取决于其先前值。然而,AR 模型要求时间序列是平稳的,这意味着它的统计属性不会随时间变化。

2. MA(移动平均线):MA 模型根据过去的预测误差预测未来值。这些模型假设观察到的序列可以用自回归模型来近似。请务必注意,本文中的术语“移动平均线”指的是预测模型,而不是众所周知的平滑技术。

ARIMA 模型结合了自回归和移动平均分量,同时还包含差分。差分过程通过从当前值中减去先前的值来帮助将时间序列转换为固定形式。这被称为 ARIMA 模型的集成组件。

通过利用自回归、移动平均和差分组件,ARIMA 模型为时间序列预测提供了一个综合框架,可适应各种数据模式和趋势。

用于比特币价格预测的 ARIMA 模型

2. 方法论

2.1 导入需要的库

为了构建模型,必须合并后续库:pandas、numpy、pyplot、statsmodels.tsa.stattools.adfuller、statsmodels.tsa.seasonal.seasonal_decompose、statsmodels.api、matplotlib.dates、datetime、yfinance、警告

从statsmodels.tsa.stattools导入pandas作为pd
导入numpy作为np
导入matplotlib.pyplot作为plt
从statsmodels.tsa.seasonal导入adfuller导入seasonal_decompose导入statsmodels.api作为sm导入matplotlib.dates
作为mpl_dates _ _ _ _ _ _ _ _导入警告




2.2 下载所需数据

要执行分析,初始步骤涉及从 Yahoo Finance 下载数据。该平台被认为是可以获得交易数据的可靠来源。除了比特币数据之外,还可以通过使用以下代码并修改名为“name”的变量来下载加密货币价格或股票价格。

date = datetime.today().strftime('%Y-%m-%d')'%Y-%m-%d' ) 
name = "BTC-USD"
ticker = yfinance.Ticker(name)
df = ticker.history(interval= "1d" ,start= "2021-03-01" ,end = date )
df[ "Date" ] = pd.to_datetime(df.index)
df[ 'Date' ] = df[ 'Date' ].apply(mpl_dates.date2num)
df = df.loc[:,[ 'Date' , '开盘价'、'高价'、'低价'、'收盘价' ]]

2.3 绘制所需数据

建议继续可视化我们的数据集,因为这将有助于理解数据的外观和结构。为此,我们可以从我们创建的 DataFrame 中绘制 BTC 的收盘价

fig, (ax) = plt.subplots() 
date_format = mpl_dates.DateFormatter('%d %b %Y')'%d %b %Y' )
ax.plot( df [ "Date" ], df [ "Close" ], label = "Closing Price" )
ax.legend(loc = "best" )
ax.xaxis.set_major_formatter( date_format)
fig.autofmt_xdate()
plt.show()

事实上,BTC 价格呈现出明显的同比变化,这被称为趋势。这种趋势可以持续增加、持续减少或两者兼而有之。在某些情况下,可能根本没有明显的趋势。要计算趋势,一种方法是使用过去“n”天的移动平均线。对于此特定数据集,已考虑 n=12 的值。

#绘制滚动平均值和滚动标准
rolling_mean = df[ "Close" ].rolling(window = 12 ).mean()
rolling_std = df[ "Close" ].rolling(window = 12 ).std()
plt.plot( df[ "Close" ], color = 'blue' , label = 'Original' )
plt.plot(rolling_mean, color = 'red' , label = 'Rolling Mean' )
plt.plot(rolling_std, color = 'black' , label = 'Rolling Std' )
plt.legend(loc = 'best' )
plt.title( 'Rolling Mean &滚动标准差' )
plt.show()

在下图中,红线代表趋势。通常,当移动平均线低于实际价格时,表明市场走势向上。相反,当移动平均线高于实际价格时,则表明市场趋势向下。黑线代表标准偏差。

时间序列上下文中的固定数据是指均值和方差随时间保持不变的数据。另一方面,非平稳数据表现出明显的趋势或季节性,表明均值和/或方差在不同时间段内发生变化。很明显,在这种情况下数据不是平稳的。在应用 ARIMA 模型之前,需要将数据转换为平稳形式。但是,让我们首先探索一种评估时间序列是否平稳的替代方法。

我们可以使用 Augmented Dickey-Fuller 检验来做到这一点。

ADF 检验,也称为 Augmented Dickey-Fuller 检验,是一种广泛使用的单位根检验。单位根的存在是造成时间序列不平稳的原因。就单位根而言,我们可以定义一个平稳的时间序列如下:如果一个时间序列移动一个时间段不改变其统计特性,则该时间序列被认为是平稳的。换句话说,平稳时间序列不具有单位根。

另一种方法是执行假设检验,并在 p 值小于或等于所选显着性水平时拒绝零假设。在这种情况下,为简单起见,如果 p 值小于 0.05(表明置信水平为 95%),我们将拒绝零假设(时间序列不稳定)。通过这样做,我们可以 95% 地确定我们的数据是平稳的(假设 p 值为 0.05)。这是这样做的代码。

#接受或拒绝H0假设。H0 假设 = 时间序列不是平稳的
result = adfuller(df[ 'Close' ])
print ( 'ADF Statistic: {}' . format (result[ 0 ]))
print ( 'p-value: {}' . format (结果[ 1 ]))
print ( 'Critical Values:' )
for key, value in result[ 4 ].items():
print ( '\t{}: {}' . format (key, value))

结果如下所示。很容易看出时间序列不是平稳的。

ADF 统计量:-1.8211105536515773 
p 值:0.37003239531915244
临界值:
1%:-3.4384994096285393
5%:-2.8651370452361107
10%:-2.56868539060993

拥有一个获取 p 值并绘制移动平均值和移动标准差的函数将是一个很好的选择。

#timeseries 是我们的数据框形式的数据集。该函数将查找“关闭” 
#label 并使用此数据
def get_stationarity ( timeseries ):

# rolling statistics
rolling_mean = timeseries.rolling(window= 12 ).mean()
rolling_std = timeseries.rolling(window= 12 )。 std()

# 滚动统计图
original = plt.plot(timeseries[ "Close" ], color= 'blue' , label= 'Original' )
mean = plt.plot(rolling_mean[ "Close" ], color= 'red' , label= '滚动平均值' )
std = plt.plot(rolling_std[ "Close" ], color= 'black' , label= 'Rolling Std' )
plt.legend(loc= 'best' )
plt.title( '滚动均值和标准差' )
plt. show(block= False )

# Dickey–Fuller test:
result = adfuller(timeseries[ "Close" ])
print ( 'ADF Statistic: {}' .format ( result[ 0 ]))
print ( 'p-value: {} ' . format (result[ 1 ]))
print ( '临界值:')
for key, value in result[ 4 ].items():
print ( '\t{}: {}' . format (key, value))
return (result[ 1 ])复制代码

2.4 使数据静止

有很多方法可以用来使数据平稳。在这里,我将讨论一些最常见的,并提供一个函数来执行此操作。

2.4.1. 日志转换

对数转换是时间序列分析中常用的技术,尤其是在处理价格数据时。通过将时间序列数据转换为对数刻度,可以减少数据的可变性。这种标准化对于捕捉价格的相对变化率特别有用。

对价格数据应用对数转换有几个优点。首先,它有助于稳定方差,使数据更适合统计建模。此外,它可以将指数增长模式线性化,使其更易于解释和分析。对数价格有效地标准化了变化率,提供了更一致的价格随时间变化的表示。

要对时间序列数据执行对数转换,您可以使用大多数编程语言和库中提供的对数函数(例如,自然对数、以 10 为底的对数)。通过对价格值取对数,您可以创建一个转换后的序列,该序列显示出减少的可变性并更好地符合许多时间序列模型的假设。

2.4.2. 电源改造

与对数变换相比,幂变换通常被认为不太直观。

2.4.3. Box-Cox 和 Yeo-Johnson

幂变换(例如 Box-Cox 和 Yeo-Johnson 变换)通常用于将数据转换为更正态分布的形式,特别是用于预测目的。虽然并不总是需要实现平稳性,但这些转换通常用于解决与数据中的非线性相关的问题。

Box-Cox 变换是一种参数方法,它优化一个幂参数来变换数据并使其更符合正态分布。类似地,Yeo-Johnson 转换是一个修改版本,可以处理正值和负值。通过应用这些转换,数据可以更好地适用于假定正态性的线性建模技术。

虽然这些幂转换的主要目的是提高数据的常态性,但在某些情况下它们也会对实现平稳性产生影响。通过解决非线性和规范化数据,这些转换可以通过使时间序列更稳定并消除任何系统模式或趋势来间接促进平稳性。

值得注意的是,虽然功率转换在某些情况下可能有效,但它们的应用应基于所分析数据的具体特征和要求。

2.4.4 使数据静止的代码

在这里,我展示了执行多个转换并检查 p 值以确定是否拒绝原假设的脚本。

#This function identifies the best option to make a series stationary 
#dataframe = the values in dataframe form
#case = 1, 2, 3, 确定数据区域如何变化

def get_best_stationarity ( dataframe, case ):
if case == 1 :
df_log = np.log(dataframe)
rolling_mean = df_log.rolling(window= 12 ).mean()
df_log_minus_mean = df_log - rolling_mean
df_log_minus_mean.dropna(inplace= True ) #删除NA值
df_log_minus_mean
p = get_stationarity(df_log_minus_mean)
elif case ==2 :
df_log = np.log(dataframe)
rolling_mean_exp_decay = df_log.ewm(halflife= 12 , min_periods= 0 , adjust= True ).mean()
df_log_exp_decay = df_log - rolling_mean_exp_decay
df_log_exp_decay.dropna(inplace= True )
p = get_stationarity(df_log_exp_decay )
elif case == 3 :
rolling_mean_exp_decay = df.ewm(halflife= 12 , min_periods= 0 , adjust= True ).mean()
df_log_exp_decay = dataframe - rolling_mean_exp_decay
df_log_exp_decay.dropna(inplace= True )
p = get_stationarity(df_log_exp_decay)
elif case == 4 :
df_log_shift = df - df.shift()
df_log_shift.dropna(inplace= True )
p = get_stationarity(df_log_shift)
elif case == 5 :
df_log = np.log(df)
df_log_shift 复制代码= df_log - df_log.shift()
df_log_shift.dropna(inplace= True )
p = get_stationarity(df_log_shift)
return (p)

p_val = list ()
for i in range ( 1 , 6 ):
p_val.append(get_best_stationarity(df, i))

这是代码生成的输出,按给定顺序显示。最初,显示统计分析结果,然后显示转换值的图表。

ADF 统计量:-6.167488227067498 
p 值:6.933136923040861e-08
临界值:
1%:-3.438602251755426
5%:-2.8651823762743245
10%:-2.568709538784067 3

ADF 统计:-4.872939733914288
p 值:3.936021182280582e-05
临界值:
1%: -3.438379332805805
5%:-2.865084115496387
10%:- 2.5686571948451586

ADF 统计量:-3.995126690320374
p 值:0.001436245409580712
临界值:
1%:- 3.4385095783477877 5%:-2.865141527500859
10 %:-2.5686877783346946 ADF 统计量:-8.177153918822858
p值:8.317635060265452 e-13临界值:1%:-3.4385095783477877





5%:-2.865141527500859
10%:-2.5686877783346946

ADF 统计量:-29.39948663516321
p 值:0.0
临界值:
1%:-3.4383892038884722
5%:-2.8650884667 384955
10%:-2.568659512747501

从以上结果可以明显看出,应用的最终转换显示出最低的 p 值,几乎为零。

df_log = np.log(df) 
df_log_shift = df_log - df_log.shift()
df_log_shift.dropna(就地=真)真)

现在是绘制 ACF 和 PACF 以确定所需 ARIMA 模型类型的时候了。

从statsmodels.graphics.tsaplots import plot_acf, plot_pacf 
plot_acf(df_log_shift[ "Close" ])
plot_pacf(df_log_shift[ "Close" ])

ARIMA(2, 1, 0) 似乎是最佳选择。这是模型的行为方式。

#decomposition = seasonal_decompose(df_log_shift["Close"])
model = sm.tsa.arima.ARIMA(df_log_shift[ "Close" ], order=( 2 , 1 , 0 ))
results = model.fit()
df_log_shift[ "预测" ] = results.fittedvalues
RSS = sum ((df_log_shift[ "predicted" ] - df_log_shift[ "Close" ])** 2 )
rounded_RSS = round (RSS, 3 )
plt.title(rounded_RSS)
plt.plot(df_log_shift[ "关闭" ])
plt.plot(results.fittedvalues, color= 'red' )

我们现在检查模型的验证

length = int(len(df_log) * 0.66)int ( len (df_log) * 0.66 ) 
train_arima = df_log[ "Close" ][: length]
test_arima = df_log[ "Close" ][length: ]
history = [x for x in train_arima]
预测 = list ()
originals = list ()
error_list = list ()


for i in range ( len (test_arima)):
warnings.filterwarnings( "ignore" )
模型 = sm.tsa.arima.ARIMA(history, order=( 2 , 1 , 0))
结果 = model.fit()
output = results.forecast()
pred_value = output[ 0 ]
pred_value = np.exp(pred_value)
original_value = test_arima[i]
history.append(original_value)
original_value = np.exp(original_value)
error = (( abs (pred_value - original_value)) / original_value) * 100
error_list.append(error)
print ( '预测 = %f, 预期 = %f, 错误 = %f ' % (pred_value, original_value, error), ' %' )
predictions.append( float (pred_value))
originals.append( float (original_value))

最后,predict函数可以用来做预测

文章来源投稿,发布:Yori;文章内容仅供参考,不构成投资建议;投资者据此操作,风险自担;如若转载,请注明出处:http://www.910btc.com/1846.html

发表评论

邮箱地址不会被公开。 必填项已用*标注