好了,制度上的事,自有人会操心,我们只谈技术。
当我们在回测中取到满意的效果后,是不是一定能在实战也能取得好的收益呢?不一定的。因为回测我们用的是历史数据,可行情每天都在发展变化,每天都有新的事情发生,有句名言说:“每天的太阳都是新的。”所以,慎重起见,我们回测过后,有必要再进行一段时间的模拟交易,回测效果好,模拟效果也好,我们再投入实战。
另外,模拟交易,还可以检验一下代码有无问题,能否按设想下单,能否成交等等问题。

模拟交易,需要对回测代码做一点修改,毕竟它们用的数据是不同,回测是历史数据,而模拟是最新的即时行情。下面我们用“四周法则策略”来进行模拟交易。(如果你没看过我之前发的“四周法则策略”的文章,可以点击查看《学习QMT股票量化系统,四周法则策略》)
一、软件版本的选择
要进行模拟交易,我们有两个选择,一个是迅投官方试用版软件,因为是试用版,我们在策略运行时,选实盘模式,依然还是模拟交易。没有跟自己真实交易账户绑定,自然不会是真实交易,但据说目前试用期只有两个星期。
第二个选择是券商的QMT模拟交易软件,模拟交易无时间限制。在此软件上运行策略,依然要选择实盘模式,虽是实盘模式,但账号资金都是模拟的,赚钱也都只是“纸上富贵”。
为什么要运行在实盘模式而不是模拟模式呢?因为在模拟模式下,它只发出买卖信号,不下单交易。
只有运行在实盘模式下,买卖信号发生后,才会下单,成交。
QMT交易端模拟跟真正的实盘交易端,操作上没太大区别。
二、修改代码
首先我们要新建一个类。
class a():passA = a() #创建空的类的实例 用来保存委托状态
然后我们要把之前的变量,如stock、accID、MY_period等等,都改成A.stock、A.accID、A.MY_period。
再然后我们需要把C.get_market_data_ex()这个获取行情数据的函数参数做些修改,加上两句代码,end_time=bar_date(最新的K线数据),count = A.MY_period+1(A.MY_period=4,即四个交易日之前1天到最新的K线数据。)参数count是用来获取数据的数量。它决定从当前时间点向前回溯,需要获取多少根K线数据。
data = C.get_market_data_ex(['close', 'high', 'low'],[A.stock],end_time=bar_date,period=C.period,count = A.MY_period+1,dividend_type='none',subscribe = True)
四周法则模拟交易完整代码如下:
#encoding:gbk'''四周法则策略,股价大于前4日最高价,全仓买入,小于前4日最低价,全仓卖出注意:本策仅用于python量化学习,不用于真实交易'''import pandas as pdimport numpy as npclass a():passA = a() #创建空的类的实例 用来保存委托状态 def init(C):# 设置股票代码和账户IDA.stock= C.stockcode + '.' +C.marketA.accID = 'your accID'A.acct_type= "stock" A.waiting_list = [] #未查到委托列表 存在未查到委托情况暂停后续报单 防止超单# 设置周期A.MY_period = 4def handlebar(C):# 计算前4日最高价和最低价,及最新收盘价#跳过历史k线if not C.is_last_bar():returnbar_date = timetag_to_datetime(C.get_bar_timetag(C.barpos), '%Y%m%d%H%M%S') #当前k线日期data = C.get_market_data_ex(['close', 'high', 'low'],[A.stock],end_time=bar_date,period=C.period,count = A.MY_period+1,dividend_type='none',subscribe = True)close = data[A.stock]['close']high = data[A.stock]['high']low = data[A.stock]['low']HIGH_4 = pd.Series(high).rolling(window=A.MY_period).max() #计算四日最大值LOW_4 = pd.Series(low).rolling(window=A.MY_period).min() #计算四日最小值# 获取账户信息account_info = get_trade_detail_data(A.accID, A.acct_type, 'account')if not account_info:print("无法获取账户信息")returnaccount_info = account_info[0]available_cash = int(account_info.m_dAvailable) # 可用资金holdings = get_trade_detail_data(A.accID, 'stock', 'position')holdings = {i.m_strInstrumentID + '.' + i.m_strExchangeID : i.m_nVolume for i in holdings}holding_vol = holdings[A.stock] if A.stock in holdings else 0# 全仓买入逻辑if holding_vol == 0 and close[-1] > HIGH_4[-2]:print("此时超过了最高价!
")# 计算买入数量,向下取整buy_volume = available_cash // close[-1]# 下单买入passorder(23, 1101, A.accID, A.stock, 5, -1, buy_volume,1, C)print(f"{bar_date} 开仓")print("holding_vol=",holding_vol)C.draw_text(1, 1, '买')# 全仓卖出逻辑elif holding_vol > 0 and close.iloc[-1] < LOW_4.iloc[-2]:print("此时低于最低价!
")# 获取持仓信息position_info = get_trade_detail_data(A.accID, 'stock', 'position')if not position_info:print("无法获取持仓信息")return# 下单卖出passorder(24, 1101, A.accID, A.stock, 5, -1, holding_vol, 1,C)print(f"{bar_date} 平仓")C.draw_text(1, 1, '卖')holdings = get_trade_detail_data(A.accID, 'stock', 'position')holdings = {i.m_strInstrumentID + '.' + i.m_strExchangeID : i.m_nVolume for i in holdings}holding_vol = holdings[C.stock] if A.stock in holdings else 0print("现在持股数量为:",holding_vol)account_info = get_trade_detail_data(C.accID, 'stock', 'account')account_info = account_info[0]available_cash = int(account_info.m_dAvailable) # 可用资金print("可用资金为:",available_cash)
三、模拟交易
1、我们在QMT模拟交易端的主界面点击“模型交易”,然后选择我们已经修改了的“四周法则”
2、然后选择模拟交易账号,在运行周期中,我们选择了5分钟,主要是为了更快速地看到下单及成交效果,并非为了更好地盈利。这个运行周期要跟策略编辑页的运行周期一致。
3、选择"实盘"模式,再点“操作”下小三角按钮运行。
策略开始模拟运行,耐心等待交易信号的发生。
(先喝杯咖啡,然后站起来伸伸腰,看看窗外,嗯,这个世界是多么美好!
)
…… ……
交易信号终于出现了!
下单了,成交了,自动交易功能实现了。至于效益如何,那就需要更长的一段时间来验证了。
总结:今天最容易让人搞糊涂的是,说的是模拟,操作时又选择实盘模式,到底是模拟还是实盘啊?
是模拟,客户端是模拟端,账号是模拟账号,资金也是模拟资金,操作上选实盘模式,是因为模拟模式只提示买卖信号,不下单,实盘模式下会下单成交,但依然是模拟交易。
#头条创作挑战赛#