1. 现象见图中描述
1.1 这是接口的错误?
在cta_gateway.py中send_order()函数中,找到出错语句前增加下面的调试打印:
self.reqid += 1
print(f"ctp_req={ctp_req}") # 调试打印
self.reqOrderInsert(ctp_req, self.reqid)
得到ctp_req的内容如下:
ctp_req={
'InstrumentID': 'ag2012',
'ExchangeID': 'SHFE',
'LimitPrice': 6093.0,
'VolumeTotalOriginal': 8,
'OrderPriceType': '',
'Direction': '1',
'CombOffsetFlag': '3',
'OrderRef': '1',
'InvestorID': '147102',
'UserID': '147102',
'BrokerID': '9999',
'CombHedgeFlag': '1',
'ContingentCondition': '1',
'ForceCloseReason': '0',
'IsAutoSuspend': 0,
'TimeCondition': '3',
'VolumeCondition': '1',
'MinVolume': 1
}
这里面的内容只有最为可疑:
'OrderPriceType': '',
2. 为什么会出错?
2.1 停止单分为两种:
- 服务器停止单:需要交易所支持,直接可以发送服务器处理
- 本地停止单:交易所不支持,由本地应用来维护
2.2 CTA的网关目前只处理两类委托请求:
ORDERTYPE_VT2CTP = {
OrderType.LIMIT: THOST_FTDC_OPT_LimitPrice, # 限价类型
OrderType.MARKET: THOST_FTDC_OPT_AnyPrice # 市价类型
}
ORDERTYPE_CTP2VT = {v: k for k, v in ORDERTYPE_VT2CTP.items()}
2.3 用户的CTA策略的停止单是有CtaEngine维护的
用户的CTA策略发送委托停止单的过程:
- 调用CtaTemplate的send_order()
- 再调用CtaEngine引擎的send_order()
- CtaEngine引擎区分委托请求时 限价单还是停止单,
- CtaEngine引擎通过过请求中合约的contract,得知是否支持服务器停止单,如果支持直接调用main_engine中ctp_gateway发送到服务器,否则有引擎保存到本地进行维护
- CtaEngine引擎中的本地停止单被触发时,CtaEngine引擎把当触发停止单转化未涨停板或跌停板限价单,调用main_engine中ctp_gateway发送到服务器
- ctp_gateway对vnpy委托请求OrderRequest中的OrderType进行映射,得到接口识别的请求类型OrderPriceType,OrderPriceType目前只接受两个类型:THOST_FTDC_OPT_LimitPrice和THOST_FTDC_OPT_AnyPrice。
- 转化后委托请求ctp_req其实是个字典,然后通过交易接口TdApi发送给交易服务器
3. 假如你从Main_Window(主界面)直接发送停止单,问题就来 !
3.1 Main_Window直接发送停止单过程:
- 1 系统是直接调用ctp_gateway,它不识别服务器是否支持
- 2 系统它不会把该停止单发送到CtaEngine引擎,因为你可以压根就没有启动CtaEngine引擎模块,怎么调用?
- 3 委托请求OrderRequest中的OrderType='STOP',在ORDERTYPE_VT2CTP字典中就没有键值,产生出来的接口请求类型OrderPriceType=''
- 4 于是就出错啦!!!
3.2 结论:
目前在主界面中是不可以发送任何停止单的!!!
目前在主界面中是不可以发送任何停止单的!!!
目前在主界面中是不可以发送任何停止单的!!!
重要的话说三遍
4. 发送委托停止单出错的修改建议:
- 1 类型映射错误,就算是服务器停止单支持,我敢断言也会出错,因为OrderPriceType=‘’ 肯定是不可以被接口接受的,这个需要改!
- 2 主界面中发送的停止单,没有做服务器是支持的判断,如果不支持也的话也无人维护。那么是否可以把下级应用cta_engine的对本地停止单的维护,上提到main_engine中来执行?
- 3 CTA策略都可以发委托单,为什么手工却不让做呢 ?这么好的功能,应该人工也享受享受!
已经分析过了,那么是否可以改进呢?