vnpy python3可以做外汇吗

Developed by traders, for traders.
vn.py - 基于python的开源交易平台开发框架
vn.py项目起源于国内私募的自主交易系统,2015年初启动时只是单纯的交易API接口的Python封装。随着业内关注度的上升和社区不断的贡献,目前已经一步步成长为一套全面的交易程序开发框架,用户群体也日渐多样化,包括私募基金、证券自营和资管、期货资管和子公司、高校研究机构、个人投资者等。
项目构成:
丰富的Python交易和数据API接口,基本覆盖了国内外常规交易品种(证券、期货、期权、外汇、CFD):
CTP(vn.ctp):期货、期货期权
飞创(vn.xspeed):期货、期货期权
飞马(vn.femas):中金所的期货和期货期权
金仕达期权(vn.ksotp):期货、期货期权、证券期权
金仕达黄金(vn.ksgold):金交所贵金属
飞鼠(vn.sgit):期货、金交所贵金属
QDP极速柜台(vn.qdp):期货、期货期权、金交所贵金属
OANDA(vn.oanda):外汇、CFD
Interactive Brokers(vn.ib):外盘股票、期货、期权、外汇等
直达期货(vn.shzd):外盘期货
OKCoin(vn.okcoin):比特币、莱特币等
通联数据(vn.datayes):历史行情数据、基本面数据
事件驱动引擎(vn.event),用于实现Python在全局锁(GIL)限制下的高性能事件驱动编程
开发示例(vn.demo),通过简洁明了的代码展示如何使用API和事件驱动引擎开发交易程序
交易平台(vn.trader),整合了vn.py项目中所有的交易接口以及Interactive Brokers的三方接口(IbPy),围绕事件驱动引擎设计了针对策略算法和交易应用开发的上层API,使得交易员可以专注于解决交易业务需求而无需关注底层细节,平台中提供了一套完整的CTA策略模块(回测和实盘)作为开发参考
RPC模块(vn.rpc),提供跨进程服务调用的RPC模块,同时支持服务端向客户端的主动数据推送,用于实现vn.py框架下模块的多进程解耦
和,长期更新vn.py相关的开发教程资料
官方交流QQ群,提供给社区用户一个便捷舒适的交流环境(严禁闲聊无关内容,由于管理严格吸引了大量的机构交易员)
想提供帮助?
vn.py项目处于快速发展期,非常需要社区提供帮助,具体包括:
测试:对vn.py项目中代码的测试和BUG反馈
文档:包括代码注释、开发教程、学习经验等
新功能:提供新的交易和行情接口接入,上层应用开发等
网站:对www.vnpy.org的官方网站(基于pelican)的外观设计和功能添加
建议通过在Github上开issue的方式来贡献以上内容
开发过程中遇到了问题?想要更多了解vn.py?请使用以下方式联系我们:
官方论坛(推荐):
项目邮箱:vn.
QQ交流群:
现阶段计划将收到的全部捐赠资金都投入到vn.py项目基金,用于支持后续的项目开发和各项活动。
在此先强调一下:vn.py是开源项目,可以永久免费使用,并没有强制捐赠的要求!!!
捐赠方式:支付宝(*晓优)
计划长期维护一份捐赠清单,所以请在留言中注明是项目捐赠以及捐赠人的名字(当然想匿名的朋友就随意了)。
& 2017 用Python的交易员
& Powered by ,vnpy-master
说明:&&用Python编写的程序化交易软件,可用于期货、期权等的实盘交易(Written in Python programming transaction software, futures, options, etc. can be used for a firm transaction)
文件列表:
vnpy-master
vnpy-master\.gitignore
vnpy-master\LICENSE
vnpy-master\README.md
vnpy-master\vn.cs
vnpy-master\vn.cs\hshlp
vnpy-master\vn.cs\hshlp\CITICs_HsT2Hlp.dll
vnpy-master\vn.cs\hshlp\CITICs_HsT2Hlp.h
vnpy-master\vn.cs\hshlp\CITICs_HsT2Hlp.lib
vnpy-master\vn.cs\hshlp\Hsconfig.ini
vnpy-master\vn.cs\hshlp\t2sdk.dll
vnpy-master\vn.cs\hshlp\t2sdk.ini
vnpy-master\vn.cs\hshlp\t2sdk.lib
vnpy-master\vn.cs\vncshshlp
vnpy-master\vn.cs\vncshshlp\test
vnpy-master\vn.cs\vncshshlp\test\()ZXZQ-TESTsfjrt-ALL-0001_3rd.dat
vnpy-master\vn.cs\vncshshlp\test\CITICs_HsT2Hlp.dll
vnpy-master\vn.cs\vncshshlp\test\Hsconfig.ini
vnpy-master\vn.cs\vncshshlp\test\csauthor.dat
vnpy-master\vn.cs\vncshshlp\test\cslog
vnpy-master\vn.cs\vncshshlp\test\cslog\.log
vnpy-master\vn.cs\vncshshlp\test\cslog\cserror.log
vnpy-master\vn.cs\vncshshlp\test\cstest.py
vnpy-master\vn.cs\vncshshlp\test\license.dat
vnpy-master\vn.cs\vncshshlp\test\t2sdk.dll
vnpy-master\vn.cs\vncshshlp\test\t2sdk.ini
vnpy-master\vn.cs\vncshshlp\test\vncshshlp.pyd
vnpy-master\vn.cs\vncshshlp\vncshshlp
vnpy-master\vn.cs\vncshshlp\vncshshlp\ReadMe.txt
vnpy-master\vn.cs\vncshshlp\vncshshlp\dllmain.cpp
vnpy-master\vn.cs\vncshshlp\vncshshlp\stdafx.cpp
vnpy-master\vn.cs\vncshshlp\vncshshlp\stdafx.h
vnpy-master\vn.cs\vncshshlp\vncshshlp\targetver.h
vnpy-master\vn.cs\vncshshlp\vncshshlp\vncshshlp.cpp
vnpy-master\vn.cs\vncshshlp\vncshshlp\vncshshlp.h
vnpy-master\vn.ctp
vnpy-master\vn.ctp\ctpapi
vnpy-master\vn.ctp\ctpapi\ThostFtdcMdApi.h
vnpy-master\vn.ctp\ctpapi\ThostFtdcTraderApi.h
vnpy-master\vn.ctp\ctpapi\ThostFtdcUserApiDataType.h
vnpy-master\vn.ctp\ctpapi\ThostFtdcUserApiStruct.h
vnpy-master\vn.ctp\ctpapi\error.dtd
vnpy-master\vn.ctp\ctpapi\error.xml
vnpy-master\vn.ctp\ctpapi\thostmduserapi.dll
vnpy-master\vn.ctp\ctpapi\thostmduserapi.lib
vnpy-master\vn.ctp\ctpapi\thosttraderapi.dll
vnpy-master\vn.ctp\ctpapi\thosttraderapi.lib
vnpy-master\vn.ctp\pyscript
vnpy-master\vn.ctp\pyscript\ThostFtdcMdApi.h
vnpy-master\vn.ctp\pyscript\ThostFtdcTraderApi.h
vnpy-master\vn.ctp\pyscript\ThostFtdcUserApiDataType.h
vnpy-master\vn.ctp\pyscript\ThostFtdcUserApiStruct.h
vnpy-master\vn.ctp\pyscript\ctp_data_type.py
vnpy-master\vn.ctp\pyscript\ctp_md_define.cpp
vnpy-master\vn.ctp\pyscript\ctp_md_function.cpp
vnpy-master\vn.ctp\pyscript\ctp_md_process.cpp
vnpy-master\vn.ctp\pyscript\ctp_md_switch.cpp
vnpy-master\vn.ctp\pyscript\ctp_md_task.cpp
vnpy-master\vn.ctp\pyscript\ctp_struct.py
vnpy-master\vn.ctp\pyscript\ctp_td_define.cpp
vnpy-master\vn.ctp\pyscript\ctp_td_function.cpp
vnpy-master\vn.ctp\pyscript\ctp_td_header_function.h
vnpy-master\vn.ctp\pyscript\ctp_td_header_on.h
vnpy-master\vn.ctp\pyscript\ctp_td_header_process.h
vnpy-master\vn.ctp\pyscript\ctp_td_process.cpp
vnpy-master\vn.ctp\pyscript\ctp_td_switch.cpp
vnpy-master\vn.ctp\pyscript\ctp_td_task.cpp
vnpy-master\vn.ctp\pyscript\ctp_td_wrap.cpp
vnpy-master\vn.ctp\pyscript\generate_data_type.py
vnpy-master\vn.ctp\pyscript\generate_md_functions.py
vnpy-master\vn.ctp\pyscript\generate_struct.py
vnpy-master\vn.ctp\pyscript\generate_td_functions.py
vnpy-master\vn.ctp\vnctpmd
vnpy-master\vn.ctp\vnctpmd\test
vnpy-master\vn.ctp\vnctpmd\test\mdtest.py
vnpy-master\vn.ctp\vnctpmd\test\thostmduserapi.dll
vnpy-master\vn.ctp\vnctpmd\test\vnctpmd.pyd
vnpy-master\vn.ctp\vnctpmd\vnctpmd
vnpy-master\vn.ctp\vnctpmd\vnctpmd\ReadMe.txt
vnpy-master\vn.ctp\vnctpmd\vnctpmd\dllmain.cpp
vnpy-master\vn.ctp\vnctpmd\vnctpmd\stdafx.cpp
vnpy-master\vn.ctp\vnctpmd\vnctpmd\stdafx.h
vnpy-master\vn.ctp\vnctpmd\vnctpmd\targetver.h
vnpy-master\vn.ctp\vnctpmd\vnctpmd\vnctpmd.cpp
vnpy-master\vn.ctp\vnctpmd\vnctpmd\vnctpmd.h
vnpy-master\vn.ctp\vnctptd
vnpy-master\vn.ctp\vnctptd\test
vnpy-master\vn.ctp\vnctptd\test\tdtest.py
vnpy-master\vn.ctp\vnctptd\test\thosttraderapi.dll
vnpy-master\vn.ctp\vnctptd\test\vnctptd.pyd
vnpy-master\vn.ctp\vnctptd\vnctptd
vnpy-master\vn.ctp\vnctptd\vnctptd\ReadMe.txt
vnpy-master\vn.ctp\vnctptd\vnctptd\dllmain.cpp
vnpy-master\vn.ctp\vnctptd\vnctptd\stdafx.cpp
vnpy-master\vn.ctp\vnctptd\vnctptd\stdafx.h
vnpy-master\vn.ctp\vnctptd\vnctptd\targetver.h
vnpy-master\vn.ctp\vnctptd\vnctptd\vnctptd.cpp
vnpy-master\vn.ctp\vnctptd\vnctptd\vnctptd.h
vnpy-master\vn.datayes
vnpy-master\vn.datayes\README.md
近期下载者:
相关文件:对于管理一个开源Python量化交易框架项目(vn.py)的建议有哪些? - 知乎754被浏览<strong class="NumberBoard-itemValue" title="2分享邀请回答0添加评论分享收藏感谢收起跟着样例学JAQS(4)-如何将JAQS对接VNPY进行实盘交易_突袭网
当前位置&:&&&&跟着样例学JAQS(4)-如何将JAQS对接VNPY进行实盘交易
热门标签:&
跟着样例学JAQS(4)-如何将JAQS对接VNPY进行实盘交易
编辑:李利平
社区很多朋友咨询,如何正确使用JAQS对接vnpy进行实盘交易,本文将完整介绍这一过程,解决大家的疑惑。1. 正确安装vnpyvnpy目前最稳定的python环境是py2.7(32位),因此我们建议的安装方式是:下载并安装anaconda。下载地址:https://www.anaconda.com/download/,选择windows平台32位,python2.7下载并安装vnpy。需要注意,不能使用pip安装,需要从github下载master分支的代码,下载地址:https://github.com/vnpy/vnpy下载完成后,目录结构如下, 请在刚才安装的Anacanda,也就是“python2.7 32位”环境下,运行install.bat,安装vnpy。2. 安装JAQS请在刚才安装的Anacanda,也就是“python2.7 32位”环境下,执行两步:安装python-snappy,从https://www.lfd.uci.edu/~gohlke/pythonlibs/#python-snappys下载python-snappy的安装包。pip install python_snappy-0.5.1-cp27-cp27m-win32.whl安装JAQSpip install jaqs3. 启动vnpy的JAQS服务进入刚才下载的vnpy的代码目录,位于examples\VnTrader下,目录下的文件结构如下:有三个重要的文件需要修改:CTP_connect.json - CTP连接的信息JS_setting.json - JAQS服务信息run_jaqs.py - 启动JAQS的脚本CTP_connect.json{"brokerID": "9999","mdAddress": "tcp://180.168.146.187:10011","tdAddress": "tcp://180.168.146.187:10001","userID": "userID","password": "password"}JS_setting.json{"host": "127.0.0.1","port": 8901}JS_setting.json 配置JAQS的服务监听地址,一般不用修改。CTP_connect.json 配置CTP服务器地址和账户信息,需要修改成你实盘的地址和账户信息。run_jaqs.pydef main():"""主程序入口"""# 创建Qt应用对象qApp = createQApp()# 创建事件引擎ee = EventEngine()# 创建主引擎me = MainEngine(ee)# 添加交易接口me.addGateway(ctpGateway)# 添加上层应用me.addApp(jaqsService)# 创建主窗口mw = MainWindow(me, ee)mw.showMaximized()# 在主线程中启动Qt事件循环sys.exit(qApp.exec_())if __name__ == '__main__':main()run_jaqs.py是一个主程序,在这个主程序里面,添加了ctpGateway和jaqsService两个模块。ctpGateway是真正的实盘交易通道,jaqsService是服务转接模块。启动方法很简单,运行 python run_jaqs.py 即可!运行成功,则会出现vnpy经典的主界面,如下图所示:在“功能”菜单,会出现一个“Jaqs服务”,点击之后,是一个消息文本框,用于查看jaqs服务的运行日志。这是表明,JAQS的服务已经启动成功了。4. 启动CTP交易通道这个和vnpy启动其他交易通道的方法完全相同,在系统菜单下,点击“连接CTP”即可。运行成功的界面如下:5. 启动JAQS策略,对接vnpy这里我们举一个特别简单的策略的例子,来说明一下JAQS策略如何进行实盘。策略原理:(1) 做rb1805.SHF和rb1810.SHF的价差套利,如果价差超过195,则空rb1805.SHF,多rb1810.SHF,如果价差小于180,则反向做。(2) 为了演示效果,只开仓不平仓。(3) 策略启动后,根据tick数据,实时计算价差。(4) 每次策略启动只做一次来回。参考代码如下:只要将交易发送的地址,修改成“tcp://127.0.0.1:8901”,这个地址就是之前vnpy启动本地Jaqs服务的地址。SpreadAlgo策略代码不在文章中贴出,请大家直接下载代码。运行后,策略会根据条件,选择是否开仓,在vnpy的界面,可以看到开仓结果。是不是很简单?6. 想尝试一下?这里的东西都是开源和免费的。
更多精彩 >>>vn.pyvn.py基于python的开源交易平台开发框架关注专栏更多最新文章{&debug&:false,&apiRoot&:&&,&paySDK&:&https:\u002F\u002Fpay.zhihu.com\u002Fapi\u002Fjs&,&wechatConfigAPI&:&\u002Fapi\u002Fwechat\u002Fjssdkconfig&,&name&:&production&,&instance&:&column&,&tokens&:{&X-XSRF-TOKEN&:null,&X-UDID&:null,&Authorization&:&oauth c3cef7c66aa9e6a1e3160e20&}}{&database&:{&Post&:{&&:{&title&:&突破GIL?? - 转载 - Quicklib 源码分析 2&,&author&:&traderusingpython&,&content&:&\u003Cp\u003E\u003Cb\u003E提示:\u003C\u002Fb\u003E\u003Cb\u003E干货\u003C\u002Fb\u003E\u003Cb\u003E分析在第二段和第三段,想节省时间的朋友可以跳过第一段。\u003C\u002Fb\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ch2\u003E\u003Cu\u003E\u003Cb\u003E写在前面\u003C\u002Fb\u003E\u003C\u002Fu\u003E\u003C\u002Fh2\u003E\u003Cp\u003E周末陪家人出去玩了一天,回来后看到Quicklib的作者在我的两篇文章下发了不少重复的评论,简单总结下他的观点,也写一下我的回应。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E观点1:vn.py的代码写的很烂,完全不屑于看。\u003C\u002Fp\u003E\u003Cp\u003E回应1:作为一个非科班出身的程序员,我一直觉得自己代码写的不咋地,高手不屑于看我表示完全理解。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E观点2:vn.py采用的是落后的多线程架构,Quicklib采用的异步IO架构性能要高得多。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E回应2:才说不屑于看vn.py的代码,这就能知道vn.py采用的是落后的多线程架构,这个我只能表示不明觉厉。另外,和Quicklib作者相反,我正在仔细研究Quicklib的代码,希望可以理解其所谓的“异步IO”架构,受限于较低的代码阅读水平,还没完全看懂,我会继续努力。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E观点3:Quicklib是Python的Node.js版本,性能远超PHP(指vn.py)。\u003C\u002Fp\u003E\u003Cp\u003E回应3:这个需要靠代码分析和测试结果来说话,否则似乎给人一种“五菱宏光才是秋名山神车”的感觉?\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cp\u003E观点4:Quicklib中的那部分vn.demo代码,是社区用户贡献的,和作者无关,接下来立即就会删除。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E回应4:这点我表示完全理解,早期vn.py代码也有过比较混乱的阶段。不过想要项目未来能够成功,作者还是得看一眼社区的PR内容后再合并吧。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Cp\u003E观点5:vn.py占据了先发优势,对Quicklib这个有潜在威胁的项目进行提前打压,本质好比2岁的孩子打10个月的孩子一样。\u003C\u002Fp\u003E\u003Cp\u003E回应5:感谢对vn.py这么高的评价,不过个人觉得现在的完成度离2岁的孩子还很远。另外感谢社区用户的捧场,我作为嘉宾过去一年受邀参加过几次活动(PyCon2016、中国金融创新峰会等),演讲过程中对于国内其他的一些开源量化项目:tushare、easy trader、at_py、RQAlpha等都做了介绍和推荐,网上也还能找到相关的视频和报道。说我现在专门针对Quicklib进行提前打压,是在暗示所有这些我推荐过的项目都比不上Quicklib?\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E读者如果觉得有遗漏的观点请在文章下面留言哈,我会在下一篇里继续回应,现在进入正文部分了。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cu\u003E\u003Cb\u003E正文\u003C\u002Fb\u003E\u003C\u002Fu\u003E\u003C\u002Fh2\u003E\u003Cp\u003E\u003Cb\u003E作者:金融民工\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E上一篇看完log,这一篇我们来看看quicklib一直吹嘘所谓先进的事件驱动机制到底有何神奇之处,先来看看OnCmd这个函数:\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eint OnCmd()\n{\nDWORD dw = WaitForMultipleObjects(MAX_EVENTNUM, hEvent, FALSE, INFINITE);\n\nswitch (dw)\n{\ncase WAIT_OBJECT_0 + EID_OnFrontDisconnected:\n\n\u002F\u002F The process identified by h[0] (hProcess1) terminated.\nreturn SYSTEM_NETCONNECT_BREAK;\\n\ncase WAIT_OBJECT_0 + EID_OnFrontConnected:\n\n\u002F\u002F The process identified by h[1] (hProcess2) terminated.\nreturn SYSTEM_NETCONNECT_SCUESS;\\n\ncase WAIT_OBJECT_0 + EID_OnRspUserLogin_Failer:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_LOGIN_DENIED;\\ncase WAIT_OBJECT_0 + EID_OnRspUserLogin_Scuess:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_LOGIN_SCUESS;\\ncase WAIT_OBJECT_0 + EID_OnRtnDepthMarketData:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_NEWTICK;\\ncase WAIT_OBJECT_0 + EID_IsErrorRspInfo:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_SYSTEM_ERROR;\\ncase WAIT_OBJECT_0 + EID_OnRspSubMarketData:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_SUBCRIBE_SCUESS;\\ncase WAIT_OBJECT_0 + EID_OnRspUnSubMarketData:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_UNSUBCRIBE_SCUESS;\\ncase WAIT_OBJECT_0 + EID_OnRspUserLogout:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_LOGINOUT_SCUESS;\\n\ncase WAIT_OBJECT_0 + EID_OnRspForQuote:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_QRY_FORQUOTE;\\ncase WAIT_OBJECT_0 + EID_OnLog:\n\n\u002F\u002F The process identified by h[2] (hProcess3) terminated.\nreturn SYSTEM_LOG;\\n\n}\n\nreturn SYSTEM_EMPTY;\n\u003C\u002Fcode\u003E\u003Cp\u003E不熟悉Windows sdk的同学看得有点懵是把,重点在WaitForMultipleObjects这个函数这里。这个函数详细参考请看\u003Ca href=\&https:\u002F\u002Fmsdn.microsoft.com\u002Fen-us\u002Flibrary\u002Fwindows\u002Fdesktop\u002Fms687025(v=vs.85).aspx\& class=\&\& data-editable=\&true\& data-title=\&MSDN对应的词条\&\u003EMSDN对应的词条\u003C\u002Fa\u003E,通俗点说就是它可以等待多个内核对象,直到参数所指定的OBJECT成为发射信号状态(SetEvent函数则是设置发射状态)才返回。那么也就是说可以使用SetEvent与WaitForMultipleObjects来做同步。明白了这一点剩下的事情就简单了。来看一个OnFrontConnected的例子:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Evoid CMdSpi::OnFrontConnected()\n{\nstd::cout && \&---&&& \& && __FUNCTION__ && std::\n\nSetEvent(hEvent[EID_OnFrontConnected]);\n\u002F\u002F\u002F用户登录请求\nReqUserLogin();\n}\n\u003C\u002Fcode\u003E\u003Cp\u003EOnFrontConnected回调被调用后,SetEvent(hEvent[EID_OnFrontConnected]); 设置一个信号。这时候OnCmd里面的WaitForMultipleObjects等待到该信号,返回\u003Cbr\u003E落在case WAIT_OBJECT_0 + EID_OnFrontConnected:这个分支,然后返回了SYSTEM_NETCONNECT_SCUESS(8005)。\u003Cbr\u003E\u003Cbr\u003E那么OnCmd的调用者是在哪呢? 在Python这边, 我们来看一段TDThread(交易线程)的代码\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Edef TD_OnUserLoginDenied():\n
# 登录被拒绝\n
print \&---------------TD_OnUserLoginDenied---------------\&\n\n\ndef TD_OnUserLoginErrPassword():\n
# 登录密码错误\n
print \&---------------TD_OnUserLoginErrPassword---------------\&\n\n\ndef TD_OnUserLogout():\n
# 登出成功\n
print \&---------------TD_OnUserLogout---------------\&\n\n\ndef TD_OnFrontConnected():\n
# 连接成功\n
print \&---------------TD_OnFrontConnected---------------\&\n...\n\ntddict = {\n
TD_EMPTY: TD_OnEmptyCmd,\n
TD_LOGIN_SCUESS: TD_OnUserLogin,\n
TD_LOGIN_DENIED: TD_OnUserLoginDenied,\n
TD_LOGIN_ERRORPASSWORD: TD_OnUserLoginErrPassword,\n
TD_LOGINOUT_SCUESS: TD_OnUserLogout,\n
TD_NETCONNECT_SCUESS: TD_OnFrontConnected,\n
TD_NETCONNECT_BREAK: TD_OnFrontDisconnected,\n
TD_NETCONNECT_FAILER: TD_OnFrontConnectedFailer,\n
TD_ERROR: TD_OnError,\n
TD_ORDER_INFO: TD_OnOrder,\n
TD_SETTLEMENTINFOCONFIRM: TD_OnSettlementInfoConfirm,\n
TD_MAXORDERVOLUME: TD_OnMaxOrderVolume\n}\n\nwhile (1):
# 死循环,反复执行\n
tddict[trader.OnCmd()]()\n\n\u003C\u002Fcode\u003E\u003Cp\u003E代码逻辑也很简单,tddict这个dict存了信号的编号到对应回调函数的映射关系。然后当OnCmd等待到信号返回的时候,对应的callback得到调用。也是平淡无奇的代码,和对外宣传的效果可是相差甚远啊。用什么滤镜美颜都达不到对外宣称的效果啊......\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E对外宣传大概是这样的:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003Equicklib架构很棒, 吊打vnpy\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib性能很屌, 吊打vnpy\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib是10年+经营的资深程序员写的各种棒, vnpy是做交易的人写的(言下之意在讲不是专业写代码的外门汉, 代码写不利索)各种屎\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib没有GIL(哈哈哈, 请允许我又笑一下), vnpy有GIL\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib是正途, 用vnpy的都是脑残. (哈哈哈, 请允许我又笑一下)\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib可以接受10w个链接(哈哈哈, 请允许我又笑一下)\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003Equicklib写了大量底层(哈哈哈, 请允许我又笑一下)\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cbr\u003E\u003Cbr\u003E而实际上呢?\u003Cbr\u003E\u003Cbr\u003E\u003Cp\u003E先说架构,quicklib充其量算封装个CTP,这样也能称之为框架,吹架构了......且先不说质量(没办法讲质量, 真是太差劲了),就功能上实际上离一个交易框架还相差甚远。这还是回到是蠢还是坏,或者又蠢又坏的问题上。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E然后是性能,这里的事件驱动用各种list+SetEvent和WaitForMultipleObjects,在原理上和用个queue没什么本质区别。不明白有什么好吹嘘的,而实际上也并不能避免GIL(你以为GIL只有显示的调用才有?),log也是同步阻塞的。不明白吹嘘的资本在哪。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E包装了个CTP就是写了大量的底层??!!!(想到那4800行的四个函数, 又想笑一下)\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E 好吧我笑抽了, 明天有兴趣再继续写交易的部分吧.\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cu\u003E\u003Cb\u003E写在后面\u003C\u002Fb\u003E\u003C\u002Fu\u003E\u003C\u002Fh2\u003E\u003Cp\u003E看第一篇分析的时候还有点懵,看完第二篇对Quicklib的运行方式大概有个概念了:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003EPython环境下的主线程中启动一个死循环(主事件循环),运行OnCmd函数,等待C++环境下的WaitForMultipleObjects信号被触发;\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E底层CTP API收到数据后,调用原生SPI的回调函数并设置事件(SetEvent),触发上一步的信号,通过一个Swtich来返回本次回调函数触发类型的信息;\u003C\u002Fli\u003E\u003Cli\u003EPython环境下收到这个触发类型的信息后,去字典中查询对应的Python回调处理函数,并立即调用\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cbr\u003E在这个模式下,Python环境中只需要一个主线程而无需启动其他的线程,Python虚拟机确实也就没有创建全局锁GIL对象。不过感觉似乎这个运行方式只能算是没有用到GIL,谈不上解决了GIL的问题(当然可能Quick作者压根就没这么说过,又是我理解错了他的意思),而且对于交易程序而言还有几个的问题:\u003Col\u003E\u003Cli\u003E数据无法从C++环境中到达Python环境中,OnCmd()返回的只有底层接口回调函数通知的类型,而没有具体的数据,也就无法使用Python开发策略,这里猜测可能Quicklib是选择开发了一些用于在Python中主动调用的函数来实现数据获取;\u003C\u002Fli\u003E\u003Cli\u003E对于只连接一个CTP接口的交易程序而言是用不着GIL了,但是如果要同时连接多个CTP接口(分账户)或者同时连接其他市场的接口(跨市套利),这个架构就无能为力了,否则为每个接口开启一个死循环必然要用到多线程,并创建GIL;\u003C\u002Fli\u003E\u003Cli\u003E因为Python中只能有一个线程,所以这个交易程序就无法和外部通讯了,GUI界面也好,运行Web服务器也好,都需要另外的线程。\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E以上只是截止目前我对Quicklib项目的理解,应该还有很多不足的地方,读完民工的分析文章后我会再深入的看下Quicklib的源代码。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E\u003Cb\u003E\u003Cu\u003Evn.py项目的Github仓库:\u003Ca href=\&http:\u002F\u002Flink.zhihu.com\u002F?target=https%3A\u002F\u002Fgithub.com\u002Fvnpy\u002Fvnpy\& class=\&\& data-editable=\&true\& data-title=\&vnpy\u002Fvnpy\&\u003Evnpy\u002Fvnpy\u003C\u002Fa\u003E,觉得还不错的话不妨来点个star!\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T03:45:31.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:40,&likeCount&:17,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T11:45:31+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic3.zhimg.com\u002Fv2-53b98e137d81f725cdc1_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:40,&likesCount&:17},&&:{&title&:&突破GIL...... - 转载 - Quicklib 源码分析 3、4&,&author&:&traderusingpython&,&content&:&\u003Ch2\u003E\u003Cb\u003E\u003Cu\u003E写在前面\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E星期天又快结束了,好久没有一个周末的情绪如此跌宕起伏,从开始对于技术研究方面的期待,到目前对于Quicklib作者一些行为的懵逼.\u003C\u002Fp\u003E\u003Cp\u003E这次直接合并发完金融民工对于Quicklib源代码的分析文章的3和4。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E\u003Cu\u003E正文\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E\u003Cb\u003E作者:金融民工\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E\u003Cu\u003E原文3\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E今天继续带大家一起来看看神奇的quicklib。来看看它的交易部分。\u003C\u002Fp\u003E\u003Cp\u003Evs打开之后是这样。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cimg src=\&v2-7d10bfaea1ab21d028f18e.png\& data-rawwidth=\&367\& data-rawheight=\&386\&\u003E\u003Cp\u003E 从目录结构上看,交易部分就是包装CTP,外加一个gzip(鬼知道gzip有没有用到?), 在加一个共享内存(鬼知道有没有用到)。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cbr\u003E习惯性的grep一下,咦似乎也没什么地方用到gzip啊....然后又grep了一下,发现也没什么地方用共享内存啊......无伤大雅我们继续。\u003Cbr\u003E\u003Cbr\u003E交易这边的套路和行情那边是一致的,CTPTradeSpi对应的头文件和源文件对应CThostFtdcTraderSpi的派生类QLCTPTraderSpi的声明和实现。\u003Cp\u003EQLCTPInterface.h 和QLCTPTradeAgenter.cpp对应把各种函数包装一次然后提供给Python那边调用。\u003C\u002Fp\u003E\u003Cp\u003E这一篇具体讲代码之前先来设定几个阅读的小目标:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003EPython怎么调用C++的代码?\u003C\u002Fli\u003E\u003Cli\u003ECTP里面C++的结构体是怎么暴露给Python这边用的?\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003EQuicklib对外宣传那么屌, 有什么黑科技吗?\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E这玩意能上实盘使用吗?\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E好了正式开始,\u003Cu\u003E先看看quicklib里面是怎么样用Python调用C++的\u003C\u002Fu\u003E。在此之前我们得现有一些前置知识,Python可以使用ctypes很方便的调用C的动态链接库,举个例子:\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003E\u002F\u002Fadd.c\nint add(int a, int b)\n{\n
return a+b;\n}\n\u003C\u002Fcode\u003E\u003Cp\u003Ecompile成动态库,以gcc为例:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Egcc -o libadd.so -shared -fPIC add.c\n\u003C\u002Fcode\u003E\u003Cp\u003E如果是用g++来编译,那么add.c里面需要用extern \&C\&包起来,类似这样,至于为什么需要用这个extern \&C\&,问题太基础,就不在这里浪费唇舌了,有兴趣可以看看\u003Ca href=\&http:\u002F\u002Fstackoverflow.com\u002Fquestions\u002F2Fin-c-source-what-is-the-effect-of-extern-c\& class=\&\& data-editable=\&true\& data-title=\&这里\&\u003E这里\u003C\u002Fa\u003E。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eextern \&C\&\n{\n
int add(int a, int b)\n
return a+b;\n
}\n}\n\u003C\u002Fcode\u003E\u003Cp\u003E然后python里面通过ctypes来调用:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eimport ctypes\nlib = ctypes.cdll.LoadLibrary(\&.\u002Flibadd.so\&)\nprint lib.add(1, 2)\n\u003C\u002Fcode\u003E\u003Cp\u003E好了,这是调用C的那么调用C++呢? 很简单啊,再给包一层C函数,来个例子:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eclass Test\n{\npublic:\n
int add(int a, int b)\n
return a+b;\n
}\n}\n\nextern \&C\&\n{\n
int add(int a, int b)\n
return t.add(a, b);\n
}\n}\n\u003C\u002Fcode\u003E\u003Cp\u003Eg++来编译一下:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Eg++ -o libtest.so -shared -fPIC test.cpp\n\u003C\u002Fcode\u003E\u003Cp\u003EPython这边同样是使用ctypes来加载就可以用了:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Eimport ctypes\nlib = ctypes.cdll.LoadLibrary(\&.\u002Flibtest.so\&)\nprint lib.add(1, 2)\n\u003C\u002Fcode\u003E\u003Cp\u003E一切都很简单对吧,没什么黑科技,quicklib里面也是这么做的,只是写起来就丑了很多。\u003C\u002Fp\u003E\u003Cp\u003E第二个问题,\u003Cu\u003ECTP里面C++的struct,怎么传递给Python里面使用呢\u003C\u002Fu\u003E,还是用的ctypes啊。可以看它的CTPTradeType.py这里,没什么黑科技。那么Quicklib使用这一种方式来让Python调用C++存在哪些槽点呢? 来理一下从C++到Python都经历了哪些内容:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003ECTP代码是C++的,为了让ctpyes调用,必须把类的成员函数都重新用C包了一层,变成一个个普通的c函数。因为load动态库都是一个一个函数,所以在Python这边又把这一个一个函数拼成一个类(代码在CTPTrader.py这里);\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E听起来感觉没有哪里不对是吧,但实际上这里是又非常多的重复性工作。如果quicklib的作者懂boost::python,懂pybind11这样的东西的话,我相信代码不会是这样,作为一个自称写了十多年C++的所谓\&资深\&程序员,不懂boost感觉怎么都说不过去呐......传闻中一年经验用十年,大抵便是如此吧。\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cbr\u003E第三个问题,\u003Cu\u003E我觉得不应该在回答这个问题了\u003C\u002Fu\u003E......\u003Cbr\u003E\u003Cbr\u003E第四个问题,\u003Cu\u003E号称多家机构在用啊\u003C\u002Fu\u003E,不知道是这些机构蠢呢,还是作者坏呢。test都没有的玩意(我尽力找了,一段类似test之类的代码都没有,有人找到了的话能告诉我吗......),真有人敢拿来实盘?当真金白银不是钱啊......\u003Cbr\u003E\u003Cbr\u003E这几个问题之后想必对quicklib应该有一个比较初步的了解了,了解了大概的轮廓就可以详细的看代码了。先来看C++派生CTPCThostFtdcTraderSpi的这部分。\u003Cp\u003EQLCTPTraderSpi这个类里面,包含两方面的内容:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003Eoverride CThostFtdcTraderSpi的几个virtual函数, 这几个函数都是回调函数(OnRsp*, OnRtn*)\u003C\u002Fli\u003E\u003Cli\u003E调用CThostFtdcTraderApi的几个对外请求的函数\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cbr\u003E正准备讲下单函数, 咦貌似没有定义:\u003Cimg src=\&v2-b3a0cbd0ca73dd1db97afc77c060b500.png\& data-rawwidth=\&532\& data-rawheight=\&164\&\u003E\u003Cp\u003E 好吧,到对应的源文件搜索reqorderinsert也没搜到,下单都没有啊......还交易框架呢,没关系看看其他的,来看一下撤单的逻辑(DeleteOrder):\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eint QLCTPTraderSpi::DeleteOrder(char *InstrumentID, DWORD orderRef)\n{\n
\u002F\u002F错误返回-1是和正常冲突的吗?\n
if (!InstrumentID)\n
return -1;\n
std::cout && __FUNCTION__ && std::\n
CThostFtdcInputOrderActionField ReqD\n
::ZeroMemory(&ReqDel, sizeof(ReqDel));\n
strcpy(ReqDel.BrokerID, gBrokerID.c_str());\n
strcpy(ReqDel.InvestorID, gUserID.c_str());\n
strcpy(ReqDel.InstrumentID, InstrumentID);\n
::sprintf(ReqDel.OrderRef, \&%012d\&, orderRef);\n
ReqDel.FrontID = FRONT_ID;\n
ReqDel.SessionID = SESSION_ID;\n
ReqDel.ActionFlag = THOST_FTDC_AF_D\n
int iResult = mpUserApi-&ReqOrderAction(&ReqDel, ++(iRequestID));\n\n
if (iResult != 0)\n
cerr && \&Failer: 撤单 : \& && ((iResult == 0) ? \&成功\& : \&失败(\&) && iResult && \&)\& &&\n
cerr && \&Scuess: 撤单 : 成功\& &&\n\n
return iR\n}\n\u003C\u002Fcode\u003E\u003Cp\u003E之前就吐槽过这种随意的,随处可见的cout,cerr,就这样的代码你吹高性能,不知道那种对此深信不疑的萌新到底有没有最基本的辨识能力。\u003C\u002Fp\u003E\u003Cp\u003E槽点太多, 挑个重点讲。iRequestID这个是个int,请自行补脑一下,以下语句多线程下会出现什么:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eint iResult = mpUserApi-&ReqOrderAction(&ReqDel, ++(iRequestID));\n\u003C\u002Fcode\u003E\u003Cp\u003E作者基础还是很欠缺火候啊...\u003Cbr\u003E\u003Cbr\u003E再来看看查询持仓,OnRspQryInvestorPosition这里。代码太长就不全贴出来,入眼第一眼就有问题啊,这个函数第二个参数CThostFtdcRspInfoField *pRspInfo直接就略过不用了,然而作者不知道即便是返回错误信息的时候pInvestorPosition也有可能不为nullptr吗。这个地方得加一段:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Eif(pRsoInfo != nullptr && pRsoInfo.ErrorID != 0)\n\u003C\u002Fcode\u003E\u003Cp\u003E然后下面的具体查询仓位的代码,粗略看一遍就发现,这里根本没有考虑不同交易所对昨仓的处理。这是一个很严重的问题啊,请自行补脑一下,当自己的程序化交易软件认为的仓位和实际的仓位不符的时候,是多麽容易照成交易事故的。\u003C\u002Fp\u003E\u003Cp\u003E这又暴露了另外一个问题,作者对业务逻辑了解得也很差啊...... 技术不行,业务也不行,这又的产物有人敢实盘,单就这份勇气,也是值得赞赏的。\u003C\u002Fp\u003E\u003Cp\u003E看点简单的好了,来看看OnRspUserLogin,用户login后产生的回调:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003ECThostFtdcRspUserLoginF\n
memset(&tn, 0, sizeof(CThostFtdcRspUserLoginField));\n\u003C\u002Fcode\u003E\u003Cp\u003E咦,这里用memset,之前DeleteOrder的时候用的是ZeroMemory呢:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003ECThostFtdcInputOrderActionField ReqD\n
::ZeroMemory(&ReqDel, sizeof(ReqDel));\n\u003C\u002Fcode\u003E\u003Cp\u003E突然让我回忆起以前读中学的时候,英文老师总说多用高级词汇不要整天but,but,but要用however!\u003C\u002Fp\u003E\u003Cp\u003E然后下面的:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003EEnterCriticalSection(&g_csdata);\n
loginlist.push_back(tn);\n
LeaveCriticalSection(&g_csdata);\n
SetEvent(hEvent[EID_OnRspUserLogin_Scuess]);\n\u003C\u002Fcode\u003E\u003Cp\u003Elock一下,再弄个信号,这部分在讲行情的时候讲过了。再接下来:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003EReqSettlementInfoConfirm();\n
Sleep(3000);\n\u003C\u002Fcode\u003E\u003Cp\u003E这个Sleep(3000)是何意...不是说好了和nodejs一样全异步吗\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E再来看看init函数, 其中注册柜台前置\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003E
mpUserApi-&RegisterFront((char *)gTDFrontAddr[0].c_str());\n
mpUserApi-&RegisterFront((char *)gTDFrontAddr[1].c_str());\n
mpUserApi-&RegisterFront((char *)gTDFrontAddr[2].c_str());\n\u003C\u002Fcode\u003E\u003Cp\u003E擦这个gTDFrontAddr不能是一个set吗, 然后for一下, 非要这样写.\u003Cbr\u003E\u003Cbr\u003E再来看看OnRtnOrder:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&cpp\&\u003Evoid QLCTPTraderSpi::OnRtnOrder(CThostFtdcOrderField *pOrder)\n{\n
if (!pOrder)\n
std::cout && __FUNCTION__ && std::\n
int orderRef = ::atoi(pOrder-&OrderRef);\n
::WaitForSingleObject(ghTradedVolMutex, INFINITE);\n
gOrderRef2TradedVol[orderRef] = pOrder-&VolumeT\n
::ReleaseMutex(ghTradedVolMutex);\n\n
CThostFtdcOrderF\n
memset(&tn, 0, sizeof(CThostFtdcOrderField));\n
memcpy_s(&tn, sizeof(tn), pOrder, sizeof(CThostFtdcOrderField));\n\n
EnterCriticalSection(&g_csdata);\n
orderlist.push_back(tn);\n
LeaveCriticalSection(&g_csdata);\n
SetEvent(hEvent[EID_OnRspOrder]);\n}\n\u003C\u002Fcode\u003E\u003Cp\u003EgOrderRef2TradedVol[orderRef] = pOrder-&VolumeT 这个地方看着就有点奇怪,点到定义发现是这样的:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Estd::map&int, int& gOrderRef2TradedV\n\u003C\u002Fcode\u003E\u003Cp\u003E使用到的地方主要在这里QryTradedVol这个函数:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Eint QryTradedVol(int OrderRef)\n{\n
int ret = -1;\n
::WaitForSingleObject(ghTradedVolMutex, INFINITE);\n
if (gOrderRef2TradedVol.find(OrderRef) != gOrderRef2TradedVol.end())\n
ret = gOrderRef2TradedVol[OrderRef];\n
::ReleaseMutex(ghTradedVolMutex);\\n}\n\u003C\u002Fcode\u003E\u003Cp\u003E看逻辑是根据orderRef查询成交数量的。那么这么写有什么问题呢? 问题大大的有,我们下一个单的数量可能是大于1的,而大于1的时候,是又可能出现部分成交的情况,\u003Cb\u003E\u003Cu\u003E而这里的代码丝毫没有考虑部分成交的情况的处理,这里只是处理了上一次成交,这有事一个会使程序认为的仓位和实际仓位不匹配的情况。\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E哎......我已经无力吐槽了。\u003Cbr\u003E\u003Cbr\u003E这代码问题层出不穷,漏洞百出,真是看不下去了,今天先到这里吧,太恶心了.....\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E\u003Cu\u003E原文4\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E出门运动了一圈,缓了一下,决定还是继续写......讲代码之前说一些无关技术的东西吧。\u003Cbr\u003E\u003Cbr\u003E也许有人想问,这个源码分析系列的写作动机是什么?是为了黑同行露个脸蹭热度吗?\u003C\u002Fp\u003E\u003Cp\u003E不不,一切只为了心中那股浩然正气,金融圈子到处充斥着各类骗子,私以为出了传销之外,骗子最多的行业非金融行业莫属,然作为一个有正气的社会主义接班人,实在没有办法眼睁睁的看着这种骗子到处坑蒙拐骗。\u003Cbr\u003E\u003Cbr\u003E虽然厌恨骗子,但是为了尊重个人隐私,QQ已经涂抹掉了。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cimg src=\&v2-70b059cea17be.png\& data-rawwidth=\&635\& data-rawheight=\&100\&\u003E\u003Cp\u003E 做人就不能脚踏实地吗......去年赚300亿啊,比进去的徐总还屌呢。编笑话能认真严肃一点吗? 类似的言论挺多的,就不一一列举了。现在九年义务教育都普及了,为什么还那么多毫无辨识能力的脑残粉啊......\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cbr\u003E另外有人私信我说:\u003Cp\u003E\&你屌为什么你不fork帮人家改改? 为什么只嘴炮不做实事?\&\u003C\u002Fp\u003E\u003Cp\u003E\&你屌为什么自己不开源个东西? \&\u003C\u002Fp\u003E\u003Cp\u003E这类问题我原本是拒绝回答的,结果这样问的人还挺多,就在这里统一回答一下。\u003C\u002Fp\u003E\u003Cp\u003E不是太明白,为什么要帮个骗子改代码呢,帮他我岂不是共犯? 帮凶? 助纣为虐? 我不理解问这种问题的人到底是怎么想的,所以无论如何,鄙人都不会帮这类骗子改代码的,提这种问题的人也是搞笑!\u003Cbr\u003E\u003Cbr\u003E而对于自己为什么不开源个东西,保密协议在身,是不会有什么金融相关的开源项目的,大家也别期待。\u003C\u002Fp\u003E\u003Cp\u003E好了继续来撸代码,C++部分看不下去了,换个口味看看Python部分好了。\u003C\u002Fp\u003E\u003Cp\u003E同样的, 开始之前先设几个小目标:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E对外宣传的低cpu占用是什么原理?\u003C\u002Fli\u003E\u003Cli\u003E低cpu占用就是所谓的高性能吗?\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cbr\u003E这同学经常吹说quicklib订阅多少多少个行情才占用百分之多少的cpu,我们来一探究竟代码里面是如何实现的,期货行情\u002FRelease\u002FQuickLibDemo.py这里。\u003Cbr\u003E\u003Cp\u003E直接看main函数好了,删除了注释后,剩余代码如下:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Ccode lang=\&python\&\u003Edef main():
#除了从配置文件读取注册服务器地址外,还可用RegisterFront添加注册多个行情服务器IP地址。稍后给出不读配置文件,只使用RegisterFront注册行情服务器地址的例子\n
if False:\n
#已从配置文件读取3个服务器地址,这里可以不添加注册了\n
market.RegisterFront(u\&tcp:\u002F\u002F180.168.146.187:10031\&) #添加注册行情服务器地址1\n
market.RegisterFront(u\&tcp:\u002F\u002F180.168.146.187:10031\&) #添加注册行情服务器地址2\n
market.RegisterFront(u\&tcp:\u002F\u002F180.168.146.187:10031\&) #添加注册行情服务器地址3\n
if True:\n
#订阅品种zn1610,接收Tick数据,不根据Tick生成其他周期价格数据,但可根据AddPeriod函数添加周期价格数据的设置
market.Subcribe(&#x27;zn1705&#x27;)\n
market.Subcribe(&#x27;ag1706&#x27;)\n\n
#配置文件订阅函数下个版本修复,本例暂时采用Subcribe方法订阅\n
market.ReadInstrumentIni()\n
#给au1612添加根据tick生成的周期,尽量避免添加不适用的周期数据,可以降低CPU和内存占用\n
market.AddPeriod(&#x27;ag1706&#x27;,YT_M1)
#添加M3周期(未在Subcribe、Subcribe1~Subcribe8函数中指定的周期,可以在本函数补充该品种周期,可多次调用函数设置同时保存多个周期)\n
market.AddPeriod(&#x27;ag1706&#x27;,YT_M3)
#添加M3周期(未在Subcribe、Subcribe1~Subcribe8函数中指定的周期,可以在本函数补充该品种周期,可多次调用函数设置同时保存多个周期)\n\n
print (&#x27;number:&#x27;,
market.InstrumentNum)\n
#字典保存各个合约tick计数,用于判断多少次tick计算1次策略,默认为0,从0开始计数\n
perdealdict={\&zn1701\&:0,\&cu1701\&:0,\&rb1706\&:0}\n
#打印自动生成的1分钟周期的数据\n
print u&#x27;最近5个1分钟周期值&#x27;\n
print u&#x27;-----------begin--------------&#x27;\n
#打印该品种显示3分钟周期最近5个周期的收盘价格,若价格&0表示已接收到数据,否则还未接收到足够的Tick生成周期K线的数据\n
for i in range(0, 5):\n
tempclose=market.GetPeriodData(&#x27;ag1706&#x27;,YT_M1,YT_CLOSE,i)\n
if tempclose&0:\n
print tempclose\n
print u&#x27;-----------end----------------&#x27;\n
time.sleep(5)\n\u003C\u002Fcode\u003E\u003Cp\u003E其他内容先别看了cpu占用之谜在于time.sleep(5)这一句,这里是sleep 5s啊......什么都不做5s啊,500ms一次tick数据,这其中你错过了10次啊。cpu占用低说明cpu没事干,这一点从来就不是评判性能高低的凭据。我们来搜索一下sleep有多少地方用呢?\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cimg src=\&v2-af85bc6843eac3c315de7f4f.png\& data-rawwidth=\&1085\& data-rawheight=\&465\&\u003E\u003Cp\u003E 基本上所有地方都有在用呢,就问你怕不怕.。\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cbr\u003E那么cpu占用率低就是所谓的高性能吗?\u003Cp\u003E不! 这从来就不是一个充要条件,倘若你的处理逻辑时耗足够低,调用次数不频繁的时候,那么是可以看到较低的cpu占用的,而quicklib这里用sleep是几个意思呢?sleep后thread挂起,这期间什么都干不了,而时间再流逝,行情在发过来,你遗漏掉了那么多行情没有处理,却在鼓吹高性能? 妈的真是又蠢又坏啊......\u003Cbr\u003E\u003Cbr\u003E再来看看期货行情的example\u002F读两种下单交易例子\u002FQuickLibDemo.py这里的main.py:\u003C\u002Fp\u003E\u003Ccode lang=\&python\&\u003Edef main():\n
retLogin = trader.Login()
#调用交易接口元素,通过 “ 接口变量.元素(接口类内部定义的方法或变量) ” 形式调用\n
if retLogin==0:\n
print u&#x27;登陆交易成功&#x27;\n
print u&#x27;登陆交易失败&#x27;\n\n
#读取合约订阅的配置文件\n
market.ReadInstrumentIni()\n
#设置拒绝接收行情服务器数据的时间,有时候(特别是模拟盘)在早晨6-8点会发送前一天的行情数据,若不拒收的话,会导致历史数据错误,本方法最多可以设置4个时间段进行拒收数据\n
market.SetRejectdataTime(0.0, 0.0, NULL, NULL, NULL, NULL)\n\n
print (&#x27;number:&#x27;,
market.InstrumentNum)\n\n
#死循环,反复执行\n
print(u\&Wait for a New Cmd(MD)\\n\&)\n
#判断是否有新Tick数据,while循环不需要Sleep,当没有新Tick时,会处在阻塞状态\n
mddict[market.OnCmd()]()\n
print(u\&Get A New cmd(MD)\\n\&)\n
开仓还是平仓
市价或现价
下单数量\n
#下单函数原型 InsertOrder(self, instrumentID, direction,
offsetFlag, priceType,
OrderRef = trader.InsertOrder(&#x27;zn1705&#x27;, QL_D_Buy, QL_OF_Open, QL_OPT_LimitPrice, market.LastPrice(&#x27;zn1705&#x27;)+10, 1)\n
#交易记录写日志文件\n
#market.LogFile(u&#x27;traderecord.csv&#x27;,u&#x27;交易下单
QL_D_Buy&#x27;)\n
time.sleep(1)\n
#撤销所有未成交的委托单\n
ret = trader.DeleteOrder(&#x27;zn1705&#x27;, OrderRef) \n
OrderRef = trader.InsertOrderByRate(&#x27;zn1705&#x27;, QL_D_Buy, QL_OF_Open, QL_OPT_LimitPrice, market.LastPrice(&#x27;zn1705&#x27;)+10, 0.25,QL_Dynamic_Capital,5)\n
#交易记录写日志文件\n
#market.LogFile(u&#x27;traderecord.csv&#x27;,u&#x27;交易下单
QL_D_Buy&#x27;)\n
time.sleep(1)\n
#撤销所有未成交的委托单\n
ret = trader.DeleteOrder(&#x27;zn1705&#x27;, OrderRef)\n\u003C\u002Fcode\u003E\u003Cp\u003E这里有一个挺有趣的设置时间的函数:\u003C\u002Fp\u003E\u003Ccode lang=\&text\&\u003Emarket.SetRejectdataTime(0.0, 0.0, NULL, NULL, NULL, NULL)\n\u003C\u002Fcode\u003E\u003Cp\u003E真棒,用double来表示时间......真是天马行空的设计啊。\u003C\u002Fp\u003E\u003Cp\u003E这一段代码存在的问题,其他示例里面都存在,比如没有个正经的timer,只会一股脑sleep。到处sleep的代码同步的log,到处都有的std::cout, prinf, std::cerr竟然对外宣传说\&最大的特点就是采用异步式 I\u002FO 与事件驱动的架构设计\&...真是挺可怕的,你当std::cout这些就不是io了吗? 为什么人能够厚颜无耻到这般地步, 又蠢又坏啊......\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E\u003Cimg src=\&v2-083ae627e5591afb9c0ee.png\& data-rawwidth=\&580\& data-rawheight=\&327\&\u003E挣扎了一下, 还是没有办法继续看下去......\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cbr\u003E\u003Ch2\u003E\u003Cb\u003E\u003Cu\u003E写在后面\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fh2\u003E\u003Cp\u003E看到这里,我首先必须对金融民工表示一下感谢:\u003Cb\u003E\u003Cu\u003E这种质量的代码都看完了,还写了非常全面的4篇分析文章,要是我自己全看完估计得吐了,这种毅力不服不行!\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E之前虽然对Quicklib作者的行为感觉挺Low,但他一直信誓旦旦坚称Quicklib的性能显著超过vn.py的自信,让我一度以为人家只是一位性格上比较怪的“技术大神”,希望自己可以通过一个系列的分析文章能取到点经,也来改进下vn.py。\u003C\u002Fp\u003E\u003Cp\u003E不过到现在我基本已经绝望了,浪费了包括一个周末在内前后4天的时间,可能得不到什么有价值的技术改进。从民工的分析中可以很明显看出Quicklib作者的两个情况:\u003C\u002Fp\u003E\u003Cp\u003E1. 没有实盘交易经验,程序内大量的代码存在交易业务逻辑上的错误,这还是相对比较简单的CTP期货接口而已;\u003C\u002Fp\u003E\u003Cp\u003E2. 没有写过生产环境中的量化交易系统,代码逻辑稳健性很低,最多是业余爱好者的范畴,弄了个map来根据委托号查询成交数量的逻辑我真是醉了。\u003C\u002Fp\u003E\u003Cp\u003E同时这几天社区用户和量化圈内的一些朋友,也通过各种渠道告诉了我Quicklib作者以前的一些黑历史,结合自己这几天见识到的他的行为,基本也有了个数。本着专业性的原则就不在我的专栏里说了,有兴趣的朋友可以在这个问题下的回答里看到一些情况:\u003Ca href=\&https:\u002F\u002Fwww.zhihu.com\u002Fquestion\u002F\& data-title=\&如何评价最近vn.py作者和Quicklib作者关于Python量化交易系统在架构设计方面的争论?\& class=\&\& data-editable=\&true\&\u003E如何评价最近vn.py作者和Quicklib作者关于Python量化交易系统在架构设计方面的争论?\u003C\u002Fa\u003E\u003C\u002Fp\u003E\u003Cp\u003E之前已经有不少人提醒我Quicklib作者搞的整个事情是想蹭热度给自己增加曝光度,我开始还觉得不至于。vn.py项目从一开始的时候我就已经表达过会永久保持开源做下去,现在项目的成熟度我觉得也就算上路而已,谈不上有什么成就。但是Quicklib的作者这几天在我的专栏文章和问题回答下面,发一些高度重复的评论,今天已经让人无语到开始直接复制粘贴刷屏,我还真是不得不信了。也懒得在这件事情上再浪费时间,决定直接加黑了事。\u003C\u002Fp\u003E&,&updated&:new Date(&T05:24:40.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:21,&likeCount&:67,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T13:24:40+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic1.zhimg.com\u002Fv2-3ffeffff8982_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:21,&likesCount&:67},&&:{&title&:&vn.py发布v1.6&,&author&:&traderusingpython&,&content&:&之前v1.6预定的是Spread Trading模块的开发,不过因为两个商品期权上市的关系最近比较忙,就选择在v1.6里提前了英文版翻译的开发,接下来的v1.7将会是Spread Trading。\u003Cp\u003E目前完成的主要英文翻译内容包括:\u003C\u002Fp\u003E\u003Cp\u003E1. vn.py的英文介绍\u003Ca href=\&https:\u002F\u002Fgithub.com\u002Fvnpy\u002Fvnpy\u002Fblob\u002Fmaster\u002FREADME-en.md\& data-editable=\&true\& data-title=\&README-en.md\&\u003EREADME-en.md\u003C\u002Fa\u003E\u003C\u002Fp\u003E\u003Cp\u003E2. vn.trader的英文翻译,可以通过VT_settting.json来进行配置,已经翻译的部分包括:\u003C\u002Fp\u003E\u003Cul\u003E\u003Cli\u003E主界面\u003C\u002Fli\u003E\u003Cli\u003E风控模块、合约查询模块、CTA策略模块\u003C\u002Fli\u003E\u003Cli\u003EctpGateway和ibGateway的相关输出\u003C\u002Fli\u003E\u003Cli\u003EvtConstant中的常量\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E基本上实现了对于英文用户来说可以开箱即用,放个截图:\u003Cimg src=\&v2-19edabd0fefb4d4.jpg\& data-rawwidth=\&1936\& data-rawheight=\&1048\&\u003E\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E其他更新包括:\u003C\u002Fp\u003E\u003Cp\u003E\u003Cu\u003E功能部分\u003C\u002Fu\u003E\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E增加合约查询组件的过滤功能\u003C\u002Fli\u003E\u003Cli\u003E重新整理了项目的文件夹配置,所有的API都放到了vn.api目录下,所有vn.trader的接口都放到了gateway目录下\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E\u003Cu\u003E接口方面\u003C\u002Fu\u003E\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E修复CTP接口认证部分的bug\u003C\u002Fli\u003E\u003Cli\u003E增加委托拒单状态STATUS_REJECTED\u003C\u002Fli\u003E\u003Cli\u003E修改ctpGateway的onRspQryInvestorPosition为更加简洁的实现\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E\u003Cu\u003E策略模块方面\u003C\u002Fu\u003E\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E增加TradeBlazer数据导入,感谢社区cooooo的贡献\u003C\u002Fli\u003E\u003Cli\u003E增加对重复成交推送的过滤\u003C\u002Fli\u003E\u003Cli\u003E增加KingKeltner策略的移动止损出场功能\u003C\u002Fli\u003E\u003Cli\u003E增加回测和实盘时对最小合约价格变动的取整\u003C\u002Fli\u003E\u003Cli\u003E增加退出策略模块时询问是否要保存持仓到数据库\u003C\u002Fli\u003E\u003Cli\u003E增加回测时对于涨跌停情况的无法成交过滤\u003C\u002Fli\u003E\u003Cli\u003E增加seaborn优化回测显示效果,感谢社区armtt的贡献\u003C\u002Fli\u003E\u003C\u002Fol\u003E&,&updated&:new Date(&T08:01:08.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:22,&likeCount&:36,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T16:01:08+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic1.zhimg.com\u002Fv2-ed1c5feefaf71ade389606_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:22,&likesCount&:36},&&:{&title&:&vn.py发布v1.6.2&,&author&:&traderusingpython&,&content&:&过去两个月发布的v1.6和v1.6.1给大家带来了很多困扰,主要是因为项目规模扩大后模块间依旧采用的Python隐式相对引用的Import方式,对运行时的目录很敏感,对于不熟悉Python细节的用户很容易发生运行vn.py时找不到某个模块的问题。\u003Cp\u003E试了不少打补丁的方式效果都不怎么样,狠下心花了一个多月的时间将原来计划放在v2.0的重构提前,将整个项目结构进行了重新设计,并将所有的py文件间采用绝对引用的Import方式,并且将vn.py项目安装到Python的site-package目录下,使得用户现在可以采用更加灵活的方式来管理自己的多个量化交易应用程序。\u003C\u002Fp\u003E\u003Cp\u003E其他的一些更新包括:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E提供build.bat一键安装和pip快速安装两种安装方式,大幅降低入门时的痛苦程度(相信我真的效果很明显)\u003C\u002Fli\u003E\u003Cli\u003E新增中信证券期权接口cshshlp,这个对于一些和中信有较多战略合作的私募机构会比较有用\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E使用qtpy模块来代替PyQt4,实现项目中的GUI代码对PyQt4和PyQt5的兼容性\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E将底层接口模块gateway和上层应用模块app对外暴露的API部分标准化,方便用户根据自己的需求自行加载需要的模块,构建自己定制化的VnTrader\u003Cbr\u003E\u003C\u002Fli\u003E\u003Cli\u003E将一些逐步淘汰的代码移到archive目录下\u003C\u002Fli\u003E\u003Cli\u003E修复了一些大大小小的bug\u003Cbr\u003E\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cbr\u003E\u003Cp\u003E这次v1.6.2的更新对vn.py项目来说算是个比较大的结构调整,对于用户来说vn.py的使用方式将会从以前接近Spyder的单一应用程序,逐渐过渡到接近Flask的开发框架,更多的鼓励用户根据自己的需求来使用vn.py构建定制化的量化交易程序。\u003C\u002Fp\u003E\u003Cp\u003E最后终于也算是解决了长期以来的一个心头刺,离承诺完成v1.7 SpreadTrading模块的时间不到一个月了,加紧干活。\u003C\u002Fp\u003E&,&updated&:new Date(&T14:39:47.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:53,&likeCount&:101,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T22:39:47+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic3.zhimg.com\u002Fv2-0efa_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:53,&likesCount&:101},&&:{&title&:&用Python的交易员的Live--vn.py的过去、现在和将来&,&author&:&traderusingpython&,&content&:&我是用 python 的交易员,知乎Python和量化交易话题的优秀回答者,金融工程硕士,目前在均直资产担任期权业务主管。同时我也是开源量化交易框架vn.py的作者,项目目前是国内用户最多的量化交易开源项目之一。 \n\u003Cp\u003Evn.py项目在Github上的Star数量已经突破3287,我本人在知乎上前后加起来也已经开过4次Live了,终于有信心来讲一讲自己最为得意的作品vn.py。 \n\u003C\u002Fp\u003E\u003Cp\u003E过去两年Python在国内的量化投资领域经历了一波飞速的发展,涌现出了一系列的开源和商业软件。不同软件在设计定位上有着较大的区别,有的侧重于数据分析,有的侧重于策略研究,而vn.py则是以量化交易的最后一步环节实盘交易作为切入点构建的全套架构。\u003C\u002Fp\u003E\u003Cp\u003E作为项目的作者,在之前的Live中和知乎私信里也经常被问到一些关于vn.py的设计、使用、未来计划等等问题,因为时间的关系大多只能简单回答,所以希望通过这场Live让大家可以对vn.py有个比较全面的了解。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E本次Live的内容会围绕vn.py展开: \u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E过去 \u003C\u002Fli\u003E\u003Col\u003E\u003Cli\u003E项目的设计理念 \u003C\u002Fli\u003E\u003Cli\u003E早期开发过程 \u003C\u002Fli\u003E\u003Cli\u003E 针对的用户群体(交易员) \u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cli\u003E现在 \u003C\u002Fli\u003E\u003Col\u003E\u003Cli\u003E目前的开发进度 \u003C\u002Fli\u003E\u003Cli\u003E如何一步步来学习整个框架 \u003C\u002Fli\u003E\u003Cli\u003E如何通过社区获取帮助 \t\u003C\u002Fli\u003E\u003Cli\u003E基于vn.py的实盘策略应用:CTA、波动率交易、价差交易、算法交易等 \u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cli\u003E将来\u003C\u002Fli\u003E\u003Col\u003E\u003Cli\u003E项目的开源可持续性 \u003C\u002Fli\u003E\u003Cli\u003E和金融机构的战略合作 \u003C\u002Fli\u003E\u003Cli\u003E未来一年的社区活动计划\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003C\u002Fol\u003E\u003Cbr\u003E\u003Cp\u003E【传送门】\u003Ca href=\&https:\u002F\u002Fwww.zhihu.com\u002Flives\u002F573888?utm_source=qq&utm_medium=social\& data-editable=\&true\& data-title=\&知乎 Live - 全新的实时问答\& class=\&\&\u003E知乎 Live - 全新的实时问答\u003C\u002Fa\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T06:38:54.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:11,&likeCount&:35,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T14:38:54+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic2.zhimg.com\u002Fv2-a4a4d4b5ac6c35bb8c9dee_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:11,&likesCount&:35},&&:{&title&:&华尔街见闻成为vn.py项目的战略合作伙伴&,&author&:&traderusingpython&,&content&:&\u003Cp\u003E随着vn.py项目的快速发展,社区成员变得越来越多样,也逐渐出现了一些全新的需求,例如项目学习培训、历史行情数据、特定策略的专用交易通道、文档的编写和维护等等。但是因为个人能力的关系(交易员出身的我主要也就擅长做做交易和写写Python程序),挺多的需求都处于一种悬而未决的状态。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E参考其他一些成功开源项目的发展历史后,意识到现在vn.py项目需要开始寻找战略合作上的伙伴,来更好的满足社区不断增长的需求。幸运的是在过去两年多的时间里,vn.py项目也吸引到了一部分国内金融机构的注意,并且这些机构有兴趣参与到项目的开源维护中来。\u003C\u002Fp\u003E\u003Cp\u003E在今天,日,华尔街见闻宣布正式加入vn.py开源量化交易社区,与vn.py在量化投资领域共同合作,支持全面推进与开拓量化投资在国内金融领域的健康发展,致力于聚集和培养更多量化投资领域的人才(原文链接:\u003Ca href=\&https:\u002F\u002Fwallstreetcn.com\u002Farticles\u002F3020402\& class=\&\& data-editable=\&true\& data-title=\&华尔街见闻正式加入vn.py开源量化交易社区 - 华尔街见闻\&\u003E华尔街见闻正式加入vn.py开源量化交易社区 - 华尔街见闻\u003C\u002Fa\u003E)。\u003C\u002Fp\u003E\u003Cbr\u003E\u003Cp\u003E双方计划的合作内容上包括一系列线上和线下的活动,结合vn.py社区在量化技术方面以及华尔街见闻在内容生产方面的优势,为社区成员提供更好的学习材料以及交流渠道。目前已经推出的是《量化投资24小时》专辑,主要面对的读者是希望通过Python在量化交易领域有所建树的初学者,结合视频和图文的形式提供更通俗易懂的学习效果,并通过由华尔街见闻社群运营团队维护的微信群来为读者提供一个高效的学习和交流渠道(专辑链接:\u003Ca href=\&https:\u002F\u002Fwallstreetcn.com\u002Fpremium\u002Ftopics\u002F1000157\& data-editable=\&true\& data-title=\&华尔街见闻Premium - 华尔街见闻Premium\& class=\&\&\u003E华尔街见闻Premium - 华尔街见闻Premium\u003C\u002Fa\u003E)。\u003C\u002Fp\u003E\u003Cp\u003E未来vn.py项目也会继续寻找其他的战略合作伙伴来更好的满足开源量化社区的各种需求,同时也计划在每个具体的领域只考虑和一家机构建立合作关系(为了双方都能全心全意的投入在合作上),有兴趣的朋友欢迎联系我。\u003C\u002Fp\u003E&,&updated&:new Date(&T13:30:48.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:5,&likeCount&:61,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T21:30:48+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic2.zhimg.com\u002Fv2-fc22d9865_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:5,&likesCount&:61},&&:{&title&:&上海中期成为vn.py项目的战略合作伙伴&,&author&:&traderusingpython&,&content&:&继上周华尔街见闻后,vn.py项目迎来了第二位战略合作伙伴上海中期期货:\u003Cblockquote\u003E上海\u003Ca href=\&http:\u002F\u002Fwww.shcifco.com\u002F?key=zq\& data-editable=\&true\& data-title=\&中期\&\u003E\u003Cu\u003E中期\u003C\u002Fu\u003E\u003C\u002Fa\u003E期货于2017年6月和vn.py开始初步合作,并决定在日正式加入vn.py开源量化交易社区,成为战略合作伙伴。双方致力于推广Python在国内量化投资领域的实战应用,为广大用户提供更多精细化和定制化的解决方案。\u003Cbr\u003E\u003Cbr\u003E作为国内最资深的量化交易专精期货公司,上海中期多年来一直在全面支持和推进量化投资在国内期货市场的发展。上海中期积极参与VN.PY项目的建设,目前已经在历史行情服务,自动回测等技术上进行了深入的合作开发。并在vn.py社区论坛“维恩的派”(\u003Ca href=\&http:\u002F\u002Fwww.vnpie.com\& data-editable=\&true\& data-title=\&论坛 - Powered by Discuz!\&\u003E论坛 - Powered by Discuz!\u003C\u002Fa\u003E)中设立了专栏。除了在技术服务方面深入拓展外,上海中期旗下的互联网金融教育品牌“金领学堂”(\u003Ca href=\&http:\u002F\u002Fwww.jinlingxuetang.com\& data-editable=\&true\& data-title=\&金领学堂 - 首页\&\u003E金领学堂 - 首页\u003C\u002Fa\u003E)还将与vn.py在投资者教育等多领域展开合作。\u003C\u002Fblockquote\u003E\u003Cp\u003E(原文链接:\u003Ca href=\&http:\u002F\u002Fwww.shcifco.com\u002Fhtml\u002Fxinxigongshi\u002Fzjshzq\u002Fdtbb\u002F25\u002F33593.html\& data-title=\&上海中期期货正式加入vn.py开源量化交易社区\& class=\&\& data-editable=\&true\&\u003E上海中期期货正式加入vn.py开源量化交易社区\u003C\u002Fa\u003E)\u003C\u002Fp\u003E\u003Cp\u003E以后历史行情数据怎么获取再也不会是社区里问得最多的问题了,此时此刻,作为项目的作者,我的心情是这样的:\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cimg src=\&v2-39db9eedd86.jpg\& data-rawwidth=\&630\& data-rawheight=\&630\&\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T11:56:20.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:15,&likeCount&:53,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T19:56:20+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic3.zhimg.com\u002Fv2-8db1dfb3db29dd7ad5ffe656_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:15,&likesCount&:53},&&:{&title&:&vn.py发布v1.7 - SpreadTrading&,&author&:&traderusingpython&,&content&:&\u003Cp\u003E先来说说这篇文章的标题配图,图里的是美国Trading Technologies公司TT交易系统的AutoSpreader功能,目前世界上功能最强大的价差交易软件之一,一些主要的功能特点包括:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E提供极高自由度的自定义价差,表现在:任意合约、任意市场、任意公式\u003C\u002Fli\u003E\u003Cli\u003E每个价差支持最多50条腿,同时允许在最多10条腿上同时报价\u003C\u002Fli\u003E\u003Cli\u003E价差配置和交易算法均运行于交易所内托管的服务器上,实现超低延时交易\u003C\u002Fli\u003E\u003Cli\u003E允许在系统内置算法规则的基础上自行开发各种条件细节\u003C\u002Fli\u003E\u003Cli\u003E用户可以使用策略应用来驱动AutoSpreader中的各种价差交易算法,实现全自动交易\u003C\u002Fli\u003E\u003Cli\u003EGUI方面包括价差梯度报价显示和交易界面,将自定义价差和每条腿上的流动性清晰地表现出来\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E参考AutoSpreader的功能,vn.py项目在v1.7版本中实现了SpreadTrading模块,整体上将价差交易的整个业务逻辑抽象为三层:价差的计算(行情、持仓)、价差算法(交易执行)和价差策略(尚未完成),并针对Python的特点以及国内市场的情况作了一些调整:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E允许创建任意合约、任意市场的价差,公式方面目前仅实现了各条腿相加减\u003C\u002Fli\u003E\u003Cli\u003E每个价差支持一条主动腿以及任意数量的被动腿,但仅允许在主动腿上报价\u003C\u002Fli\u003E\u003Cli\u003E实现标准的价差算法交易开发模板,并提供了狙击算法(SniperAlgo)作为开发示例\u003C\u002Fli\u003E\u003Cli\u003E对于所有的交易算法,用户只需设置价差交易的目标价格(buy、sell、short、cover)、最大限仓、每轮下单数以及交易方向等配置,算法即可完成自动交易\u003C\u002Fli\u003E\u003Cli\u003E价差策略层则负责基于目前的市场价格情况计算交易信号,来调整对应价差算法的价格和数量配置(目前尚未完成,计划v1.8推出)\u003C\u002Fli\u003E\u003Cli\u003EGUI界面上包括价差的行情和持仓显示、交易算法管理以及算法状态日志输出,不打算提供类似AutoSpreader的梯度工具(对于Python来说,开发这类需要极高响应的界面有一定压力)\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cp\u003E应该说SpreadTrading才初步完成,不足的地方还很多,接下来会根据社区的反馈快速迭代上去。其他的一些更新内容包括CTA策略模板的StopOrder相关推送、CTA策略回测中基于逐日盯市的盈亏统计模式等内容,细节可以直接在这里看:\u003Ca href=\&https:\u002F\u002Fgithub.com\u002Fvnpy\u002Fvnpy\u002Freleases\&\u003EGithub Release\u003C\u002Fa\u003E。\u003C\u002Fp\u003E\u003Cp\u003E2017年的开发计划里比较重要的还剩Web界面(包括Docker实现)和完整的海龟策略(数据处理、策略回测、信号生成、算法交易)两个部分,由于海龟需要的数据问题暂时还没得到解决,在v1.8中就准备先开发Web界面了。\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003C\u002Fp\u003E&,&updated&:new Date(&T14:57:00.000Z&),&canComment&:false,&commentPermission&:&anyone&,&commentCount&:16,&likeCount&:96,&state&:&published&,&isLiked&:false,&slug&:&&,&isTitleImageFullScreen&:false,&rating&:&none&,&sourceUrl&:&&,&publishedTime&:&T22:57:00+08:00&,&links&:{&comments&:&\u002Fapi\u002Fposts\u002F2Fcomments&},&url&:&\u002Fp\u002F&,&titleImage&:&https:\u002F\u002Fpic2.zhimg.com\u002Fv2-c74cab2ac252cbd7f1eb11_r.jpg&,&summary&:&&,&href&:&\u002Fapi\u002Fposts\u002F&,&meta&:{&previous&:null,&next&:null},&snapshotUrl&:&&,&commentsCount&:16,&likesCount&:96},&&:{&title&:&vn.py发布v1.7.1 - CTA策略模块升级版&,&author&:&traderusingpython&,&content&:&\u003Cp\u003E前后忙活了两个月,终于算是完成发布了v1.7.1的版本。这次新版本主要针对的是CTA策略相关的功能,按照几个主要的方向来介绍下。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E\u003Cu\u003E交易委托的开平仓自动转化功能\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E之前使用VnTrader来跑CTA交易策略,下单开平仓方面有两个让用户比较头疼的问题:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E上期所合约的平今、平昨指令必须分开发送,无法像其他交易所一个平仓委托自动都平掉\u003C\u002Fli\u003E\u003Cli\u003E某些有平今手续费惩罚的合约,需要使用锁仓交易模式:\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cul\u003E\u003Cli\u003E优先平昨\u003C\u002Fli\u003E\u003Cli\u003E无昨或者有反向今仓则开仓\u003C\u002Fli\u003E\u003Cli\u003E禁止平今\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cp\u003E这两个问题需要策略程序在下单时,知道当前账户持仓中实时的今、昨、总仓的数量和可平量。而原本VnTrader底层的持仓情况是通过CTP接口的持仓查询接口轮询(默认4秒一次)来实现的,存在持仓数据延时的情况。所以就需要用户自行在策略程序中使用数据库仓位同步功能和成交推送,来维护一个当前的实时持仓情况。\u003C\u002Fp\u003E\u003Cp\u003E上面这段话读着有点绕人,总之就是原本觉得应该交给vn.py用户去自行把握的细粒度挂撤单操作,很多人在写的时候遭遇了比较大的困难,以至于只有少量水平比较高的用户才实现了如rb(上期所品种)、IF(平今惩罚)等品种的隔夜交易策略,大部分人只能选择绕过这些品种。\u003C\u002Fp\u003E\u003Cimg src=\&v2-6e475de445d3d7ceb27c.jpg\& data-caption=\&\& data-rawwidth=\&387\& data-rawheight=\&200\&\u003E\u003Cp\u003E开始时我觉得只是大家还在摸索,差不多一年时间过去后我才意识到是自己的思路问题:\u003Cb\u003E\u003Ci\u003E大部分用户只是想做量化交易,而不是去搞明白国内各个交易所规则里的坑!!!\u003C\u002Fi\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E最后决定将这块的功能做成标准化的实现:\u003C\u002Fp\u003E\u003Col\u003E\u003Cli\u003E在DataEngine中实现本地持仓数据缓存功能,基于持仓查询、成交推送、委托挂撤单来实时计算当前所有仓位的持仓量、冻结量和可用量的数据\u003C\u002Fli\u003E\u003Cli\u003E通过缓存对象实现委托开平仓自动转换功能,将上层的开平仓请求根据实时持仓情况转化成底层需要发出的委托,主要提供三种模式:\u003C\u002Fli\u003E\u003C\u002Fol\u003E\u003Cul\u003E\u003Cli\u003E普通模式(MODE_NORMAL ):\u003C\u002Fli\u003E\u003Cul\u003E\u003Cli\u003E什么转换都不做,直接发出\u003C\u002Fli\u003E\u003Cli\u003E大部分合约默认使用该模式\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cli\u003E上期所模式(MODE_SHFE):\u003C\u002Fli\u003E\u003Cul\u003E\u003Cli\u003E将平仓委托自动根据今昨仓情况拆分,优先平今、今仓不足则平昨\u003C\u002Fli\u003E\u003Cli\u003E上期所合约默认使用该模式\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003Cli\u003E平今惩罚模式(MODE_TDPENALTY ):\u003C\u002Fli\u003E\u003Cul\u003E\u003Cli\u003E反向有昨仓且无今仓时优先平昨\u003C\u002Fli\u003E\u003Cli\u003E反向有今仓或无昨仓时改为开仓\u003C\u002Fli\u003E\u003Cli\u003E禁止平今\u003C\u002Fli\u003E\u003Cli\u003E需要在VT_setting.json里配置实用该模式的合约\u003C\u002Fli\u003E\u003C\u002Ful\u003E\u003C\u002Ful\u003E\u003Cp\u003E最后达成的效果就是用户在开发CTA策略模块时,无需再去管今、昨仓的问题,直接发单就行。\u003C\u002Fp\u003E\u003Cp\u003E\u003Cbr\u003E\u003C\u002Fp\u003E\u003Cp\u003E\u003Cb\u003E\u003Cu\u003EK线合成器和时间序列管理器\u003C\u002Fu\u003E\u003C\u002Fb\u003E\u003C\u002Fp\u003E\u003Cp\u003E和上一个问题类似,也是太过追求自由度,把Tick合成1分钟线、1分钟线合成X分钟线的逻辑完全暴露给用户去实现(比如允许1分钟线切分以37秒而非0秒作为分割点),结果很多用户踩坑爬不出来。\u003C\u002Fp\u003E\u003Cp\u003E增加了ctaTemplate.py中的BarManager(K线合成器)和ArrayManager(K线时间序列管理器)后,现在写简单CTA策略的代码在行数上已经非常接近于MultiCharts的EasyLanguage了(顺道说一句我也是MC粉丝,长期推荐给刚入门的量化新手用),策略的主要业务逻辑写在onXminBar里就行:\u003C\u002Fp\u003E\u003Ccode lang=\&python\&\u003E
#----------------------------------------------------------------------\n
def onTick(self, tick):\n
\&\&\&收到行情TICK推送(必须由用户继承实现)\&\&\& \n
self.bm.updateTick(tick)
# bm是一个合成5分钟K线的BarManager对象\n\n
#----------------------------------------------------------------------\n
def onBar(self, bar):\n
\&\&\&收到Bar推送(必须由用户继承实现)\&\&\&\n
self.bm.updateBar(bar)\n
#----------------------------------------------------------------------\n
def onXminBar(self, bar):\n
\&\&\&收到X分钟K线\&\&\&\n
# 全撤之前发出的委托\n
self.cancelAll()\n
# 保存K线数据\n
am = self.am
# am是一个ArrayManager对象\n
am.updateBar(bar)\n
if not am.inited:\n
# 计算指标数值\n
self.bollUp, self.bollDown = am.boll(self.bollWindow, self.bollDev)\n
self.cciValue = am.cci(self.cciWindow)\n
self.atrValue = am.atr(self.atrWindow)\n
# 判断是否要进行交易\n
# 当前无仓位,发送开仓委托\n
if self.pos == 0:\n
self.intraTradeHigh = bar.high\n
self.intraTradeLow = bar.low
if self.cciValue & 0:\n
self.buy(self.bollUp, self.fixedSize, True)\n
elif self.cciValue & 0:\n
self.short(self.bollDown, self.fixedSize, True)\n
# 持有多头仓位\n
elif self.pos & 0:\n
self.intraTradeHigh = max(self.intraTradeHigh, bar.high)\n
self.intraTradeLow = bar.low\n
self.longStop = self.intraTradeHigh - self.atrValue * self.slMultiplier\n
self.sell(self.longStop, abs(self.pos), True)\n
# 持有空头仓位\n
elif self.pos & 0:\n
self.intraTradeHigh = bar.high\n
self.intraTradeLow = min(self.intraTradeLow, bar.low)\n
self.shortStop = self.intraTradeLow + self.atrValue * self.slMultiplier\n
self.cover(self.shortStop, abs(self.pos), True)\n
# 发出状态更新事件\n
self.putEvent()
\u003C\u002Fcode\u003E\u003Cp\u003E以上代码截取自strategyBollChannel.p

我要回帖

更多关于 vnpy 的文章

 

随机推荐