这个文章主要是记录IB模拟交易使用的一些坑,IB TWS和VNPY链接和一般的接口不一样,不是VNPY通过API直接联网IB交易服务器,而且现在本地安装一个类似gateway的tws客户端,vnpy链接本地tws客户端,在由客户端中转到交易服务器。IB也提供非客户端的纯本地gatway软件,没有试过,这里只是说说通过TWS客户端。
在写之前没有看到陈总在知乎的文章,走了不少坑。https://zhuanlan.zhihu.com/p/75787960
1 - 安装IB TWS桌面版,然后登录模拟账户。假定你已经申请好了用户,并且有了模拟账户。如果没有可以直接官网申请。
2 - 等罗后一定要记得勾选“Enable ActiveX and Socket Clients”这个选项,此外在下方的“Trusted IPs”,要注意是否允许本地连接已经打开了,这个勾选后,默认127.0.0.1可以直接访问TWS,而其他地址,需要通过“Create”命令,加入到TWS的白名单里。
另外Socket port,和VNPY里面要填入一致,一般7497是模拟交易,7496是正式交易。
3 - 链接后,会返回message code,可以去下面网址查询message code含义,-1是warning
ERROR -1 2104 Market data farm connection is OK:usfarm.nj
ERROR -1 2104 Market data farm connection is OK:cashfarm
ERROR -1 2104 Market data farm connection is OK:usfarm
ERROR -1 2106 HMDS data farm connection is OK:hkhmds
ERROR -1 2106 HMDS data farm connection is OK:ushmds
https://interactivebrokers.github.io/tws-api/message_codes.html
4 - 研究下IB Gateway的三个类,简单说明下, 后面有空在研究
IbGateway: BaseGateway的继承,提供BaseGateway的一些abstractmethod的实现,被其他引擎按照标准调用,其实那些实现都是打包IbAPI的方法。
IbAPI:IBAPI 中Ewrapper 类的继承,基本所有订阅查询下单都是在这里二次打包了。
IbClient: IBAPI中EClient的继承,主要保持和TWS连通
5 - 订阅行情,这里是查询是盈透证券对于每个合约在某一交易所的唯一标识符ConId码,而非Symbol或者LocalName。要去下面官网查询,比如BABA就是166090175
https://contract.ibkr.info/v3.10/index.php
关于交易所,可以在TWS中点击右键 - Finacial Instrument Info 看到,SMART并不是交易所,而且IB会自动选择Primary Exhcange,避免选取太多。
如果提示错误信息 354, 那就是你没有订阅相关行情数据,那么去安装下面也去订阅,还有模拟账户共享真实账户订阅数据,所以即使模拟账户,还是要现在真实账户订阅。
https://interactivebrokers.github.io/tws-api/market_data.html
7 - 交易,直接在vnpy交易界面下单,没有什么问题,对于股票来说就是多是买入,空是卖出,和方向开平没有什么关系。
返回成交信息的时候,vnpy系统报错,研究发现是IB的模拟交易用了一个模拟交易所exhange,所以在vnpy/gateway/ib/ib_gateway.py和 trader/constant.py文件中加入这个exhange
Exchange.IBKRATS:'IBKRATS'
8 - 延时行情订阅,当你去订阅时候,会发现,嗯,收费的,不如我大A股,测试环境只能用延时数据,暂时还不准备打钱。这时候虽然在tws上是有数据,但是在vnpy尝试订阅延时数据时候,会提示说
ERROR 6 10168 Requested market data is not subscribed. Delayed market data is not enabled
研究了下,在vnpy/gateway/ib/ib_gateway.py中reqMktData前的延时快照数据读取激活,如果真的买了,最好改回去,虽然系统会自动推送最新数据如果发现你购买了。
这里默认是1真实行情, 3 是延时行情。live(1)frozen(2)delayed(3)delayedfrozen(4).
在reqMktData之前加一行
self.client.reqMarketDataType(3)
但是发现还是没有vnpy数据,再一看,是因为delyed的ticktype不一样,是88,而vnpy只让45这个实际的过来。而且还有tick数据也不一样编码,要从新加入到ENUM TICKFIELD_IB2VT, 好像折腾,直接再TWS就不可以看到了。改到这里就改下去吧,最好可以显示。
def tickString 修改成
if tickType!="45"ortickType!="88":
TICKFIELD_IB2VT 加入下面
66:"bid_volume_1",
69:"bid_price_1",
67:"ask_price_1",
70:"ask_volume_1",
68:"last_price",
71:"last_volume",
73:"high_price",
73:"low_price",
74:"volume",
75:"pre_close",
76:"open_price",
最后显示效果如下
后面我会尝试用Jupyter Notebook试试交易