人工智能在金融领域的应用(Python)
人工智能在金融领域的应用(Python)
从上海证券交易所和深圳证券交易所分别自选1家上市公司,下载2018年6月1日-2023年5月31日的日度交易行情信息:开盘价、最低价、最高价、收盘价、成交量和成交金额,进行下列数据分析实验
画出两支股票全样本日收盘价和成交金额时间序列图
问题解决方案
在国泰安数据库下载好必要的数据之后,用pandas读入数据,以日期作为x轴,以收盘价和成交金额分别作为y1,和y2,通过matploylib画出双轴图。其中由于成交金额与收盘价差别过大,为了展示美观,将成交金额单位由“元”转换为“千万元”。
代码
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif']=[u'SimHei']
mpl.rcParams['axes.unicode_minus']=False#显示负号
#读入数据
s_601985=pd.read_csv('D:/Python程序/人工智能/大作业/601985.csv',index_col=1,parse_dates=True)
s_000037=pd.read_csv('D:/Python程序/人工智能/大作业/000037.csv',index_col=1,parse_dates=True)
#x轴和y1、y2轴
x1=s_000037.index
x2=s_601985.index
y1_c=s_000037['Clsprc']
y1_d=s_000037['Dnvaltrd']/10000000
y2_c=s_601985['Clsprc']
y2_d=s_601985['Dnvaltrd']/10000000
#第一张图
fig,ax1=plt.subplots(figsize=(9,6))#用左侧纵坐标绘图
plt.plot(x1,y1_c,label='收盘价(单位:元)',color='r')
plt.ylabel(u'金额(元)',fontsize=13)
plt.legend(loc=2, fontsize=13)#图例位置在左上方
ax2=ax1.twinx()#用右侧纵坐标绘图
plt.plot(y1_d,label='成交金额(单位:千万元)',linestyle=':')
plt.ylabel(u'金额(千万元)',fontsize=13)
plt.legend(loc=1, fontsize=13)#图例位置在右上方
plt.title('601985的收盘价和成交金额时间序列图', fontsize=13)
plt.show()
#第二张图
fig2,ax11=plt.subplots(figsize=(9,6))#用左侧纵坐标绘图
plt.plot(x2,y2_c,label='收盘价(单位:元)',color='r')
plt.ylabel(u'金额(元)',fontsize=13)
plt.legend(loc=2, fontsize=13)#图例位置在左上方
ax2=ax11.twinx()#用右侧纵坐标绘图
plt.plot(y2_d,label='成交金额(单位:千万元)',linestyle=':')
plt.ylabel(u'金额(千万元)',fontsize=13)
plt.legend(loc=1, fontsize=13)#图例位置在右上方
plt.title('000037的收盘价和成交金额时间序列图', fontsize=13)
plt.show()
结果

使用日度交易行情信息构造3个特征,要求说明:构造3个特征的理由,构造方法,画出时间序列图。
问题解决方案
构造的3个特征:
(1) 指数加权移动平均
选择移动平均的目的是过滤掉时间序列中的高频扰动,保留有用的低频趋势。指数加权移动平均相比简单移动平均是给数值赋予了不同的权重,权重按指数递减。指数移动平均由于对近期的数据赋予了更高的权重,因此它对近期的变化更加敏感。
构造方法是利用pandas库中自带的计算指数加权移动平均的ewm()函数;
(2)动量
选择动量的原因在于其显示的是一段时间内价格变动的速度,以帮助投资者判断趋势的强弱。动量衡量股价的涨跌速度。对于趋势分析来说,动量是衡量问题价格强弱的有用指标。
构造方法是将30天的移动窗口的对数收益率取滑动均值;
(3)滚动波动率
选择滚动波动率的原因是在股票投资市场上除了收益,人们还十分关心风险。股票的波动率衡量了在特定时间内收益率的变化。常常将一只股票的波动率和另一只股票比较,以寻找风险较小的股票;或是将之与市场指数比较,来检查股票在整个市场上的波动。一般来说,波动率越高,该股票的投资风险更大,人们就会选择投资其他股票。
构造方法是将30天的移动窗口的对数收益率取滑动标准差。
代码
def add_features(df,window=30):
'''增加更多特征'''
df['ewm']=pd.DataFrame(df['Clsprc']).ewm(alpha=0.5).mean()
df['r'] = np.log(df['Clsprc'] / df['Clsprc'].shift())
df['mom'] = df['r'].rolling(window).mean()#动量
df['vol'] = df['r'].rolling(window).std()#滚动波动率
df.dropna(inplace=True)
df['d'] = np.where(df['r'] > 0, 1, 0)#当日收益率方向
return df
s_000037=add_features(s_000037)
s_601985=add_features(s_601985)
#可视化新增加特征的时间序列图
x1=s_000037.index
y1_0=s_000037['ewm']
y2_0=s_000037['mom']
y3_0=s_000037['vol']
x2=s_601985.index
y1_6=s_601985['ewm']
y2_6=s_601985['mom']
y3_6=s_601985['vol']
#第一张图
plt.plot(x1,y1_0,label='指数加权移动平均')
plt.plot(x1,y2_0,label='动量',linestyle=':')
plt.plot(x1,y3_0,label='滚动波动率',linestyle='-')
plt.title('000037新增三个特征的时间序列图', fontsize=13)
plt.legend(fontsize=15)
plt.show()
#第二张图
plt.plot(x2,y1_6,label='指数加权移动平均')
plt.plot(x2,y2_6,label='动量',linestyle=':')
plt.plot(x2,y3_6,label='滚动波动率',linestyle='-')
plt.title('601985新增三个特征的时间序列图', fontsize=13)
plt.legend(fontsize=15)
plt.show()
结果


上图是两支股票新增加的三个特征——指数加权平均、动量和滚动波动率的时间序列图。从图中可以看出股票000037的指数加权平均要更高。同时相比指数加权平均,动量和滚动波动率的数值要更低,均在0左右。
使用日度行情信息和构造的特征,使用OLS、密集神经网络、循环神经网络对市场弱式效率进行检验
问题解决方案
(1)首先定义add_lags()函数将日度行情信息和构造的特征滞后5天;
(2)其次以8:2的比例划分训练集和测试集,同时定义了cw()函数处理使用深度循环网络中出现的类别不平衡问题;
(3)将新增了特征之后的数据中的收益率作为因变量,滞后5天的日度行情以及构造的特征作为自变量,运用numpy库中的linalg.lstsq()函数和tensorflow的keras库分别对其进行OLS回归,和使用密集神经网络以及循环神经网络模型进行拟合;
(4)通过判断测试集的准确率来判断是否出现统计失效,即能够以一定的优势预测未来价格的走势,以此判断市场是否是弱式有效市场。
代码
lags=5 #5天滞后
def add_lags(df,lags):
'''增加滞后项'''
cols = []
features = ['Opnprc', 'Hiprc', 'Loprc', 'Clsprc', 'Dnshrtrd',
'Dnvaltrd','ewm', 'mom', 'vol']
for f in features:
for lag in range(1, lags + 1):
col = f'{f}_lag_{lag}'
df[col] = df[f].shift(lag)
cols.append(col)
df.dropna(inplace=True)
return df, cols
s_000037,cols_000037=add_lags(s_000037, lags)
s_601985,cols_601985=add_lags(s_601985, lags)
#OLS回归
from sklearn.metrics import accuracy_score
a=0
reg = np.linalg.lstsq(s_000037[cols_000037],s_000037['r'], rcond=-1)[a] #OLS回归
pred = np.dot(s_000037[cols_000037], reg) #模型预测
acc_ols = accuracy_score(np.sign(s_000037['r']), np.sign(pred)) #准确率分析
def cw(df):
'''类别不平衡'''
c0, c1 = np.bincount(df['d'])
w0 = (1 / c0) * (len(df)) / 2
w1 = (1 / c1) * (len(df)) / 2
return {0: w0, 1: w1}
#使用DNN
import random
import logging
import tensorflow as tf
from tensorflow.keras.layers import Dense
from tensorflow.keras.models import Sequential
from tensorflow.keras.optimizers import Adam
from sklearn.metrics import accuracy_score
tf.get_logger().setLevel(logging.ERROR)
def set_seeds(seed=100):
random.seed(seed) #设定Python随机数种子
np.random.seed(seed) #设定Numpy随机数种子
tf.random.set_seed(seed) #设定TensorFlow随机数种子
optimizer = Adam(learning_rate=0.001) #默认优化器
def create_model(hl=1, hu=128, optimizer=optimizer):
model = Sequential()
model.add(Dense(hu, input_dim=len(cols_000037),
activation='relu')) #第1层
for _ in range(hl):
model.add(Dense(hu, activation='relu')) #中间层
model.add(Dense(1, activation='sigmoid')) #输出层
model.compile(loss='binary_crossentropy', #损失函数
optimizer=optimizer, #使用的优化器
metrics=['accuracy']) #要收集的其它指标
return model
set_seeds()
model = create_model(hl=1, hu=128)
split = int(len(s_000037) * 0.8) #数据集拆分
train = s_000037.iloc[:split].copy() #训练集
test = s_000037.iloc[split:].copy() #测试集
h = model.fit(train[cols_000037], train['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train))
acc_dnn=model.evaluate(test[cols_000037], test['d'])[1] #样本外评估性能
#RNN
from tensorflow.keras.preprocessing.sequence import TimeseriesGenerator
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import SimpleRNN, LSTM, Dense
symbol = 'Clsprc'
p = s_000037[symbol].values
p = p.reshape((len(p), -1))#数据重塑为2维
def create_rnn_model(hu=100, lags=lags, layer='SimpleRNN',
features=1, algorithm='estimation'):
model = Sequential()
#增加一个SimpleRNN层或LSTM层
if layer == 'SimpleRNN':
model.add(SimpleRNN(hu, activation='relu',
input_shape=(lags, features)))
else:
model.add(LSTM(hu, activation='relu',
input_shape=(lags, features)))
#增加一个用于估计或分类的输出层
if algorithm == 'estimation':
model.add(Dense(1, activation='linear'))
model.compile(optimizer='adam', loss='mse', metrics=['mae'])
else:
model.add(Dense(1, activation='sigmoid'))
model.compile(optimizer='adam', loss='binary_crossentropy',
metrics=['accuracy'])
return model
g = TimeseriesGenerator(train.values, train['r'].values, length=lags, batch_size=5)
set_seeds()
model = create_rnn_model(hu=100,
features=len(s_000037.columns),layer='SimpleRNN')
model.fit(g, epochs=100, steps_per_epoch=10,verbose=False)
g_ = TimeseriesGenerator(test.values, test['r'].values,
length=lags, batch_size=5)
y = model.predict(g_).flatten()
acc_rnn=accuracy_score(np.sign(test['r'].iloc[lags:]), np.sign(y))
print('RNN_Accuracy',acc_rnn)
print('OLS_Accuracy:',acc_ols)
print('DNN_Accuracy:',acc_dnn)
print('RNN_Accuracy:',acc_rnn)
结果

601985

000037
通过上图我们可以看出,三种方法得到的准确率都只在50%左右,其中股票000037的准确率略高一点,但是二者的预测效果一般。并没有达到60%这样能够以一定的优势预测股票价格未来的走势方向,即没有在市场上发现统计失效的现象。而弱式有效市场的定义就是当前价格已经反映了历史的信息,我们无法利用技术手段获取超额收益,而上述三种方法的准确率也证明了市场是弱式有效的。
使用日度行情信息和构造的特征,使用OLS、密集神经网络、循环神经对股票价格周度、月度变化方向进行预测,并根据预测构建投资组合,给出投资组合业绩表现:收益率、贝塔值、夏普比率。投资组合构建可以使用无风险投资,无风险年利率等于2%。
问题解决方案
(1) 首先对数据重新按一周和一月重新采样生成周度数据和月度数据;
(2) 其次再使用密集神经网络、循环神经对股票价格周度、月度变化方向进行预测;
(3) 由于OLS本质上是一种针对因变量的数值预测方法,适用于解释因变量与自变量之间的线性关系,不太适用分类问题,即股票价格方向的预测。因此本文使用OLS预测股票收益率;
(4) 针对股票价格变动方向的预测,构建投资权重为0.5:0.5的投资组合,根据预测的价格变化构建投资策略:如果预测该股价格上升,则对其进行买入;否则就投资无风险产品获得无风险收益(将无风险收益年利率转换为对应周期的利率),并根据两只股票的买卖方向计算组合的实际收益率;
(5) 针对股票收益率的预测,构建投资权重为0.5:0.5的投资组合,根据预测的收益率计算组合的期望收益率:如果期望收益率大于对应周期的无风险收益率,则对其进行买入;否则就投资无风险产品获得无风险收益,并计算实际收益率;
(6) 读取同时段的周度和月度市场指数数据计算收益率,与投资组合的收益率一起,定义calculate_beta()函数计算贝塔值:股票和市场指数的协方差/市场指数的方差;
(7) 使用投资组合的收益率和转换后的无风险利率计算夏普比率:(收益减无风险利率)/标准差。
代码
def refresh_data():
s_601985=pd.read_csv('D:/Python程序/人工智能/大作业/601985.csv',index_col=1,parse_dates=True)
s_000037=pd.read_csv('D:/Python程序/人工智能/大作业/000037.csv',index_col=1,parse_dates=True)
s_000037=add_features(s_000037)
s_000037,cols_000037=add_lags(s_000037, lags)
s_601985=add_features(s_601985)
s_601985,cols_601985=add_lags(s_601985, lags)
###针对000037
# 构造周度数据
weekly_data_0 = s_000037.resample('W').last() # 假设每周的数据取最后一天作为代表
weekly_data_0['r'] = np.log(weekly_data_0 ['Clsprc'] / weekly_data_0 ['Clsprc'].shift())
weekly_data_0 .dropna(inplace=True)
# 构造月度数据
monthly_data_0 = s_000037.resample('M').last() # 假设每月的数据取最后一天作为代表
monthly_data_0 ['r'] = np.log(monthly_data_0 ['Clsprc'] /monthly_data_0 ['Clsprc'].shift())
monthly_data_0 .dropna(inplace=True)
#划分训练集、测试集
split_0_w = int(len(weekly_data_0 ) * 0.8) #数据集拆分
train_0_w = weekly_data_0 .iloc[:split_0_w].copy() #训练集
test_0_w = weekly_data_0 .iloc[split_0_w :].copy() #测试集
split_0_m = int(len(monthly_data_0 ) * 0.8) #数据集拆分
train_0_m = monthly_data_0 .iloc[:split_0_m].copy() #训练集
test_0_m = monthly_data_0 .iloc[split_0_m :].copy() #测试集
#####针对601985
# 构造周度数据
weekly_data_6 = s_601985.resample('W').last() # 假设每周的数据取最后一天作为代表
weekly_data_6['r'] = np.log(weekly_data_6 ['Clsprc'] / weekly_data_6 ['Clsprc'].shift())
weekly_data_6 .dropna(inplace=True)
# 构造月度数据
monthly_data_6 = s_601985.resample('M').last() # 假设每月的数据取最后一天作为代表
monthly_data_6 ['r'] = np.log(monthly_data_6 ['Clsprc'] /monthly_data_6['Clsprc'].shift())
monthly_data_6 .dropna(inplace=True)
#划分训练集、测试集
split_6_w= int(len(weekly_data_6 ) * 0.8) #数据集拆分
train_6_w= weekly_data_6.iloc[:split_6_w].copy() #训练集
test_6_w = weekly_data_6.iloc[split_6_w:].copy() #测试集
split_6_m= int(len(monthly_data_6 ) * 0.8) #数据集拆分
train_6_m= monthly_data_6.iloc[:split_6_m].copy() #训练集
test_6_m = monthly_data_6.iloc[split_6_m:].copy() #测试集
return train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m
def output_OLS():
#用OLS回归
a=0
reg_0_w= np.linalg.lstsq(train_0_w [cols_000037],train_0_w ['r'], rcond=-1)[a] #OLS回归
pred_000037_w = np.dot(test_0_w [cols_000037], reg_0_w) #模型预测
reg_6_w = np.linalg.lstsq(train_6_w[cols_601985],train_6_w['r'], rcond=-1)[a] #OLS回归
pred_601985_w = np.dot(test_6_w[cols_000037], reg_6_w) #模型预测
reg_0_m= np.linalg.lstsq(train_0_m [cols_000037],train_0_m ['r'], rcond=-1)[a] #OLS回归
pred_000037_m = np.dot(test_0_m [cols_000037], reg_0_m) #模型预测
reg_6_m = np.linalg.lstsq(train_6_m[cols_601985],train_6_m['r'], rcond=-1)[a] #OLS回归
pred_601985_m = np.dot(test_6_m[cols_601985], reg_6_m) #模型预测
#构建投资组合——周度 portfolio_w=pd.concat([pd.DataFrame(pred_601985_w),pd.DataFrame(pred_000037_w)],axis=1)
portfolio_w.columns=['601985','000037']
portfolio_w['r_w_predict']=0.5*pred_601985_w+0.5*pred_000037_w
portfolio_w['r_w_true']=[i for i in 0.5*test_0_w['r']+0.5*test_6_w['r']]
#投资策略
M_w=1
r_w=0.02/360*7#把无风险年利率转换为周利率
r_d_w=[]#存放收益
for i in range(len(portfolio_w)):
if portfolio_w['r_w_predict'][i] <= r_w:
M_w=M_w*(1+r_w)
r_d_w.append(r_w)
else:
M_w=M_w*(1+portfolio_w['r_w_true'][i])
r_d_w.append(portfolio_w['r_w_true'][i])
port_ols_w=M_w-1
portfolio_w['r_d_w']=r_d_w
#构建投资组合——月度
portfolio_m=pd.concat([pd.DataFrame(pred_601985_m),pd.DataFrame(pred_000037_m)],axis=1)
portfolio_m.columns=['601985','000037']
portfolio_m['r_m_predict']=0.5*pred_601985_m+0.5*pred_000037_m
portfolio_m['r_m_true']=[i for i in 0.5*test_0_m['r']+0.5*test_6_m['r']]
#投资策略
M_m=1
r_m=0.02/12#把无风险年利率转换为月利率
r_d_m=[]
for i in range(len(portfolio_m)):
if portfolio_m['r_m_predict'][i] <= r_m:
M_m=M_m*(1+r_m)
r_d_m.append(M_m-1)
else:
M_m=M_m*(1+portfolio_m['r_m_true'][i])
r_d_m.append(M_m-1)
port_ols_m=M_m-1
portfolio_m['r_d_m']=r_d_m
#读取同时段指数信息
index=pd.read_csv('D:/Python程序/人工智能/大作业/指数.csv',index_col=0,parse_dates=True)
weekly_index=index.resample('W').last()
monthly_index=index.resample('M').last()
weekly_index['r']=np.log(weekly_index['Clsindex'] / weekly_index['Clsindex'].shift())
weekly_index.dropna(inplace=True)
monthly_index['r']=np.log(monthly_index['Clsindex'] /monthly_index['Clsindex'].shift())
monthly_index.dropna(inplace=True)
weekly_index=weekly_index.iloc[192:]
monthly_index=monthly_index.iloc[46:]
#计算贝塔值
def calculate_beta(stock_returns, market_returns):
# 计算股票和市场的协方差
covariance = np.cov(stock_returns, market_returns)[0, 1]
# 计算市场的方差
market_variance = np.var(market_returns)
# 计算股票的贝塔系数
beta = covariance / market_variance
return beta
beta_w=calculate_beta(portfolio_w['r_d_w'],weekly_index['r'])
beta_m=calculate_beta(portfolio_m['r_d_m'],monthly_index['r'])
#计算夏普比率
sharpe_ratio_w = (portfolio_w['r_d_w'].mean() - r_w) / portfolio_w['r_d_w'].std()
sharpe_ratio_m = (portfolio_m['r_d_m'].mean() - r_m) / portfolio_m['r_d_m'].std()
#输出结果
print('周度贝塔值:',beta_w)
print('周度夏普比率:',sharpe_ratio_w)
print('周度收益:',port_ols_w)
print('--------------------------------------------------------')
print('月度贝塔值:',beta_m)
print('月度贝夏普比率:',sharpe_ratio_m)
print('月度收益:',port_ols_m)
def output_DNN():
#用DNN
set_seeds()
model = create_model(hl=1, hu=128)
model.fit(train_0_w [cols_000037],train_0_w ['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_000037_w = model.predict(test_0_w[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128)
model.fit(train_6_w[cols_601985],train_6_w['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_601985_w = model.predict(test_6_w[cols_601985]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128)
model.fit(train_0_m [cols_000037],train_0_m ['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_000037_m = model.predict(test_0_m[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128)
model.fit(train_6_m[cols_601985],train_6_m['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_601985_m = model.predict(test_6_m[cols_601985]) #模型预测
#投资策略——周度
portfolio_w=pd.concat([pd.DataFrame(pred_601985_w),pd.DataFrame(pred_000037_w),pd.DataFrame(np.array(test_0_w['r'])),pd.DataFrame(np.array(test_6_w['r']))],axis=1,ignore_index=True)
portfolio_w.columns=['601985','000037','601985r','000037r']
M_w=1
r_w=0.02/360*7#把无风险年利率转换为周利率
r_d_w=[]#存放收益
for i in range(len(portfolio_w)):
if portfolio_w['601985'][i]==1:
r1=portfolio_w['601985r'][i]
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_w*0.5
else:
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r_w*0.5+r2*0.5
else:
r=r_w
M_w=M_w*(r+1)
r_d_w.append(r)
port_return_w=M_w-1
portfolio_w['r_d_w']=r_d_w
#构建投资组合——月度
portfolio_m=pd.concat([pd.DataFrame(pred_601985_m),pd.DataFrame(pred_000037_m),pd.DataFrame(np.array(test_0_m['r'])),pd.DataFrame(np.array(test_6_m['r']))],axis=1)
portfolio_m.columns=['601985','000037','601985r','000037r']
#投资策略
M_m=1
r_m=0.02/12#把无风险年利率转换为月利率
r_d_m=[]
for i in range(len(portfolio_m)):
if portfolio_m['601985'][i]==1:
r1=portfolio_m['601985r'][i]
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_m*0.5
else:
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r_m*0.5+r2*0.5
else:
r=r_m
M_m=M_m*(r+1)
r_d_m.append(r)
port_return_m=M_m-1
portfolio_m['r_d_m']=r_d_m
#读取同时段指数信息
index=pd.read_csv('D:/Python程序/人工智能/大作业/指数.csv',index_col=0,parse_dates=True)
weekly_index=index.resample('W').last()
monthly_index=index.resample('M').last()
weekly_index['r']=np.log(weekly_index['Clsindex'] / weekly_index['Clsindex'].shift())
weekly_index.dropna(inplace=True)
monthly_index['r']=np.log(monthly_index['Clsindex'] /monthly_index['Clsindex'].shift())
monthly_index.dropna(inplace=True)
weekly_index=weekly_index.iloc[192:]
monthly_index=monthly_index.iloc[46:]
#计算贝塔值
def calculate_beta(stock_returns, market_returns):
# 计算股票和市场的协方差
covariance = np.cov(stock_returns, market_returns)[0, 1]
# 计算市场的方差
market_variance = np.var(market_returns)
# 计算股票的贝塔系数
beta = covariance / market_variance
return beta
beta_w=calculate_beta(portfolio_w['r_d_w'],weekly_index['r'])
beta_m=calculate_beta(portfolio_m['r_d_m'],monthly_index['r'])
#计算夏普比率
sharpe_ratio_w = (portfolio_w['r_d_w'].mean() - r_w) / portfolio_w['r_d_w'].std()
sharpe_ratio_m = (portfolio_m['r_d_m'].mean() - r_m) / portfolio_m['r_d_m'].std()
#输出结果
print('周度贝塔值:',beta_w)
print('周度夏普比率:',sharpe_ratio_w)
print('周度收益:',port_return_w)
print('--------------------------------------------------------')
print('月度贝塔值:',beta_m)
print('月度贝夏普比率:',sharpe_ratio_m)
print('月度收益:',port_return_m)
def output_RNN(): train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
set_seeds()
model_0_w = create_rnn_model(hu=50,features=len(cols_000037),layer='LSTM',algorithm='classification')
g_0_w = TimeseriesGenerator(train_0_w[cols_000037].values,train_0_w['d'].values,length=lags, batch_size=5)
model_0_w.fit(g_0_w, epochs=5,steps_per_epoch=10,verbose=False,class_weight=cw(train_0_w))
g_0_w_ =TimeseriesGenerator(test_0_w[cols_000037].values,test_0_w['d'].values, length=lags, batch_size=5)
pred_000037_w=np.where(model_0_w.predict(g_0_w_) > 0.5,1, 0).flatten()
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
set_seeds()
model_0_m = create_rnn_model(hu=50,features=len(cols_000037),layer='LSTM',algorithm='classification')
g_0_m = TimeseriesGenerator(train_0_m[cols_000037].values,train_0_m['d'].values,length=lags, batch_size=5)
model_0_m.fit(g_0_m, epochs=5,steps_per_epoch=10,verbose=False,class_weight=cw(train_0_m))
g_0_m_ =TimeseriesGenerator(test_0_m[cols_000037].values,test_0_m['d'].values, length=lags, batch_size=5)
pred_000037_m=np.where(model_0_m.predict(g_0_m_) > 0.5,1, 0).flatten()
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
set_seeds()
model_6_w = create_rnn_model(hu=50,features=len(cols_000037),layer='LSTM',algorithm='classification')
g_6_w = TimeseriesGenerator(train_6_w[cols_000037].values,train_6_w['d'].values,length=lags, batch_size=5)
model_6_w.fit(g_6_w, epochs=5,steps_per_epoch=10,verbose=False,class_weight=cw(train_6_w))
g_6_w_ =TimeseriesGenerator(test_6_w[cols_000037].values,test_6_w['d'].values, length=lags, batch_size=5)
pred_601985_w=np.where(model_6_w.predict(g_6_w_) > 0.5,1, 0).flatten()
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
set_seeds()
model_6_m = create_rnn_model(hu=50,features=len(cols_000037),layer='LSTM',algorithm='classification')
g_6_m = TimeseriesGenerator(train_6_m[cols_000037].values,train_6_m['d'].values,length=lags, batch_size=5)
model_6_m.fit(g_6_m, epochs=5,steps_per_epoch=10,verbose=False,class_weight=cw(train_6_m))
g_6_m_ =TimeseriesGenerator(test_6_m[cols_000037].values,test_6_m['d'].values, length=lags, batch_size=5)
pred_601985_m=np.where(model_6_m.predict(g_6_m_) > 0.5,1, 0).flatten()
#投资策略——周度 portfolio_w=pd.concat([pd.DataFrame(pred_601985_w),pd.DataFrame(pred_000037_w),pd.DataFrame(np.array(test_0_w['r']))[0:44],pd.DataFrame(np.array(test_6_w['r']))[0:44]],axis=1,ignore_index=True)
portfolio_w.columns=['601985','000037','601985r','000037r']
M_w=1
r_w=0.02/360*7#把无风险年利率转换为周利率
r_d_w=[]#存放收益
for i in range(len(portfolio_w)):
if portfolio_w['601985'][i]==1:
r1=portfolio_w['601985r'][i]
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_w*0.5
else:
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r_w*0.5+r2*0.5
else:
r=r_w
M_w=M_w*(r+1)
r_d_w.append(r)
port_return_w=M_w-1
portfolio_w['r_d_w']=r_d_w
#构建投资组合——月度 portfolio_m=pd.concat([pd.DataFrame(pred_601985_m),pd.DataFrame(pred_000037_m),pd.DataFrame(np.array(test_0_m['r']))[0:7],pd.DataFrame(np.array(test_6_m['r']))[0:7]],axis=1)
portfolio_m.columns=['601985','000037','601985r','000037r']
#投资策略
M_m=1
r_m=0.02/12#把无风险年利率转换为月利率
r_d_m=[]
for i in range(len(portfolio_m)):
if portfolio_m['601985'][i]==1:
r1=portfolio_m['601985r'][i]
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_m*0.5
else:
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r_m*0.5+r2*0.5
else:
r=r_m
M_m=M_m*(r+1)
r_d_m.append(r)
port_return_m=M_m-1
portfolio_m['r_d_m']=r_d_m
#读取同时段指数信息
index=pd.read_csv('D:/Python程序/人工智能/大作业/指数.csv',index_col=0,parse_dates=True)
weekly_index=index.resample('W').last()
monthly_index=index.resample('M').last()
weekly_index['r']=np.log(weekly_index['Clsindex'] / weekly_index['Clsindex'].shift())
weekly_index.dropna(inplace=True)
monthly_index['r']=np.log(monthly_index['Clsindex'] /monthly_index['Clsindex'].shift())
monthly_index.dropna(inplace=True)
weekly_index=weekly_index.iloc[192:][0:44]
monthly_index=monthly_index.iloc[46:][0:7]
#计算贝塔值
def calculate_beta(stock_returns, market_returns):
# 计算股票和市场的协方差
covariance = np.cov(stock_returns, market_returns)[0, 1]
# 计算市场的方差
market_variance = np.var(market_returns)
# 计算股票的贝塔系数
beta = covariance / market_variance
return beta
beta_w=calculate_beta(portfolio_w['r_d_w'],weekly_index['r'])
beta_m=calculate_beta(portfolio_m['r_d_m'],monthly_index['r'])
#计算夏普比率
sharpe_ratio_w = (portfolio_w['r_d_w'].mean() - r_w) / portfolio_w['r_d_w'].std()
sharpe_ratio_m = (portfolio_m['r_d_m'].mean() - r_m) / portfolio_m['r_d_m'].std()
#输出结果
print('周度贝塔值:',beta_w)
print('周度夏普比率:',sharpe_ratio_w)
print('周度收益:',port_return_w)
print('----------------------------------------------------')
print('月度贝塔值:',beta_m)
print('月度贝夏普比率:',sharpe_ratio_m)
print('月度收益:',port_return_m)
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
output_OLS()
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
output_DNN()
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
output_RNN()
结果
上表一共展示了构建的六种投资组合的评估结果,分别使用OLS、DNN和RNN三种方法预测周度价格变化方向和月度价格变化方向所构建的投资组合的收益率、贝塔值和夏普比率。
整体来看,通过预测时间周期更短的周度数据比预测月度价格变化方向的收益率更高,而此中使用OLS预测的效果最好。但是如果考虑到市场波动率的话,通过预测月度数据构建的投资组合夏普比率更高,即在承担同等风险的情况下能够获得更高的超额收益,而此中使用OLS来进行预测效果最好。同时从表中还可以看出使用OLS预测月度价格变化构建的投资组合贝塔值为负数,说明此投资组合的价格波动与市场整体的价格波动方向相反。具体而言,贝塔值为负数意味着当市场整体下跌时,投资组合的价值可能上涨;而当市场整体上涨时,投资组合的价值可能下跌。可以将其视作一种避险资产。同时还可观察出三种方法中使用RNN来进行预测构建的投资组合效果最差。
总而言之,如果投资者只想追求高收益,那么使用OLS方法对每周的价格变化方向进行预测买卖会获得较高的收益;如果投资者承担的风险有限,不想一味追求高收益,只想尽可能地在承担一定的风险下获得更高地超额收益,那么推荐使用OLS方法对每月的价格变化方向进行预测,基于此进行买卖;如果投资者预测未来很长一段时期内市场的整体走向不会太好,而又想获得一定收益的话,推荐使用OLS方法对每月的价格变化方向预测而进行买卖。
虽然考虑了使用不同方法针对不同周期的价格进行预测构建投资组合,但是以上的六种投资组合都是等权重投资,如果更换不同的权重也许会找到表现更好的投资组合。同理,此次组合中只是由两项风险资产和一项无风险资产组成,增加更多数量的风险资产也可能会找到表现更好的投资组合。另外就是如果投资策略是根据价格涨跌的方向进行买卖,实际上即便是价格上涨,但如果收益率仍旧不如无风险收益率的话也不应该买入。因此如果是通过预测收益率与无风险收益率比较进行买卖也会对我们构建的投资组合有所改进,而上表也证明了这一点。
讨论归一化、正则化、装袋、优化方法对问题(4)结果影响
问题解决方案
(1) 将数据减去均值除以标准差及对其做高斯归一化,然后将处理过的数据再次使用OLS回归方法进行拟合,将所得结果与结果(4)作比较;
(2) 分别考虑正则化、装袋和优化器方法对DNN预测结果影响的改进,其中优化器选择’rmsprop’, ‘adagrad’, ‘adadelta’, ‘adam’, ‘adamax’, 'nadam’5种分别对结果进行预测,最后查看影响对比。
代码
#归一化
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
mu,std=train_0_w.mean(),train_0_w.std()
train_0_w=(train_0_w-mu)/std
mu,std=train_0_m.mean(),train_0_m.std()
train_0_m=(train_0_m-mu)/std
mu,std=train_6_w.mean(),train_6_w.std()
train_6_w=(train_6_w-mu)/std
mu,std=train_6_m.mean(),train_6_m.std()
train_6_m=(train_6_m-mu)/std
output_OLS()
#正则化
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
from tensorflow.keras.regularizers import l1, l2
def create_model(hl=1, hu=128, dropout=False, rate=0.3,regularize=False, reg=l1(0.0005),#正则化添加到每一层
optimizer=optimizer, input_dim=len(cols_000037)):
if not regularize:
reg = None
model = Sequential()
model.add(Dense(hu, input_dim=input_dim,
activity_regularizer=reg,
activation='relu'))
if dropout:
model.add(Dropout(rate, seed=100))
for _ in range(hl):
model.add(Dense(hu, activation='relu',activity_regularizer=reg)) #正则化添加到每一层
if dropout:
model.add(Dropout(rate, seed=100))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer=optimizer,
metrics=['accuracy'])
return model
set_seeds()
model = create_model(hl=1, hu=128, regularize=True)
model.fit(train_0_w [cols_000037],train_0_w ['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_000037_w = model.predict(test_0_w[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128, regularize=True)
model.fit(train_6_w[cols_601985],train_6_w['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_601985_w = model.predict(test_6_w[cols_601985]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128, regularize=True)
model.fit(train_0_m [cols_000037],train_0_m ['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_000037_m = model.predict(test_0_m[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128)
model.fit(train_6_m[cols_601985],train_6_m['d'],epochs=50, verbose=False,
validation_split=0.2, shuffle=False,class_weight=cw(train_0_w))
pred_601985_m = model.predict(test_6_m[cols_601985]) #模型预测
def output():
#投资策略——周度
portfolio_w=pd.concat([pd.DataFrame(pred_601985_w),pd.DataFrame(pred_000037_w),pd.DataFrame(np.array(test_0_w['r'])),pd.DataFrame(np.array(test_6_w['r']))],axis=1,ignore_index=True)
portfolio_w.columns=['601985','000037','601985r','000037r']
M_w=1
r_w=0.02/360*7#把无风险年利率转换为周利率
r_d_w=[]#存放收益
for i in range(len(portfolio_w)):
if portfolio_w['601985'][i]==1:
r1=portfolio_w['601985r'][i]
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_w*0.5
else:
if portfolio_w['000037'][i]==1:
r2=portfolio_w['000037r'][i]
r=r_w*0.5+r2*0.5
else:
r=r_w
M_w=M_w*(r+1)
r_d_w.append(r)
port_return_w=M_w-1
portfolio_w['r_d_w']=r_d_w
#构建投资组合——月度
portfolio_m=pd.concat([pd.DataFrame(pred_601985_m),pd.DataFrame(pred_000037_m),pd.DataFrame(np.array(test_0_m['r'])),pd.DataFrame(np.array(test_6_m['r']))],axis=1)
portfolio_m.columns=['601985','000037','601985r','000037r']
#投资策略
M_m=1
r_m=0.02/12#把无风险年利率转换为月利率
r_d_m=[]
for i in range(len(portfolio_m)):
if portfolio_m['601985'][i]==1:
r1=portfolio_m['601985r'][i]
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r1*0.5+r2*0.5
else:
r=r1*0.5+r_m*0.5
else:
if portfolio_m['000037'][i]==1:
r2=portfolio_m['000037r'][i]
r=r_m*0.5+r2*0.5
else:
r=r_m
M_m=M_m*(r+1)
r_d_m.append(r)
port_return_m=M_m-1
portfolio_m['r_d_m']=r_d_m
#读取同时段指数信息
index=pd.read_csv('D:/Python程序/人工智能/大作业/指数.csv',index_col=0,parse_dates=True)
weekly_index=index.resample('W').last()
monthly_index=index.resample('M').last()
weekly_index['r']=np.log(weekly_index['Clsindex'] / weekly_index['Clsindex'].shift())
weekly_index.dropna(inplace=True)
monthly_index['r']=np.log(monthly_index['Clsindex'] /monthly_index['Clsindex'].shift())
monthly_index.dropna(inplace=True)
weekly_index=weekly_index.iloc[192:]
monthly_index=monthly_index.iloc[46:]
#计算贝塔值
def calculate_beta(stock_returns, market_returns):
# 计算股票和市场的协方差
covariance = np.cov(stock_returns, market_returns)[0, 1]
# 计算市场的方差
market_variance = np.var(market_returns)
# 计算股票的贝塔系数
beta = covariance / market_variance
return beta
beta_w=calculate_beta(portfolio_w['r_d_w'],weekly_index['r'])
beta_m=calculate_beta(portfolio_m['r_d_m'],monthly_index['r'])
#计算夏普比率
sharpe_ratio_w = (portfolio_w['r_d_w'].mean() - r_w) / portfolio_w['r_d_w'].std()
sharpe_ratio_m = (portfolio_m['r_d_m'].mean() - r_m) / portfolio_m['r_d_m'].std()
#输出结果
print('周度贝塔值:',beta_w)
print('周度夏普比率:',sharpe_ratio_w)
print('周度收益:',port_return_w)
print('----------------------------------------------------')
print('月度贝塔值:',beta_m)
print('月度贝夏普比率:',sharpe_ratio_m)
print('月度收益:',port_return_m)
output()
#装袋
train_0_w,train_0_m,test_0_w,test_0_m,train_6_w,train_6_m,test_6_w,test_6_m=refresh_data()[0],refresh_data()[1],refresh_data()[2],refresh_data()[3],refresh_data()[4],refresh_data()[5],refresh_data()[6],refresh_data()[7]
from sklearn.ensemble import BaggingClassifier
from tensorflow.keras.wrappers.scikit_learn import KerasClassifier
max_features = 0.75
base_estimator = KerasClassifier(build_fn=create_model,verbose=False, epochs=20, hl=1, hu=128,
dropout=True, regularize=False,#基础估计器,这里是keras的Sequential模型的实例
input_dim=int(len(cols_000037) * max_features))
set_seeds()
model= BaggingClassifier(base_estimator=base_estimator,n_estimators=15,max_samples=0.75,max_features=max_features,
bootstrap=True,bootstrap_features=True,n_jobs=1,random_state=100)
model.fit(train_0_w [cols_000037],train_0_w ['d'])
pred_000037_w = model.predict(test_0_w[cols_000037]) #模型预测
set_seeds()
model= BaggingClassifier(base_estimator=base_estimator,n_estimators=15,max_samples=0.75,max_features=max_features,
bootstrap=True,bootstrap_features=True,n_jobs=1,random_state=100)
model.fit(train_6_w[cols_601985],train_6_w['d'])
pred_601985_w = model.predict(test_6_w[cols_601985]) #模型预测
set_seeds()
model=BaggingClassifier(base_estimator=base_estimator,n_estimators=15,max_samples=0.75,max_features=max_features,
bootstrap=True,bootstrap_features=True,n_jobs=1,random_state=100)
model.fit(train_0_m [cols_000037],train_0_m ['d'])
pred_000037_m = model.predict(test_0_m[cols_000037]) #模型预测
set_seeds()
model=BaggingClassifier(base_estimator=base_estimator,n_estimators=15,max_samples=0.75,max_features=max_features,
bootstrap=True,bootstrap_features=True,n_jobs=1,random_state=100)
model.fit(train_6_m[cols_601985],train_6_m['d'])
pred_601985_m = model.predict(test_6_m[cols_601985]) #模型预测
#优化器
optimizers = [ 'rmsprop', 'adagrad', 'adadelta', 'adam', 'adamax', 'nadam']
for optimizer in optimizers:
set_seeds()
model = create_model(hl=1, hu=128,dropout=True, rate=0.3,regularize=False,reg=l2(0.001),optimizer=optimizer) #为给定的优化器实例化DNN模型
model.fit(train_0_w [cols_000037],train_0_w ['d'],epochs=50, verbose=False,validation_split=0.2, shuffle=False,class_weight=cw(train_0_w)) #使用给定的优化器拟合模型
pred_000037_w = model.predict(test_0_w[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128,dropout=True, rate=0.3,regularize=False,reg=l2(0.001),optimizer=optimizer) #为给定的优化器实例化DNN模型
model.fit(train_0_m [cols_000037],train_0_m ['d'],epochs=50, verbose=False,validation_split=0.2, shuffle=False,class_weight=cw(train_0_m)) #使用给定的优化器拟合模型
pred_000037_m = model.predict(test_0_m[cols_000037]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128,dropout=True, rate=0.3,regularize=False,reg=l2(0.001),optimizer=optimizer) #为给定的优化器实例化DNN模型
model.fit(train_6_w [cols_601985],train_6_w ['d'],epochs=50, verbose=False,validation_split=0.2, shuffle=False,class_weight=cw(train_6_w)) #使用给定的优化器拟合模型
pred_601985_w = model.predict(test_6_w[cols_601985]) #模型预测
set_seeds()
model = create_model(hl=1, hu=128,dropout=True, rate=0.3,regularize=False,reg=l2(0.001),optimizer=optimizer) #为给定的优化器实例化DNN模型
model.fit(train_0_m [cols_601985],train_6_m ['d'],epochs=50, verbose=False,validation_split=0.2, shuffle=False,class_weight=cw(train_6_m)) #使用给定的优化器拟合模型
pred_601985_m = model.predict(test_6_m[cols_601985]) #模型预测
print('-----------',optimizer,'-----------')
output()
结果






通过表33-1可以看出使用高斯归一化对组合月度表现的提升更好,收益率大约提升了10%,夏普比率也增加了一倍。但是虽然月度表现提升,但是周度表现下降得很快。表34-1和表34-2显示相比装袋,正则化对基于DNN预测构建的投资组合效果更好。但是二者改进不多,甚至使用装袋使得组合的夏普比率为负,说明新的组合连无风险收益率都没有获得。投资者在承担了风险的同时并没有获得相应的报酬,因此在此种情况下不推荐使用此方法。图34-1图35-1和图35-2都是使用不同的优化器对预测结果的影响,可看出使用rmsprop和nadam对周度收益率的改善较好,提高了5个百分点。同时这两个优化器对周度组合的夏普比率提升效果也较好,原始的夏普比率为负、不推荐的组合经过使用rmsprop和nadam优化器夏普比率提升了十几个百分点,效果明显。
总而言之,针对此次构造的投资组合,推荐使用归一化对OLS月度预测做改进,效果较好。另外在优化器方面使用rmsprop和nadam对周度数据提升效果好。正则化的提升效果不明显,而装袋方法不适合此次构建的投资组合改进。
说明使用深度强化学习改进投资组合业绩表现的方法
- 状态表示:智能体的输入是市场相关信息,包括历史价格、财务指标、技术指标等。可以使用RNN或DNN来处理序列数据,并从中提取有用的特征。
- 动作空间:智能体的输出是对每个资产的权重。动作空间可以是连续的,例如使用多层感知机(MLP)输出每个资产的权重,并对权重进行适当的归一化。也可以将动作空间离散化,例如将权重限制在几个预定义的取值范围内。
- 构建强化学习模型:使用深度神经网络作为强化学习模型。输入状态,并输出对每个动作(即资产权重)的预测值。可以采用深度Q网络(DQN)或其他算法来训练模型。Q值网络用于评估给定状态下采取不同动作的长期收益,可以通过训练使其逐步优化。
- 训练算法:可以使用基于梯度的方法来训练智能体,例如使用随机梯度下降法(SGD)或其他优化算法。训练过程中一般使用经验回放技术,即将之前的经验存储在一个缓冲区中,并从中随机抽取样本进行训练,以使数据更加独立和稳定。
- 定义奖励函数:为了引导智能体学习,需要定义奖励函数。奖励函数可以基于投资组合业绩进行设计,例如根据收益率、波动率、最大回撤等指标来定义奖励,使得智能体优化投资组合的长期收益和风险之间的平衡。
- 确定交易策略:根据模型的输出(即资产权重),确定具体的交易策略,包括买入、卖出和持有等决策。
- 进行训练和优化:通过与环境(市场)的交互,使用强化学习算法对模型进行训练和优化。可以使用经验回放技术来平衡数据的相关性,提高训练效率和稳定性。
- 考虑风险控制:在实际应用中,需要综合考虑风险控制。可以设置止损、分散投资、限制单个资产权重等方式来管理投资组合的风险。
