接上一篇文章(期货ML策略(二)构建机器学习模型),这篇文章开始对上一篇的结果进行回测分析。
上一篇文章中我简单的介绍了如何构建ML模型。当在实盘的时候,每隔一分钟我们可以获取到不同合约的实时数据(1分钟k线数据),然后构造需要的特征并将其输入模型中。模型会根据输入的特征输出20分钟后上涨概率,当达到预先设定的阈值时对其做多或做空。
在回测的过程中,为了加快回测的速度,我们只需要提前计算好在何时买入,何时卖出即可。考虑到当获得K线数据之后不能马上给出交易信号,并且存在一些时间差,所以回测的时候延后1分钟交易;即在第0分钟给出交易信号,第1分钟开仓,第20分钟平仓。因为目前考虑的是日内交易,所以策略会在尾盘清仓。
github中的Trian.ipynb程序会自动输出交易信号result.csv。回测过程中根据给定的交易信号进行交易。
因为期货交易中不同合约品种的手续费不太一样,所以这里我借助了天勤平台进行回测。
Step1 : 按时间顺序寻找交易信号,如果有交易信号则进入Step2,否则进入Step5
Step2 : 判断当前时间点是否开仓,如果当前时间点需要开仓,则进行开仓操作。如果当前时间点大于开仓时间,则回到Step1,否则进入Step3
Step3 : 遍历判断当前持仓是否达到平仓时间,如果是则平仓。然后进入Step4
Step4 : 如果当前时间是14点58分,清空所有仓位。然后回到Step1寻找新的交易信号
Step5 : 遍历判断当前持仓是否达到平仓时间,如果是则平仓。如果当前时间是14点58分,清空所有仓位,并结束回测程序。
Step1核心代码如下:
for trade_date, tmp_df in pred.groupby('datetime_open'):
# print(now_time_, now_time_ - trade_date)
# print(trade_date)
tmp_df = tmp_df[(tmp_df['pred'] > buying_prob)|(tmp_df['pred'] < selling_prob)]
flag = False # 判断是否有进行加减仓等一系列操作
if len(tmp_df) != 0:
trade_kind = list(tmp_df['ts_code'].values)
trade_prob = tmp_df['pred'].values
close_time = list(tmp_df['datetime_close'])
Step2核心代码如下:
# 进行做多或者做空操作
if pd.Timedelta(seconds=-15) < trade_date - now_time_ < pd.Timedelta(seconds=15):
for kind, prob, tmp_close_time in zip(trade_kind, trade_prob, close_time):
target_pos = TargetPosTask(api, kind)
hold_pos = api.get_position(kind).pos
if prob > buying_prob:
target_pos.set_target_volume(hold_pos + 1)
direction.append(1)
else:
target_pos.set_target_volume(hold_pos - 1)
direction.append(-1)
hold_kind.append(kind)
close_datetime.append(tmp_close_time)
# set_kind.add(kind)
print(kind, direction[-1], now_time_)
api.wait_update()
flag = True
trade_kind = []
trade_prob = []
# break
elif now_time_ - trade_date > pd.Timedelta(seconds=15):
break
Step3核心代码如下:
# 查看是否已满20分钟
while True:
if len(hold_kind) == 0:
break
# print(now_time-hold_time[0])
for i in range(len(hold_kind)-1, -1, -1):
if now_time_ - close_datetime[i] >= pd.Timedelta(seconds=-15):
target_pos = TargetPosTask(api, hold_kind[i])
hold_pos = api.get_position(hold_kind[i]).pos
if direction[i] == 1 and hold_pos != 0:
target_pos.set_target_volume(hold_pos - 1)
elif hold_pos != 0:
target_pos.set_target_volume(hold_pos + 1)
print('time end, 平1手 ' + hold_kind[i])
hold_kind.pop(i)
direction.pop(i)
close_datetime.pop(i)
api.wait_update()
flag = True
break
Step4核心代码如下:
# 当日清仓
if now_time_.hour == 14 and now_time_.minute >= 58:
# tmp_kind = []
# print(api._serials.items())
print(now_time_)
for tmp in set(hold_kind):
target_pos = TargetPosTask(api, tmp)
if target_pos != 0:
target_pos.set_target_volume(0)
print('清空 '+str(tmp))
api.wait_update()
flag = True
hold_kind = []
close_datetime = []
direction = []
回测时间:2019年9月1日->2020年4月20日
所有结果如下:
从结果上来看,策略能够勉强做到盈利,这也很正常,毕竟我才刚开始做,要是这么简单就做出来岂不是随随便便赚钱,相信再深究一些因子设计肯定会有更好的效果。从交易频率上看,可以发现很多时候都是没有进行交易的,这个可以根据涨跌概率排名来进行做多或做空。总之,这个简单的机器学习策略还是很有潜力的,毕竟目前的策略只是一个玩具策略,改进之后肯定有更难以想象的效果。
下一篇文章将会利用构建的模型进行模拟盘交易。
所有代码github:
https://github.com/wbbhcb/futures_strategy/tree/master/ML_Strategy
对量化、数据挖掘、深度学习感兴趣的可以关注公众号,本人不定期分享有关这些方面的研究。
个人知乎:
https://www.zhihu.com/people/e-zhe-shi-wo/activities