vn.py量化社区
By Traders, For Traders.
Member
avatar
加入于:
帖子: 45
声望: 0

场景介绍
1、无界面模式运行,策略是BollChannelStrategy,交易合约是 rb2010.SHFE
2、运行结果

D:\vnstudio\python.exe D:/vnstudio/Lib/site-packages/vnpy/app/cta_strategy/run_noui.py
启动CTA策略守护父进程
启动子进程
子进程启动成功
2020-08-16 11:58:22,962  INFO: 主引擎创建成功
2020-08-16 11:58:22,964  INFO: 注册日志事件监听
2020-08-16 11:58:22,967  INFO: 连接CTP接口
2020-08-16 11:58:23,001  INFO: 行情服务器连接成功
2020-08-16 11:58:23,193  INFO: 行情服务器登录成功
2020-08-16 11:58:25,787  INFO: RQData数据接口初始化成功
在使用天勤量化之前,默认您已经知晓并同意以下免责条款,如果不同意请立即停止使用:https://www.shinnytech.com/blog/disclaimer/
2020-08-16 11:58:27,626  INFO: CTA策略引擎初始化成功
2020-08-16 11:58:27,627  INFO: CTA策略初始化完成
2020-08-16 11:58:27,633  INFO: BCS_IC2008开始执行初始化
2020-08-16 11:58:27,639  INFO: BCS_IC2008: 策略初始化
2020-08-16 11:58:28,188  INFO: BCS_IC2008: 行情订阅失败,找不到合约rb2010.SHFE
2020-08-16 11:58:28,188  INFO: BCS_IC2008初始化完成

3、设了断点,确认能登录上rqdata,能取到全市场合约表。
4、class CtaEngine -> def _init_strategy 中 strategy.vt_symbol 有合约名 “rb2010.SHFE”,但是 contract = self.main_engine.get_contract(strategy.vt_symbol) 取不到相关信息,因此报错。

然后就不知道为什么无法取到合约了。请教前辈大拿。

Administrator
avatar
加入于:
帖子: 4208
声望: 240

CTP的合约信息是从交易接口获取的,而你这里日志里没有登录成功的记录。

Member
avatar
加入于:
帖子: 45
声望: 0

代码调通了,但是还是有点懵懵懂懂,继续学习,有问题再请教。多谢群主。

Member
avatar
加入于:
帖子: 45
声望: 0

CTP的合约信息是从交易接口获取的
———— 还是这个问题请教,连接上 ctp 后,从 ctp 取到对应合约的信息,是哪个代码实现?
我逐步运行代码,按如下顺序跟踪

run.py ->
def run_child ->
cta_engine.init_engine() ->
vnpy.app.cta_strategy.engine.py ->
class CtaEngine ->
def init_engine ->
self.register_event() -> 这里为何能跳到下一个地方,搞不明白
vnpy.trader.converter.py ->
class OffsetConverter ->
def is_convert_required -> contract = self.main_engine.get_contract(strategy.vt_symbol) ->
vnpy.trader.engine.py ->
class OmsEngine ->
def get_contract -> return self.contracts.get(vt_symbol, None)

这一步执行完,就从ctp行情接口取到self.contracts的信息了。
可是明面上看,这一句是从OmeEngine类的对象初始化时定义的dict变量,原本就是空的,不应该取到值 。
我哪里没有搞对?

Member
avatar
加入于:
帖子: 936
声望: 47

process_contract_event函数里在self.contracts字典里放了事件驱动引擎(接口传到event)传来的contract吧

Member
avatar
加入于:
帖子: 45
声望: 0

是的,经过跟踪,新发现获取contract信息的路径是

1、在def run_child 函数里 main_engine = MainEngine(event_engine) 初始化主引擎时,有注册事件的操作,其中将process_contract_event函数与事件EVENT_CONTRACT作了绑定。

2、连接ctp时,
由main_engine.connect(ctp_setting, "CTP") 调用 ctp_gateway.connect(setting) ,在该方法中连接ctp的前置,之后调用查询方法 def init_query()。
而 def init_query() 里边也只是查帐号、查持仓,再将函数 process_timer_event 注册给事件EVENT_TIMER
def process_timer_event这个函数则是把self.query_functions中查询账号的内容去掉,补充一个新的func,之后再更新一次。

3、随后在新开的线程 Thread-7(应该是之前EventEngine实例化时新开的获取并处理事件的线程)中,event_engine从队列里取事件,其类型是EVENT_CONTRACT,根据event_engine中self._handlers里已注册的信息,就调用 OmsEngine.process_contract_event来处理,该方法接收到 eContract 事件时,就包含了要交易的合约的信息,这个信息再被赋值给dict变量self.contracts供后续使用。

问题是在以上过程中,还是找不到将合约名称发送给ctp查询的语句。
连接上ctp和查询账号、持仓,并不会返回指定某个合约(本例中是 rb2010.SHFE)的详细信息。
其他就找不到执行查询合约 rb2010.SHFE信息的操作了。

所以还是要请帮看看我有什么地方没有跟踪到的。多谢

Member
avatar
加入于:
帖子: 936
声望: 47

def init_engine的时候不是load_strategy_setting了吗,在那里应该拿到了vt_symbol变成strategy.vt_symbol,然后通过get_contract返回了合约信息

Member
avatar
加入于:
帖子: 45
声望: 0

不是的,通过断点和单步查看 self.contracts的值,在之前的 main_engine.connect(ctp_setting, "CTP") 这句连接上ctp后,就从ctp拿到了要交易合约(比如rb2010.SHFE)的信息。
我猜测,登录ctp成功后,event_engine._run_timer方法就持续发送 EVENT_TIMER事件,而响应这个事件的函数 def process_timer_event 包含访问ctp获取合约信息的行为(只执行一次),但是找不到对应的语句。

© 2015-2019 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号-3