Statsmodels AutoRegression回测代码有效性
Statsmodels AutoRegression backtesting code validity
我正在使用统计模型库学习 Python 中的自回归模型。
我正在做的是获取一个数据集,该数据集显示来自此处的金融股票的 returns:
当我运行以下命令时,数据如下所示:
data['y'] = data['close'].shift(-1).astype(float)
data.dropna(inplace=True)
data.tail()
基本上,y 列是下一个时间步长的收盘价。我的数据集中总共有 500 个时间步。
现在我想拟合一个简单的 AR 模型,使用当前收盘价预测下一期收盘价。为了测试我的模型的适合度,我做了一个回测。
from statsmodels.tsa.arima_model import AutoReg
def backtest(num_periods, data):
predictions = []
true_values = []
x = data[['open', 'high', 'low', 'close']]
y = data['y']
for i in reversed(range(1, num_periods)):
# split the data into training and test splits
# the y_test variable should be a single value for the next period out of the sample
x_train = x.iloc[:len(x)-i]
y_train = y.iloc[:len(y)-i]
x_test = x.iloc[len(x)-i]
y_test = y.iloc[len(y)-i]
# fit the model on the endogenous variables
model = AutoReg(endog=x_train.close.astype(float), lags = 13).fit()
# forecast for the period out of the
pred = model.predict(start=len(x_train), end=len(x_train)+1)
# create the prediction and true value arrays
predictions.append(pred)
true_values.append(y_test)
return true_values, predictions
true, pred = backtest(10, data)
但这给了我两个预测系列:
plt.plot(true, label='true', );
plt.plot(pred, label = 'pred', );
plt.legend();
这是怎么回事?我回测 AR 模型的方法是否正确?我主要担心的是,我似乎是在 y 上训练模型,但 y 来自下一个时期。因此,当我预测样本外时,它会从测试集中获取一个值。
任何指导都将非常感谢代码示例。
这里有很多事情需要解决。
首先,不应该使用 Autoregressive model 来预测股票或任何高流动性市场。这是因为自回归模型会考虑第 n 个滞后的值,如果数据不是周期性的,它就没有用,我将进一步详细解释:
考虑 efficient market hypothesis,这表明市场会将所有已知信息考虑到资产价格中。对于预测,这意味着如果每个人都知道价格会在周二上涨和周五下跌,那么人们就会在周一买入并在周四卖出,从而使股价回到均衡状态。
如果您的目标是准确预测市场,已经有一些使用 LSTM 神经网络模型的尝试在这方面取得了一定的成功。
关于验证方法,它似乎没问题,但是有一种方法可以增加灵活性来验证代码,在每次迭代中,您可以直接为每次迭代获得带有验证指标的结果,所以在这种情况下您只需使用数据集和添加行数的测试大小,在本例中为天数。
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
def test_train_spl(data, testsize):
test = data.tail(testsize)
train = data.head(data.shape[0] - testsize)
return test, train
def walkforward_validation(data, test_start_date, test_end_date=None, step_size=15, testsize=15, model='SARIMA'):
test_start_date = pd.to_datetime(test_start_date)
current_max_date = test_start_date
modelling_results = pd.DataFrame(columns=['test_start', 'test_end', 'MAE', 'MAPE'])
if test_end_date is None:
test_end_date = data.index.max()
test_end_date = pd.to_datetime(test_end_date)
else:
test_end_date = pd.to_datetime(test_end_date)
while current_max_date < test_end_date:
data.index = pd.to_datetime(data.index)
iter_data = data[data.index <= current_max_date + timedelta(days=testsize)]
test, train = test_train_spl(iter_data, testsize=testsize)
# fit the model on the endogenous variables
model = AutoReg(endog=x_train.close.astype(float), lags = 13).fit()
# forecast for the period out of the
pred = model.predict(start=len(x_train), end=len(x_train)+1)
# create the prediction and true value arrays
mae=mean_absolute_error(y_test, pred)
mape=mean_absolute_error(y_test, pred)
iter_results = pd.DataFrame({'test_start': [current_max_date],'test_end': [current_max_date + timedelta(testsize)], 'MAE': [mae], 'MAPE': [mape]})
modelling_results = modelling_results.append(iter_results, ignore_index=True)
#add the step size to the current date analized and continue the while loop until it is over
current_max_date = current_max_date + timedelta(days=step_size)
return modelling_results
我正在使用统计模型库学习 Python 中的自回归模型。
我正在做的是获取一个数据集,该数据集显示来自此处的金融股票的 returns:
当我运行以下命令时,数据如下所示:
data['y'] = data['close'].shift(-1).astype(float)
data.dropna(inplace=True)
data.tail()
基本上,y 列是下一个时间步长的收盘价。我的数据集中总共有 500 个时间步。
现在我想拟合一个简单的 AR 模型,使用当前收盘价预测下一期收盘价。为了测试我的模型的适合度,我做了一个回测。
from statsmodels.tsa.arima_model import AutoReg
def backtest(num_periods, data):
predictions = []
true_values = []
x = data[['open', 'high', 'low', 'close']]
y = data['y']
for i in reversed(range(1, num_periods)):
# split the data into training and test splits
# the y_test variable should be a single value for the next period out of the sample
x_train = x.iloc[:len(x)-i]
y_train = y.iloc[:len(y)-i]
x_test = x.iloc[len(x)-i]
y_test = y.iloc[len(y)-i]
# fit the model on the endogenous variables
model = AutoReg(endog=x_train.close.astype(float), lags = 13).fit()
# forecast for the period out of the
pred = model.predict(start=len(x_train), end=len(x_train)+1)
# create the prediction and true value arrays
predictions.append(pred)
true_values.append(y_test)
return true_values, predictions
true, pred = backtest(10, data)
但这给了我两个预测系列:
plt.plot(true, label='true', );
plt.plot(pred, label = 'pred', );
plt.legend();
这是怎么回事?我回测 AR 模型的方法是否正确?我主要担心的是,我似乎是在 y 上训练模型,但 y 来自下一个时期。因此,当我预测样本外时,它会从测试集中获取一个值。
任何指导都将非常感谢代码示例。
这里有很多事情需要解决。 首先,不应该使用 Autoregressive model 来预测股票或任何高流动性市场。这是因为自回归模型会考虑第 n 个滞后的值,如果数据不是周期性的,它就没有用,我将进一步详细解释:
考虑 efficient market hypothesis,这表明市场会将所有已知信息考虑到资产价格中。对于预测,这意味着如果每个人都知道价格会在周二上涨和周五下跌,那么人们就会在周一买入并在周四卖出,从而使股价回到均衡状态。
如果您的目标是准确预测市场,已经有一些使用 LSTM 神经网络模型的尝试在这方面取得了一定的成功。
关于验证方法,它似乎没问题,但是有一种方法可以增加灵活性来验证代码,在每次迭代中,您可以直接为每次迭代获得带有验证指标的结果,所以在这种情况下您只需使用数据集和添加行数的测试大小,在本例中为天数。
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import mean_squared_error
def test_train_spl(data, testsize):
test = data.tail(testsize)
train = data.head(data.shape[0] - testsize)
return test, train
def walkforward_validation(data, test_start_date, test_end_date=None, step_size=15, testsize=15, model='SARIMA'):
test_start_date = pd.to_datetime(test_start_date)
current_max_date = test_start_date
modelling_results = pd.DataFrame(columns=['test_start', 'test_end', 'MAE', 'MAPE'])
if test_end_date is None:
test_end_date = data.index.max()
test_end_date = pd.to_datetime(test_end_date)
else:
test_end_date = pd.to_datetime(test_end_date)
while current_max_date < test_end_date:
data.index = pd.to_datetime(data.index)
iter_data = data[data.index <= current_max_date + timedelta(days=testsize)]
test, train = test_train_spl(iter_data, testsize=testsize)
# fit the model on the endogenous variables
model = AutoReg(endog=x_train.close.astype(float), lags = 13).fit()
# forecast for the period out of the
pred = model.predict(start=len(x_train), end=len(x_train)+1)
# create the prediction and true value arrays
mae=mean_absolute_error(y_test, pred)
mape=mean_absolute_error(y_test, pred)
iter_results = pd.DataFrame({'test_start': [current_max_date],'test_end': [current_max_date + timedelta(testsize)], 'MAE': [mae], 'MAPE': [mape]})
modelling_results = modelling_results.append(iter_results, ignore_index=True)
#add the step size to the current date analized and continue the while loop until it is over
current_max_date = current_max_date + timedelta(days=step_size)
return modelling_results