diff --git a/.gitignore b/.gitignore index 9fd1b1cc..1c245f5d 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,7 @@ Release/ *.local *.temp *.vt -*.dat + vn.ctp/build/* vn.lts/build/* .idea diff --git a/vnpy/api/cshshlp/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat b/vnpy/api/cshshlp/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat new file mode 100644 index 00000000..8effa775 Binary files /dev/null and b/vnpy/api/cshshlp/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat differ diff --git a/vnpy/api/cshshlp/CITICs_HsT2Hlp.dll b/vnpy/api/cshshlp/CITICs_HsT2Hlp.dll new file mode 100644 index 00000000..ab3c99af Binary files /dev/null and b/vnpy/api/cshshlp/CITICs_HsT2Hlp.dll differ diff --git a/vnpy/api/cshshlp/Hsconfig.ini b/vnpy/api/cshshlp/Hsconfig.ini new file mode 100644 index 00000000..90bc131c --- /dev/null +++ b/vnpy/api/cshshlp/Hsconfig.ini @@ -0,0 +1,146 @@ +[t2sdk] + +; 客户端要连接的服务端的IP和端口,可以配置一个或多个,中间以;分割,连接初始化时,会从这串服务端地址中,随即选择一个作为要建立连接的服务端 + +;servers=10.23.179.15:20008 + +;联通请使用这个地址: + +;servers=118.192.134.124:20008 + +;电信请使用这个地址: + +servers=124.207.9.124:20008 + +; 接收缓存的初始大小,单位字节,实际接收到服务端的数据时,可能会扩大(如果需要) + +init_recv_buf_size=512 + + + +; 每块发送缓存的初始大小,单位字节,该大小也会根据需要动态扩大 + +init_send_buf_size=512 + + + +; 发送队列的大小,该大小不会动态变化,若该配置项很小,且连接发包很频繁,则可能 + +; 因为发送队列满而造成发送失败 + +send_queue_size=1000 + + + +; lang用于指定T2_SDK错误信息的语言ID(2052为简体中文,1033为英文) + +; 默认为2052 + +lang=2052 + + + +; 此配置项请参看“注意事项” + +event_count=10 + + + +; 许可证文件的路径,默认为当前目录下的license.dat。 + +license_file=(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat + + + +;第三方许可证密码 + +license_pwd=999999 + + + +; 客户端给服务端发送心跳的间隔时间,单位为秒,最小值为5秒 + +; 不配或者配<=0,表示不开启客户端心跳 + +heartbeat_time=5 + + + + + +;t2sdk开发包取本机IP和MAC地址,值为1表示t2sdk与服务端建立连接的时候要带上IP和MAC,其它任何值都不会带IP和MAC地址信息 + +addipmac=1 + + + +[proxy] + +; 可配置采用何种代理配置http/socks4/socks5,空表示不采用代理 + +proxy_type= + + + +; 代理服务器的IP地址 + +ip= + +port= + + + +; 登陆代理服务器的用户名 + +user_name=guest + +password= + + + +[safe] + +; 连接的安全模式,明文(none),通信密码(pwd),SSL(ssl) + +; 注意大小写敏感 + +safe_level=ssl + + + +; 当连接的安全模式为pwd时,client_id配置项才生效 + +client_id= + + + +; 在pwd模式下,当client_id为空时,comm_pwd为默认的密钥 + +; 注意当client_id为空时,comm_pwd必须和服务端的配置一致方可正常使用,目前服务 + +; 端的配置为888888 + +comm_pwd=999999 + + + +; 当连接的安全模式为ssl时,cert_file和cert_pwd配置项才生效 + +; 证书文件路径 + +cert_file=s2013.pfx + +cert_pwd=999999 + + + + + +; 是否校验服务端,可不配,若不配,默认校验服务端 + +check_server_cert= + + + + + diff --git a/vnpy/api/cshshlp/__init__.py b/vnpy/api/cshshlp/__init__.py new file mode 100644 index 00000000..e1ff327f --- /dev/null +++ b/vnpy/api/cshshlp/__init__.py @@ -0,0 +1,3 @@ +# encoding: UTF-8 + +from vncshshlp import CsHsHlp \ No newline at end of file diff --git a/vnpy/api/cshshlp/csapi.ini b/vnpy/api/cshshlp/csapi.ini new file mode 100644 index 00000000..c684d125 --- /dev/null +++ b/vnpy/api/cshshlp/csapi.ini @@ -0,0 +1,38 @@ +[csapi] +log_path=.\\cslog\ + +biz_trace=2 +; 0: 不记录日志; +; 1: 只记录错误请求参数日志 +; 2: 记录所有请求参数日志, 默认值; +; 4: 记录所有请求参数日志,并且记录t2sdk的二进制请求包 +; 8: 并且记录t2sdk的二进制应答包,调试使用。 + +error_trim = 11 +;错误信息格式化,0:不处理;1:只过滤"表记录"提示;11:在1的基础上过滤&&后面的参数 +;默认为0 + +update_site=10.1.1.1:21001 +;自动升级服务器IP及端口 + +license_file=csauthor.dat +; CITICs_HsT2Hlp.dll接口许可证文件名称,不含路径 + +[connection] +connect_timeout=10 +; 中间件连接超时时间,单位:S,默认时间10s + +biz_timeout=15 +; 业务请求超时时间,单位:S,默认时间10s + +op_site_prefix= +;操作站点前缀,默认为空。可以配置长度不超过8个字符的字符串 + +[func_log] +; 该配置与[biz_trace] 选项两者取大值 +; 功能号, 日志标识 1:只记录错误; 2:记录请求数据; 4:记录请求/应答(top2) 8:记录请求/应答数据(完整) + +;func_01=331100,4 +;func_02=333002,4 +;func_03=339306,2 +;func_04=333104,4 diff --git a/vnpy/api/cshshlp/csauthor.dat b/vnpy/api/cshshlp/csauthor.dat new file mode 100644 index 00000000..f8dcf012 --- /dev/null +++ b/vnpy/api/cshshlp/csauthor.dat @@ -0,0 +1,16 @@ +[auth_info] +ProfileCode=8cb1c6d660013b4277abe5a4c51836b3 +LimitDate=20300101 +AllowPushTransation=0 +AllowWbp=0 +AuthCode=AQAAAABo23BjZjkxZDczMGQyN2I2MzI0NmI0NzRhMGIwYzg5ZDg0OQAAAAAAAAAAAAAAAA== +[functions] +func= +;[ProcessInfo_0] +;ProcessName=HsT2Hlp_Demo.exe,Hs.exe +;NetIP=172.23.123.9 +;NetMask=255.255.255.0 +;[ProcessInfo_0] +;ProcessName=Option_Demo.exe +;NetIP=10.0.0.0 +;NetMask=255.0.0.0 diff --git a/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.dll b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.dll new file mode 100644 index 00000000..ab3c99af Binary files /dev/null and b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.dll differ diff --git a/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.h b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.h new file mode 100644 index 00000000..fe0fd486 --- /dev/null +++ b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.h @@ -0,0 +1,141 @@ +#ifndef __CITICS_HSHLP_H__ +#define __CITICS_HSHLP_H__ + +#ifdef WIN32 +#ifdef CITICS_HSHLP_EXPORTS +#define CITICS_HSHLP_API __declspec(dllexport) +#else +#define CITICS_HSHLP_API __declspec(dllimport) +#endif + +#define CITICSSTDCALL __stdcall /* ensure stcall calling convention on NT */ +#else +#define CITICS_HSHLP_API +#define CITICSSTDCALL /* leave blank for other systems */ +#endif + +#define ERROR_MSG_SIZE 512 +////////////////////////////////////////////////////////////////////////// + +/** +* 同步业务调用 +* 使用该标识调用业务时,系统处于阻塞状态直到返回应答信息或超时 +*/ +#define BIZCALL_SYNC 0 + +/** +* 异步业务调用 +* 使用该标识调用业务时,系统立即返回而不等待应答信息。 +* 需要调用QueueGetMsg获取应答结果信息 +*/ +#define BIZCALL_ASYNC 1 + +/** +* 订阅消息中心发布的消息信息 +* 标识该业务为消息订阅请求。如订阅成交推送数据、系统通知消息等 +* 需要调用QueueGetMsg获取订阅的信息 +*/ +#define BIZCALL_SUBSCRIBE 3 + +typedef void *HSHLPCFGHANDLE; +typedef void *HSHLPHANDLE; +typedef void *HSHLPASYNCMSG; + +#pragma pack(1) + +/* 异步和订阅消息控制信息*/ +typedef struct +{ + int nFlags; // 位标识信息,0x0:正常消息, >0:系统状态消息 + int nFuncID; // 异步请求功能号 + int nReqNo; // 异步请求接受序号,根据该序号和功能号对请求和应答数据匹配 + int nIssueType; // 发布消息类别 + int nErrorNo; // 错误代码 + HSHLPASYNCMSG HAsyncMsg; // 消息句柄 + char szErrorInfo[ERROR_MSG_SIZE+1]; // 错误信息 +}MSG_CTRL, *LPMSG_CTRL; + +#pragma pack() + + +#ifdef __cplusplus +extern "C" +{ +#endif + + // 初始化配置项,szConfigFile为空时则按系统默认值初始化,hConfig为出参 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_InitConfig(HSHLPCFGHANDLE* hConfig, const char* szConfigFile=NULL); + + // 加载配置文件项,可以加载多个不同的配置文件,返回不同的配置句柄。等同于InitConfig + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_LoadConfig(HSHLPCFGHANDLE* hConfig, const char* szConfigFile); + + // 重置服务器连接地址。格式:ip1:port1;ip2:port2; + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_ResetServer(HSHLPCFGHANDLE hConfig, const char* szAddr); + + // 根据配置句柄,初始化一个连接对象。 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_Init(HSHLPHANDLE* HlpHandle, HSHLPCFGHANDLE hConfig); + // 释放连接句柄系统资源 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_Exit(HSHLPHANDLE HlpHandle); + + // 与服务器建立连接 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_ConnectServer(HSHLPHANDLE HlpHandle); + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_DisConnect(HSHLPHANDLE HlpHandle); + + // 提交业务请求,如果szParam参数为NULL,则认为是通过SetValue函数设置的请求参数 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_BizCallAndCommit(HSHLPHANDLE HlpHandle, int iFuncID, const char* szParam=NULL, int nBizCallType=BIZCALL_SYNC, LPMSG_CTRL lpMsgCtrl=NULL); + + // 获取记录行、列数,返回值为行、列数 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetRowCount(HSHLPHANDLE HlpHandle, LPMSG_CTRL lpMsgCtrl=NULL); + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetColCount(HSHLPHANDLE HlpHandle, LPMSG_CTRL lpMsgCtrl=NULL); + + // 获取字段名称,序号以0为基数 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetColName(HSHLPHANDLE HlpHandle, int iColumn, char* szColName, LPMSG_CTRL lpMsgCtrl=NULL); + + // 获取下一行记录,第一次调用则首先打开结果集,并把第0行作为当前记录行 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetNextRow(HSHLPHANDLE HlpHandle, LPMSG_CTRL lpMsgCtrl=NULL); + + // 根据字段名称,获取字段值 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetValue(HSHLPHANDLE HlpHandle, const char* szKeyName, char* szValue, LPMSG_CTRL lpMsgCtrl=NULL); + + // 根据字段序号获取字段值,序号以0为基数 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetValueByIndex(HSHLPHANDLE HlpHandle, int iColumn, char* szValue, LPMSG_CTRL lpMsgCtrl=NULL); + + // 获取当前错误代码和信息 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_GetErrorMsg(HSHLPHANDLE HlpHandle, int* piErrorCode, char* szErrorMsg); + + + /************************************************************************/ + // 另一种请求参数设置的方法,一个一个的设置。 + // 初始化请求参数 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_BeginParam(HSHLPHANDLE HlpHandle); + // 设置每个请求参数字段名称和值 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_SetValue(HSHLPHANDLE HlpHandle, const char* szKeyName, const char* szValue); + + + /************************************************************************/ + // 异步请求和消息订阅相关函数 + + // 获取异步消息队列中的消息数量 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_QueueMsgCount(HSHLPHANDLE HlpHandle); + + // 从队列中读取一条消息,如果队列中没有数据,该函数会一直阻塞不返回,直到nWaitTime超时时间后才返回。 + // nWaitTime: 单位毫秒 + // = 0: 立即返回;如果队列中有数据则返回Msg,且return值为 0,否则return值为-5(超时错误) + // =-1: 阻塞,直到队列中有数据获取到Msg 才返回。否则将永久阻塞等待。return值为 0, + // = 其它值:超时时间,如果队列中有数据则立即返回,否则等待time时间后返回。return值为 -5(超时错误)。 + // Return: 0: 队列中有数据且获取消息成功; + // -5: 超时错误,在设定的时间内队列中没有数据。 + // 其它错误: + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_QueueGetMsg(HSHLPHANDLE HlpHandle, LPMSG_CTRL lpMsgCtrl /*Out*/, int nWaitTime=0); + + // 处理完成或者不需要该消息时,应及时删除该消息,否则消息将占用大量内存。 + // 如果不删除有可能每次都Get到同一条消息 + CITICS_HSHLP_API int CITICSSTDCALL CITICs_HsHlp_QueueEraseMsg(HSHLPHANDLE HlpHandle, LPMSG_CTRL lpMsgCtrl /*In*/); + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.lib b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.lib new file mode 100644 index 00000000..159f5c18 Binary files /dev/null and b/vnpy/api/cshshlp/hshlp/CITICs_HsT2Hlp.lib differ diff --git a/vnpy/api/cshshlp/hshlp/Hsconfig.ini b/vnpy/api/cshshlp/hshlp/Hsconfig.ini new file mode 100644 index 00000000..7f986e97 --- /dev/null +++ b/vnpy/api/cshshlp/hshlp/Hsconfig.ini @@ -0,0 +1,53 @@ +[t2sdk] +; 客户端要连接的服务端的IP和端口,可以配置一个或多个,中间以;分割,连接初始化时,会从这串服务端地址中,随即选择一个作为要建立连接的服务端 +servers=114.251.228.136:20008 +; 接收缓存的初始大小,单位字节,实际接收到服务端的数据时,可能会扩大(如果需要) +init_recv_buf_size=512 + +; 每块发送缓存的初始大小,单位字节,该大小也会根据需要动态扩大 +init_send_buf_size=512 + +; 发送队列的大小,该大小不会动态变化,若该配置项很小,且连接发包很频繁,则可能 +; 因为发送队列满而造成发送失败 +send_queue_size=1000 + +; lang用于指定T2_SDK错误信息的语言ID(2052为简体中文,1033为英文) +; 默认为2052 +lang=2052 + +; 此配置项请参看“注意事项” +event_count=10 + +; 许可证文件的路径,默认为当前目录下的license.dat。 +license_file=./license.dat + + +[proxy] +; 可配置采用何种代理配置http/socks4/socks5,空表示不采用代理 +proxy_type= + +; 代理服务器的IP地址 +ip= +port= + +; 登陆代理服务器的用户名 +user_name=guest +password= + +[safe] +; 连接的安全模式,明文(none),通信密码(pwd),SSL(ssl) +; 注意大小写敏感 +safe_level=none + +; 当连接的安全模式为pwd时,client_id配置项才生效 +client_id= + +; 在pwd模式下,当client_id为空时,comm_pwd为默认的密钥 +; 注意当client_id为空时,comm_pwd必须和服务端的配置一致方可正常使用,目前服务 +; 端的配置为888888 +comm_pwd=888888 + +; 当连接的安全模式为ssl时,cert_file和cert_pwd配置项才生效 +; 证书文件路径 +cert_file=xxx.pem +cert_pwd=xxxxxxxx diff --git a/vnpy/api/cshshlp/hshlp/t2sdk.dll b/vnpy/api/cshshlp/hshlp/t2sdk.dll new file mode 100644 index 00000000..4d41f138 Binary files /dev/null and b/vnpy/api/cshshlp/hshlp/t2sdk.dll differ diff --git a/vnpy/api/cshshlp/hshlp/t2sdk.ini b/vnpy/api/cshshlp/hshlp/t2sdk.ini new file mode 100644 index 00000000..5c3ba604 --- /dev/null +++ b/vnpy/api/cshshlp/hshlp/t2sdk.ini @@ -0,0 +1,20 @@ + +[t2sdk] +#第三方许可证 +license_file= +servers=192.168.94.85:8001 +login_name= +init_recv_buf_size=512 +init_send_buf_size=512 +send_queue_size=1000 +#心跳时间 +heartbeat_time=10 +#接入用户密码 +license_pwd= + +[safe] +safe_level=ssl +#SSL证书 +cert_file= +#SSL证书密码 +cert_pwd= diff --git a/vnpy/api/cshshlp/hshlp/t2sdk.lib b/vnpy/api/cshshlp/hshlp/t2sdk.lib new file mode 100644 index 00000000..f9dc0419 Binary files /dev/null and b/vnpy/api/cshshlp/hshlp/t2sdk.lib differ diff --git a/vnpy/api/cshshlp/license.dat b/vnpy/api/cshshlp/license.dat new file mode 100644 index 00000000..1bff812c Binary files /dev/null and b/vnpy/api/cshshlp/license.dat differ diff --git a/vnpy/api/cshshlp/readme.md b/vnpy/api/cshshlp/readme.md new file mode 100644 index 00000000..d763cf93 --- /dev/null +++ b/vnpy/api/cshshlp/readme.md @@ -0,0 +1,14 @@ +# vn.cshshlp + +### 简介 +中信证券恒生接口规范的Python封装。 + +1. 使用时请将该目录下所有的dat、pfx、ini文件复制到vn.trader目录后使用; +2. 该封装目前只支持交易接口,行情接口请使用中信期货的CTP行情 + +### API版本 +日期:2013-09-17 + +名称:Cs_Hshlp + +描述:中信证券恒生API diff --git a/vnpy/api/cshshlp/s2013.pfx b/vnpy/api/cshshlp/s2013.pfx new file mode 100644 index 00000000..5a091528 Binary files /dev/null and b/vnpy/api/cshshlp/s2013.pfx differ diff --git a/vnpy/api/cshshlp/t2sdk.dll b/vnpy/api/cshshlp/t2sdk.dll new file mode 100644 index 00000000..4d41f138 Binary files /dev/null and b/vnpy/api/cshshlp/t2sdk.dll differ diff --git a/vnpy/api/cshshlp/t2sdk.ini b/vnpy/api/cshshlp/t2sdk.ini new file mode 100644 index 00000000..5c3ba604 --- /dev/null +++ b/vnpy/api/cshshlp/t2sdk.ini @@ -0,0 +1,20 @@ + +[t2sdk] +#第三方许可证 +license_file= +servers=192.168.94.85:8001 +login_name= +init_recv_buf_size=512 +init_send_buf_size=512 +send_queue_size=1000 +#心跳时间 +heartbeat_time=10 +#接入用户密码 +license_pwd= + +[safe] +safe_level=ssl +#SSL证书 +cert_file= +#SSL证书密码 +cert_pwd= diff --git a/vnpy/api/cshshlp/test/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat b/vnpy/api/cshshlp/test/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat new file mode 100644 index 00000000..8effa775 Binary files /dev/null and b/vnpy/api/cshshlp/test/(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat differ diff --git a/vnpy/api/cshshlp/test/CITICs_HsT2Hlp.dll b/vnpy/api/cshshlp/test/CITICs_HsT2Hlp.dll new file mode 100644 index 00000000..ab3c99af Binary files /dev/null and b/vnpy/api/cshshlp/test/CITICs_HsT2Hlp.dll differ diff --git a/vnpy/api/cshshlp/test/Hsconfig.ini b/vnpy/api/cshshlp/test/Hsconfig.ini new file mode 100644 index 00000000..90bc131c --- /dev/null +++ b/vnpy/api/cshshlp/test/Hsconfig.ini @@ -0,0 +1,146 @@ +[t2sdk] + +; 客户端要连接的服务端的IP和端口,可以配置一个或多个,中间以;分割,连接初始化时,会从这串服务端地址中,随即选择一个作为要建立连接的服务端 + +;servers=10.23.179.15:20008 + +;联通请使用这个地址: + +;servers=118.192.134.124:20008 + +;电信请使用这个地址: + +servers=124.207.9.124:20008 + +; 接收缓存的初始大小,单位字节,实际接收到服务端的数据时,可能会扩大(如果需要) + +init_recv_buf_size=512 + + + +; 每块发送缓存的初始大小,单位字节,该大小也会根据需要动态扩大 + +init_send_buf_size=512 + + + +; 发送队列的大小,该大小不会动态变化,若该配置项很小,且连接发包很频繁,则可能 + +; 因为发送队列满而造成发送失败 + +send_queue_size=1000 + + + +; lang用于指定T2_SDK错误信息的语言ID(2052为简体中文,1033为英文) + +; 默认为2052 + +lang=2052 + + + +; 此配置项请参看“注意事项” + +event_count=10 + + + +; 许可证文件的路径,默认为当前目录下的license.dat。 + +license_file=(20130403)ZXZQ-TESTsfjrt-ALL-0001_3rd.dat + + + +;第三方许可证密码 + +license_pwd=999999 + + + +; 客户端给服务端发送心跳的间隔时间,单位为秒,最小值为5秒 + +; 不配或者配<=0,表示不开启客户端心跳 + +heartbeat_time=5 + + + + + +;t2sdk开发包取本机IP和MAC地址,值为1表示t2sdk与服务端建立连接的时候要带上IP和MAC,其它任何值都不会带IP和MAC地址信息 + +addipmac=1 + + + +[proxy] + +; 可配置采用何种代理配置http/socks4/socks5,空表示不采用代理 + +proxy_type= + + + +; 代理服务器的IP地址 + +ip= + +port= + + + +; 登陆代理服务器的用户名 + +user_name=guest + +password= + + + +[safe] + +; 连接的安全模式,明文(none),通信密码(pwd),SSL(ssl) + +; 注意大小写敏感 + +safe_level=ssl + + + +; 当连接的安全模式为pwd时,client_id配置项才生效 + +client_id= + + + +; 在pwd模式下,当client_id为空时,comm_pwd为默认的密钥 + +; 注意当client_id为空时,comm_pwd必须和服务端的配置一致方可正常使用,目前服务 + +; 端的配置为888888 + +comm_pwd=999999 + + + +; 当连接的安全模式为ssl时,cert_file和cert_pwd配置项才生效 + +; 证书文件路径 + +cert_file=s2013.pfx + +cert_pwd=999999 + + + + + +; 是否校验服务端,可不配,若不配,默认校验服务端 + +check_server_cert= + + + + + diff --git a/vnpy/api/cshshlp/test/csapi.ini b/vnpy/api/cshshlp/test/csapi.ini new file mode 100644 index 00000000..c684d125 --- /dev/null +++ b/vnpy/api/cshshlp/test/csapi.ini @@ -0,0 +1,38 @@ +[csapi] +log_path=.\\cslog\ + +biz_trace=2 +; 0: 不记录日志; +; 1: 只记录错误请求参数日志 +; 2: 记录所有请求参数日志, 默认值; +; 4: 记录所有请求参数日志,并且记录t2sdk的二进制请求包 +; 8: 并且记录t2sdk的二进制应答包,调试使用。 + +error_trim = 11 +;错误信息格式化,0:不处理;1:只过滤"表记录"提示;11:在1的基础上过滤&&后面的参数 +;默认为0 + +update_site=10.1.1.1:21001 +;自动升级服务器IP及端口 + +license_file=csauthor.dat +; CITICs_HsT2Hlp.dll接口许可证文件名称,不含路径 + +[connection] +connect_timeout=10 +; 中间件连接超时时间,单位:S,默认时间10s + +biz_timeout=15 +; 业务请求超时时间,单位:S,默认时间10s + +op_site_prefix= +;操作站点前缀,默认为空。可以配置长度不超过8个字符的字符串 + +[func_log] +; 该配置与[biz_trace] 选项两者取大值 +; 功能号, 日志标识 1:只记录错误; 2:记录请求数据; 4:记录请求/应答(top2) 8:记录请求/应答数据(完整) + +;func_01=331100,4 +;func_02=333002,4 +;func_03=339306,2 +;func_04=333104,4 diff --git a/vnpy/api/cshshlp/test/csauthor.dat b/vnpy/api/cshshlp/test/csauthor.dat new file mode 100644 index 00000000..f8dcf012 --- /dev/null +++ b/vnpy/api/cshshlp/test/csauthor.dat @@ -0,0 +1,16 @@ +[auth_info] +ProfileCode=8cb1c6d660013b4277abe5a4c51836b3 +LimitDate=20300101 +AllowPushTransation=0 +AllowWbp=0 +AuthCode=AQAAAABo23BjZjkxZDczMGQyN2I2MzI0NmI0NzRhMGIwYzg5ZDg0OQAAAAAAAAAAAAAAAA== +[functions] +func= +;[ProcessInfo_0] +;ProcessName=HsT2Hlp_Demo.exe,Hs.exe +;NetIP=172.23.123.9 +;NetMask=255.255.255.0 +;[ProcessInfo_0] +;ProcessName=Option_Demo.exe +;NetIP=10.0.0.0 +;NetMask=255.0.0.0 diff --git a/vnpy/api/cshshlp/test/cstest.py b/vnpy/api/cshshlp/test/cstest.py new file mode 100644 index 00000000..76736ad8 --- /dev/null +++ b/vnpy/api/cshshlp/test/cstest.py @@ -0,0 +1,94 @@ +# encoding: UTF-8 + +import sys +from time import sleep + +from PyQt4 import QtGui + +from vncshshlp import * + + +branch_no = '' + + +#---------------------------------------------------------------------- +def print_list(l): + """""" + for d in l: + print d + +#---------------------------------------------------------------------- +def print_dict(d): + """鎸夌収閿兼墦鍗颁竴涓瓧鍏""" + for key,value in d.items(): + print key + ':' + str(value) + + +#---------------------------------------------------------------------- +def simple_log(func): + """绠鍗曡楗板櫒鐢ㄤ簬杈撳嚭鍑芥暟鍚""" + def wrapper(*args, **kw): + print '-' * 20 + print str(func.__name__) + return func(*args, **kw) + return wrapper + + +class TestHlp(CsHsHlp): + #---------------------------------------------------------------------- + def __init__(self): + """""" + super(TestHlp, self).__init__() + + #---------------------------------------------------------------------- + @simple_log + def onMsg(self, type_, data, reqNo, errorNo, errorInfo): + """""" + print 'type:', type_ + print_list(data) + print 'reqNo:', reqNo + print 'errorNo:', errorNo + print 'errorInfo:', errorInfo + +#---------------------------------------------------------------------- +def test(): + """娴嬭瘯鐢""" + api = TestHlp() + + # 璇诲彇閰嶇疆鏂囦欢 + i = api.loadConfig("Hsconfig.ini") + if i: + print u'鍔犺浇閰嶇疆澶辫触锛', i + print u'鍔犺浇閰嶇疆鎴愬姛' + + # 鍒濆鍖 + i = api.init() + if i: + print u'鍒濆鍖栧け璐ワ細', i + print u'鍒濆鍖栨垚鍔' + + # 杩炴帴鏈嶅姟鍣 + i = api.connectServer() + if i: + print u'鏈嶅姟鍣ㄨ繛鎺ュけ璐ワ細', i + print u'鏈嶅姟鍣ㄨ繛鎺ユ垚鍔' + + # 鐧诲綍 + print u'灏濊瘯鐧诲綍' + i = api.beginParam() + api.setValue("identity_type", "2") + api.setValue("password_type", "2") + api.setValue("input_content", "1") + api.setValue("op_entrust_way", "5") + api.setValue("password", "") + api.setValue("account_content", "") + i = api.bizCallAndCommit(331100) + print '鐧诲綍reqNo:', i + + print 'done' + + raw_input() + + +if __name__ == '__main__': + test() \ No newline at end of file diff --git a/vnpy/api/cshshlp/test/license.dat b/vnpy/api/cshshlp/test/license.dat new file mode 100644 index 00000000..1bff812c Binary files /dev/null and b/vnpy/api/cshshlp/test/license.dat differ diff --git a/vnpy/api/cshshlp/test/s2013.pfx b/vnpy/api/cshshlp/test/s2013.pfx new file mode 100644 index 00000000..5a091528 Binary files /dev/null and b/vnpy/api/cshshlp/test/s2013.pfx differ diff --git a/vnpy/api/cshshlp/test/t2sdk.dll b/vnpy/api/cshshlp/test/t2sdk.dll new file mode 100644 index 00000000..4d41f138 Binary files /dev/null and b/vnpy/api/cshshlp/test/t2sdk.dll differ diff --git a/vnpy/api/cshshlp/test/t2sdk.ini b/vnpy/api/cshshlp/test/t2sdk.ini new file mode 100644 index 00000000..5c3ba604 --- /dev/null +++ b/vnpy/api/cshshlp/test/t2sdk.ini @@ -0,0 +1,20 @@ + +[t2sdk] +#第三方许可证 +license_file= +servers=192.168.94.85:8001 +login_name= +init_recv_buf_size=512 +init_send_buf_size=512 +send_queue_size=1000 +#心跳时间 +heartbeat_time=10 +#接入用户密码 +license_pwd= + +[safe] +safe_level=ssl +#SSL证书 +cert_file= +#SSL证书密码 +cert_pwd= diff --git a/vnpy/api/cshshlp/test/vncshshlp.pyd b/vnpy/api/cshshlp/test/vncshshlp.pyd new file mode 100644 index 00000000..666b2035 Binary files /dev/null and b/vnpy/api/cshshlp/test/vncshshlp.pyd differ diff --git a/vnpy/api/cshshlp/vncshshlp.pyd b/vnpy/api/cshshlp/vncshshlp.pyd new file mode 100644 index 00000000..ec6b1247 Binary files /dev/null and b/vnpy/api/cshshlp/vncshshlp.pyd differ diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp.sln b/vnpy/api/cshshlp/vncshshlp/vncshshlp.sln new file mode 100644 index 00000000..c9940863 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp.sln @@ -0,0 +1,22 @@ +锘 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vncshshlp", "vncshshlp\vncshshlp.vcxproj", "{982DF24C-BCD1-4F25-BDE8-84ADB719588B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {982DF24C-BCD1-4F25-BDE8-84ADB719588B}.Debug|Win32.ActiveCfg = Debug|Win32 + {982DF24C-BCD1-4F25-BDE8-84ADB719588B}.Debug|Win32.Build.0 = Debug|Win32 + {982DF24C-BCD1-4F25-BDE8-84ADB719588B}.Release|Win32.ActiveCfg = Release|Win32 + {982DF24C-BCD1-4F25-BDE8-84ADB719588B}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/ReadMe.txt b/vnpy/api/cshshlp/vncshshlp/vncshshlp/ReadMe.txt new file mode 100644 index 00000000..2712d85e --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/ReadMe.txt @@ -0,0 +1,32 @@ +锘======================================================================== + 鍔ㄦ侀摼鎺ュ簱锛歷ncshshlp 椤圭洰姒傝堪 +======================================================================== + +搴旂敤绋嬪簭鍚戝宸蹭负鎮ㄥ垱寤轰簡姝 vncshshlp DLL銆 + +鏈枃浠舵瑕佷粙缁嶇粍鎴 vncshshlp 搴旂敤绋嬪簭鐨勬瘡涓枃浠剁殑鍐呭銆 + + +vncshshlp.vcxproj + 杩欐槸浣跨敤搴旂敤绋嬪簭鍚戝鐢熸垚鐨 VC++ 椤圭洰鐨勪富椤圭洰鏂囦欢锛屽叾涓寘鍚敓鎴愯鏂囦欢鐨 Visual C++ 鐨勭増鏈俊鎭紝浠ュ強鏈夊叧浣跨敤搴旂敤绋嬪簭鍚戝閫夋嫨鐨勫钩鍙般侀厤缃拰椤圭洰鍔熻兘鐨勪俊鎭 + +vncshshlp.vcxproj.filters + 杩欐槸浣跨敤鈥滃簲鐢ㄧ▼搴忓悜瀵尖濈敓鎴愮殑 VC++ 椤圭洰绛涢夊櫒鏂囦欢銆傚畠鍖呭惈鏈夊叧椤圭洰鏂囦欢涓庣瓫閫夊櫒涔嬮棿鐨勫叧鑱斾俊鎭傚湪 IDE 涓紝閫氳繃杩欑鍏宠仈锛屽湪鐗瑰畾鑺傜偣涓嬩互鍒嗙粍褰㈠紡鏄剧ず鍏锋湁鐩镐技鎵╁睍鍚嶇殑鏂囦欢銆備緥濡傦紝鈥.cpp鈥濇枃浠朵笌鈥滄簮鏂囦欢鈥濈瓫閫夊櫒鍏宠仈銆 + +vncshshlp.cpp + 杩欐槸涓 DLL 婧愭枃浠躲 + + 姝 DLL 鍦ㄥ垱寤烘椂涓嶅鍑轰换浣曠鍙枫傚洜姝わ紝鐢熸垚鏃朵笉浼氫骇鐢 .lib 鏂囦欢銆傚鏋滃笇鏈涙椤圭洰鎴愪负鍏朵粬鏌愪釜椤圭洰鐨勯」鐩緷璧栭」锛屽垯闇瑕佹坊鍔犱唬鐮佷互浠 DLL 瀵煎嚭鏌愪簺绗﹀彿锛屼互渚夸骇鐢熶竴涓鍑哄簱锛屾垨鑰咃紝涔熷彲浠ュ湪椤圭洰鈥滃睘鎬ч〉鈥濆璇濇涓殑鈥滈摼鎺ュ櫒鈥濇枃浠跺す涓紝灏嗏滃父瑙勨濆睘鎬ч〉涓婄殑鈥滃拷鐣ヨ緭鍏ュ簱鈥濆睘鎬ц缃负鈥滄槸鈥濄 + +///////////////////////////////////////////////////////////////////////////// +鍏朵粬鏍囧噯鏂囦欢: + +StdAfx.h, StdAfx.cpp + 杩欎簺鏂囦欢鐢ㄤ簬鐢熸垚鍚嶄负 vncshshlp.pch 鐨勯缂栬瘧澶 (PCH) 鏂囦欢鍜屽悕涓 StdAfx.obj 鐨勯缂栬瘧绫诲瀷鏂囦欢銆 + +///////////////////////////////////////////////////////////////////////////// +鍏朵粬娉ㄩ噴: + +搴旂敤绋嬪簭鍚戝浣跨敤鈥淭ODO:鈥濇敞閲婃潵鎸囩ず搴旀坊鍔犳垨鑷畾涔夌殑婧愪唬鐮侀儴鍒嗐 + +///////////////////////////////////////////////////////////////////////////// diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/dllmain.cpp b/vnpy/api/cshshlp/vncshshlp/vncshshlp/dllmain.cpp new file mode 100644 index 00000000..260abc6d --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/dllmain.cpp @@ -0,0 +1,19 @@ +// dllmain.cpp : 定义 DLL 应用程序的入口点。 +#include "stdafx.h" + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + break; + } + return TRUE; +} + diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.cpp b/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.cpp new file mode 100644 index 00000000..63accacc --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.cpp @@ -0,0 +1,8 @@ +// stdafx.cpp : 只包括标准包含文件的源文件 +// vncshshlp.pch 将作为预编译头 +// stdafx.obj 将包含预编译类型信息 + +#include "stdafx.h" + +// TODO: 在 STDAFX.H 中 +// 引用任何所需的附加头文件,而不是在此文件中引用 diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.h b/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.h new file mode 100644 index 00000000..2ec1caa0 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/stdafx.h @@ -0,0 +1,16 @@ +// stdafx.h : 标准系统包含文件的包含文件, +// 或是经常使用但不常更改的 +// 特定于项目的包含文件 +// + +#pragma once + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // 从 Windows 头文件中排除极少使用的信息 +// Windows 头文件: +#include + + + +// TODO: 在此处引用程序需要的其他头文件 diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/targetver.h b/vnpy/api/cshshlp/vncshshlp/vncshshlp/targetver.h new file mode 100644 index 00000000..7a7d2c83 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/targetver.h @@ -0,0 +1,8 @@ +#pragma once + +// 包括 SDKDDKVer.h 将定义可用的最高版本的 Windows 平台。 + +// 如果要为以前的 Windows 平台生成应用程序,请包括 WinSDKVer.h,并将 +// WIN32_WINNT 宏设置为要支持的平台,然后再包括 SDKDDKVer.h。 + +#include diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.cpp b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.cpp new file mode 100644 index 00000000..bb1e0fd5 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.cpp @@ -0,0 +1,243 @@ +// vncshshlp.cpp : 定义 DLL 应用程序的导出函数。 +// + +#include "stdafx.h" +#include "vncshshlp.h" + +//------------------------------------------------------------------------ +//主动函数部分 +//------------------------------------------------------------------------ + +//读取配置文件 +int CsHsHlp::loadConfig(string fileName) +{ + int i = CITICs_HsHlp_LoadConfig(&this->cfgHandle, fileName.c_str()); + return i; +}; + +//初始化 +int CsHsHlp::init() +{ + int i = CITICs_HsHlp_Init(&this->handle, this->cfgHandle); + return i; +}; + +//连接服务器 +int CsHsHlp::connectServer() +{ + int i = CITICs_HsHlp_ConnectServer(this->handle); + + if (this->active == false) + { + this->active = true; + function0 f = boost::bind(&CsHsHlp::processMsg, this); + thread t(f); + this->task_thread = &t; + } + + return i; +}; + +//获取错误信息 +string CsHsHlp::getErrorMsg() +{ + int i; + char msg[512]; + CITICs_HsHlp_GetErrorMsg(this->handle, &i, msg); + string errorMsg = msg; + return errorMsg; +}; + +//初始化发包请求 +int CsHsHlp::beginParam() +{ + int i = CITICs_HsHlp_BeginParam(this->handle); + return i; +}; + +//设置发包的参数字段名称和值 +int CsHsHlp::setValue(string key, string value) +{ + int i = CITICs_HsHlp_SetValue(this->handle, key.c_str(), value.c_str()); + return i; +}; + +//异步发包 +int CsHsHlp::bizCallAndCommit(int iFuncID) +{ + int i = CITICs_HsHlp_BizCallAndCommit(this->handle, iFuncID, NULL, BIZCALL_ASYNC, NULL); + return i; +}; + +//订阅 +boost::python::list CsHsHlp::subscribeData(int iFuncID) +{ + int i = CITICs_HsHlp_BizCallAndCommit(this->handle, iFuncID, NULL, BIZCALL_SUBSCRIBE, NULL); + + //订阅为同步调用,读取返回的结果 + int row = CITICs_HsHlp_GetRowCount(this->handle); //获取msg行数(有多少个回应) + int col = CITICs_HsHlp_GetColCount(this->handle); //获取msg列数(有哪些字段) + char key[64] = { 0 }; + char value[512] = { 0 }; + + boost::python::list data; + + for (int i = 0; i < row; i++) + { + if (0 == CITICs_HsHlp_GetNextRow(this->handle)) + { + dict d; + for (int j = 0; j < col; j++) + { + CITICs_HsHlp_GetColName(this->handle, j, key); + CITICs_HsHlp_GetValueByIndex(this->handle, j, value); + + string str_key = key; + string str_value = value; + d[str_key] = str_value; + } + data.append(d); + } + } + + return data; +}; + +//断开服务器 +int CsHsHlp::disconnect() +{ + int i = CITICs_HsHlp_DisConnect(this->handle); + return i; +}; + +//退出 +int CsHsHlp::exit() +{ + this->active = false; + int i = CITICs_HsHlp_Exit(this->handle); + return i; +}; + + +//------------------------------------------------------------------------ +//异步消息处理线程 +//------------------------------------------------------------------------ + +//连续运行的消息处理函数 +void CsHsHlp::processMsg() +{ + LPMSG_CTRL msgCtrl; //控制信息 + int type = 0; //消息类型 + int reqNo = 0; //异步请求编号 + int errorNo = 0; //错误代码 + string errorInfo = ""; //错误信息 + + int row = 0; //行数 + int col = 0; //列数 + char key[64] = {0}; //键 + char value[512] = {0}; //值 + + PyGILState_STATE gil_state; //GIL全局锁 + + //连续运行 + while (this->active) + { + //初始化指针 + msgCtrl = new MSG_CTRL(); + + //读取消息 + int i = CITICs_HsHlp_QueueGetMsg(this->handle, msgCtrl, -1); + + //读取信息 + if (msgCtrl->nIssueType) + { + type = msgCtrl->nIssueType; + } + else + { + type = msgCtrl->nFuncID; + } + + reqNo = msgCtrl->nReqNo; + errorNo = msgCtrl->nErrorNo; + errorInfo = msgCtrl->szErrorInfo; + + row = CITICs_HsHlp_GetRowCount(this->handle, msgCtrl); //获取msg行数(有多少个回应) + col = CITICs_HsHlp_GetColCount(this->handle, msgCtrl); //获取msg列数(有哪些字段) + + //生成字典并推送到Python中 + gil_state = PyGILState_Ensure(); //创建Python对象前先锁定GIL + + boost::python::list data; + + for (int i = 0; i < row; i++) + { + if (0 == CITICs_HsHlp_GetNextRow(this->handle, msgCtrl)) + { + dict d; + for (int j = 0; j < col; j++) + { + CITICs_HsHlp_GetColName(this->handle, j, key, msgCtrl); + CITICs_HsHlp_GetValueByIndex(this->handle, j, value, msgCtrl); + + string str_key = key; + string str_value = value; + d[str_key] = str_value; + } + data.append(d); + } + } + + this->onMsg(type, data, reqNo, errorNo, errorInfo); + + PyGILState_Release(gil_state); //推送Python对象完成后释放GIL + + //从队列删除消息 + CITICs_HsHlp_QueueEraseMsg(this->handle, msgCtrl); + + //删除指针 + delete msgCtrl; + } +}; + + +///------------------------------------------------------------------------------------- +///Boost.Python封装 +///------------------------------------------------------------------------------------- + +struct CsHsHlpWrap : CsHsHlp, wrapper < CsHsHlp > +{ + virtual void onMsg(int type, boost::python::list data, int reqNo, int errorNo, string errorInfo) + { + //以下的try...catch...可以实现捕捉python环境中错误的功能,防止C++直接出现原因未知的崩溃 + try + { + this->get_override("onMsg")(type, data, reqNo, errorNo, errorInfo); + } + catch (error_already_set const &) + { + PyErr_Print(); + } + }; +}; + + +BOOST_PYTHON_MODULE(vncshshlp) +{ + PyEval_InitThreads(); //导入时运行,保证先创建GIL + + class_("CsHsHlp") + .def("loadConfig", &CsHsHlpWrap::loadConfig) + .def("init", &CsHsHlpWrap::init) + .def("connectServer", &CsHsHlpWrap::connectServer) + .def("getErrorMsg", &CsHsHlpWrap::getErrorMsg) + .def("beginParam", &CsHsHlpWrap::beginParam) + .def("setValue", &CsHsHlpWrap::setValue) + .def("bizCallAndCommit", &CsHsHlpWrap::bizCallAndCommit) + .def("disconnect", &CsHsHlpWrap::disconnect) + .def("exit", &CsHsHlpWrap::exit) + .def("subscribeData", &CsHsHlpWrap::subscribeData) + + .def("onMsg", pure_virtual(&CsHsHlpWrap::onMsg)) + ; +}; \ No newline at end of file diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.h b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.h new file mode 100644 index 00000000..7165ec8f --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.h @@ -0,0 +1,99 @@ +//说明部分 + +//系统 +#include "stdafx.h" +#include +#include + +//Boost +#define BOOST_PYTHON_STATIC_LIB +#include //python封装 +#include //python封装 +#include //python封装 +#include //python封装 +#include //python封装 +#include //python封装 +#include //任务队列的线程功能 +#include //任务队列的线程功能 +#include //任务队列的任务实现 + +//API +#include "CITICs_HsT2Hlp.h" + +//命名空间 +using namespace std; +using namespace boost::python; +using namespace boost; + + +///------------------------------------------------------------------------------------- +///封装类 +///------------------------------------------------------------------------------------- + +class CsHsHlp +{ +private: + HSHLPCFGHANDLE cfgHandle; //配置指针 + HSHLPHANDLE handle; //操作对象指针 + thread *task_thread; //工作线程指针(向python中推送数据) + bool active; //工作状态 + +public: + CsHsHlp() + { + this->active = false; + }; + + ~CsHsHlp() + { + this->active = false; + }; + + //------------------------------------------------------------------------ + //主动函数部分 + //------------------------------------------------------------------------ + + //读取配置文件 + int loadConfig(string fileName); + + //初始化 + int init(); + + //连接服务器 + int connectServer(); + + //获取错误信息 + string getErrorMsg(); + + //初始化发包请求 + int beginParam(); + + //设置发包的参数字段名称和值 + int setValue(string key, string value); + + //发包 + int bizCallAndCommit(int iFuncID); + + //订阅 + boost::python::list subscribeData(int iFuncID); + + //断开服务器 + int disconnect(); + + //退出 + int exit(); + + //------------------------------------------------------------------------ + //异步消息处理线程 + //------------------------------------------------------------------------ + + //连续运行的消息处理函数 + void processMsg(); + + //------------------------------------------------------------------------ + //Python中继承的回调函数 + //------------------------------------------------------------------------ + + //向Python中推送消息的函数 + virtual void onMsg(int type, boost::python::list data, int reqNo, int errorNo, string errorInfo) {}; +}; diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj new file mode 100644 index 00000000..6e49f474 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj @@ -0,0 +1,117 @@ +锘 + + + + Debug + Win32 + + + Release + Win32 + + + + {982DF24C-BCD1-4F25-BDE8-84ADB719588B} + Win32Proj + vncshshlp + + + + DynamicLibrary + true + v120 + Unicode + + + DynamicLibrary + false + v120 + true + Unicode + + + + + + + + + + + + + true + + + false + C:\Users\Administrator\Desktop\vn.cs\vn.cs\hshlp;C:\Users\Administrator\Anaconda2\include;C:\boost_1_62_0;$(IncludePath) + C:\boost_1_62_0\libs;C:\Users\Administrator\Anaconda2\libs;C:\Users\Administrator\Desktop\vn.cs\vn.cs\hshlp;$(ReferencePath) + .pyd + + + + Use + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;VNCSHSHLP_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + + + + + Level3 + Use + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;VNCSHSHLP_EXPORTS;%(PreprocessorDefinitions) + true + + + Windows + true + true + true + C:\Users\Administrator\Desktop\vn.cs\vn.cs\hshlp;C:\Users\Administrator\Anaconda2\libs;C:\boost_1_62_0\stage\lib;%(AdditionalLibraryDirectories) + + + + + + + + + + + + + + false + + + false + + + + + Create + Create + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj.filters b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj.filters new file mode 100644 index 00000000..0f4393f5 --- /dev/null +++ b/vnpy/api/cshshlp/vncshshlp/vncshshlp/vncshshlp.vcxproj.filters @@ -0,0 +1,61 @@ +锘 + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + + + Source Files + + + Source Files + + + Source Files + + + + + Resource Files + + + Resource Files + + + + + Resource Files + + + Resource Files + + + \ No newline at end of file diff --git a/vnpy/trader/ctaStrategy/ctaHistoryData.py b/vnpy/trader/ctaStrategy/ctaHistoryData.py index 0aa11465..461575af 100644 --- a/vnpy/trader/ctaStrategy/ctaHistoryData.py +++ b/vnpy/trader/ctaStrategy/ctaHistoryData.py @@ -309,8 +309,6 @@ class HistoryDataEngine(object): print u'%s涓嬭浇瀹屾垚' %symbol else: print u'鎵句笉鍒板悎绾%s' %symbol - - #---------------------------------------------------------------------- def downloadEquityDailyBarts(self, symbol): @@ -362,7 +360,6 @@ def downloadEquityDailyBarts(self, symbol): else: print u'鎵句笉鍒板悎绾%s' %symbol - #---------------------------------------------------------------------- def loadMcCsv(fileName, dbName, symbol): """灏哅ulticharts瀵煎嚭鐨刢sv鏍煎紡鐨勫巻鍙叉暟鎹彃鍏ュ埌Mongo鏁版嵁搴撲腑""" @@ -431,50 +428,7 @@ def loadTdxCsv(fileName, dbName, symbol): print bar.date, bar.time print u'鎻掑叆瀹屾瘯锛岃楁椂锛%s' % (time()-start) - -#---------------------------------------------------------------------- -def loadTBCsv(fileName, dbName, symbol): - """灏員radeBlazer瀵煎嚭鐨刢sv鏍煎紡鐨勫巻鍙叉暟鎹彃鍏ュ埌Mongo鏁版嵁搴撲腑 - 鏁版嵁鏍锋湰锛 - //鏃堕棿,寮鐩樹环,鏈楂樹环,鏈浣庝环,鏀剁洏浠,鎴愪氦閲,鎸佷粨閲 - 2017/04/05 09:00,3200,3240,3173,3187,312690,2453850 - """ - import csv - - start = time() - print u'寮濮嬭鍙朇SV鏂囦欢%s涓殑鏁版嵁鎻掑叆鍒%s鐨%s涓' %(fileName, dbName, symbol) - - # 閿佸畾闆嗗悎锛屽苟鍒涘缓绱㈠紩 - client = pymongo.MongoClient(globalSetting['mongoHost'], globalSetting['mongoPort']) - collection = client[dbName][symbol] - collection.ensure_index([('datetime', pymongo.ASCENDING)], unique=True) - - # 璇诲彇鏁版嵁鍜屾彃鍏ュ埌鏁版嵁搴 - reader = csv.reader(file(fileName, 'r')) - for d in reader: - if len(d[0]) > 10: - bar = CtaBarData() - bar.vtSymbol = symbol - bar.symbol = symbol - - bar.datetime = datetime.strptime(d[0], '%Y/%m/%d %H:%M') - bar.date = bar.datetime.date().strftime('%Y%m%d') - bar.time = bar.datetime.time().strftime('%H:%M:%S') - - bar.open = float(d[1]) - bar.high = float(d[2]) - bar.low = float(d[3]) - bar.close = float(d[4]) - - bar.volume = float(d[5]) - bar.openInterest = float(d[6]) - flt = {'datetime': bar.datetime} - collection.update_one(flt, {'$set':bar.__dict__}, upsert=True) - print '%s \t %s' % (bar.date, bar.time) - - print u'鎻掑叆瀹屾瘯锛岃楁椂锛%s' % (time()-start) - if __name__ == '__main__': ## 绠鍗曠殑娴嬭瘯鑴氭湰鍙互鍐欏湪杩欓噷 diff --git a/vnpy/trader/gateway/__init__.py b/vnpy/trader/gateway/__init__.py index 46e147c4..6feb1d45 100644 --- a/vnpy/trader/gateway/__init__.py +++ b/vnpy/trader/gateway/__init__.py @@ -23,7 +23,7 @@ for root, subdirs, files in os.walk(path): # 鎺ュ彛鐩綍鍚嶄腑蹇呴』鍚湁Gateway if 'Gateway' in foldername: # 妯″潡鍚嶇О闇瑕佷笂鍓嶇紑 - moduleName = 'gateway.' + foldername + moduleName = 'vnpy.trader.gateway.' + foldername try: # 浣跨敤importlib鍔ㄦ佽浇鍏ユā鍧楋紝骞朵繚瀛樺埌瀛楀吀涓 diff --git a/vnpy/trader/gateway/cshshlpGateway/CSHSHLP_connect.json b/vnpy/trader/gateway/cshshlpGateway/CSHSHLP_connect.json new file mode 100644 index 00000000..606262ab --- /dev/null +++ b/vnpy/trader/gateway/cshshlpGateway/CSHSHLP_connect.json @@ -0,0 +1,11 @@ +{ + "brokerID": "1000", + "mdAddress": "tcp://203.110.179.217:31213", + "userID": "璇疯仈绯讳腑淇℃湡璐х敵璇", + "ctpPassword": "璇疯仈绯讳腑淇℃湡璐х敵璇", + + "opEntrustWay": "5", + "opStation": "111111111", + "fundAccount": "璇疯仈绯讳腑淇¤瘉鍒哥敵璇", + "password": "璇疯仈绯讳腑淇¤瘉鍒哥敵璇" +} \ No newline at end of file diff --git a/vnpy/trader/gateway/cshshlpGateway/__init__.py b/vnpy/trader/gateway/cshshlpGateway/__init__.py new file mode 100644 index 00000000..c65bbbd4 --- /dev/null +++ b/vnpy/trader/gateway/cshshlpGateway/__init__.py @@ -0,0 +1,10 @@ +# encoding: UTF-8 + +import vtConstant +from cshshlpGateway import CshshlpGateway as gateway + +gatewayName = 'CSHSHLP' +gatewayDisplayName = u'涓俊鏈熸潈' +gatewayType = vtConstant.GATEWAYTYPE_EQUITY +gatewayQryEnabled = True + diff --git a/vnpy/trader/gateway/cshshlpGateway/cshshlpGateway.py b/vnpy/trader/gateway/cshshlpGateway/cshshlpGateway.py new file mode 100644 index 00000000..3a12839e --- /dev/null +++ b/vnpy/trader/gateway/cshshlpGateway/cshshlpGateway.py @@ -0,0 +1,1002 @@ +# encoding: UTF-8 + +import sys +import os +import json +from time import sleep + +from vnpy.api.cshshlp import CsHsHlp +from vnpy.api.ctp import MdApi +from vnpy.trader.vtGateway import * + + +# 鎺ュ彛甯搁噺 +FUNCTION_LOGIN = 331100 +FUNCTION_SENDORDER = 338011 +FUNCTION_CANCELORDER = 338012 +FUNCTION_QRYCONTRACT = 338000 +FUNCTION_QRYORDER = 338020 +FUNCTION_QRYTRADE = 338021 +FUNCTION_QRYPOSITION = 338023 +FUNCTION_QRYACCOUNT = 338022 +FUNCTION_SUBSCRIBE= 620001 + +ISSUE_ORDER = 33012 +ISSUE_TRADE = 33011 + + +# 浜ゆ槗鎵绫诲瀷鏄犲皠 +exchangeMap = {} +exchangeMap[EXCHANGE_SSE] = '1' +exchangeMap[EXCHANGE_SZSE] = '2' +exchangeMapReverse = {v:k for k,v in exchangeMap.items()} +exchangeMapReverse['SSE'] = EXCHANGE_SSE + + +# 鏈熸潈绫诲瀷鏄犲皠 +optionTypeMap = {} +optionTypeMap[OPTION_CALL] = 'C' +optionTypeMap[OPTION_PUT] = 'P' +optionTypeMapReverse = {v:k for k,v in optionTypeMap.items()} + +# 鏂瑰悜绫诲瀷鏄犲皠 +directionMap = {} +directionMap[DIRECTION_LONG] = '1' +directionMap[DIRECTION_SHORT] = '2' +directionMapReverse = {v: k for k, v in directionMap.items()} + +# 寮骞崇被鍨嬫槧灏 +offsetMap = {} +offsetMap[OFFSET_OPEN] = 'O' +offsetMap[OFFSET_CLOSE] = 'C' +offsetMapReverse = {v:k for k,v in offsetMap.items()} + +# 鎸佷粨绫诲瀷鏄犲皠 +posDirectionMap = {} +posDirectionMap[DIRECTION_LONG] = '0' +posDirectionMap[DIRECTION_SHORT] = '1' +posDirectionMap[DIRECTION_COVEREDSHORT] = '2' +posDirectionMapReverse = {v:k for k,v in posDirectionMap.items()} + +# 濮旀墭鐘舵佹槧灏 +statusMapReverse = {} +statusMapReverse['2'] = STATUS_NOTTRADED +statusMapReverse['5'] = STATUS_CANCELLED +statusMapReverse['6'] = STATUS_CANCELLED +statusMapReverse['7'] = STATUS_PARTTRADED +statusMapReverse['8'] = STATUS_ALLTRADED +statusMapReverse['9'] = STATUS_REJECTED + +# 浠锋牸绫诲瀷鏄犲皠 +priceTypeMap = {} +priceTypeMap[PRICETYPE_LIMITPRICE] = '0' +priceTypeMap[PRICETYPE_MARKETPRICE] = 'OPB' +priceTypeMapReverse = {v: k for k, v in priceTypeMap.items()} + + +######################################################################## +class CshshlpGateway(VtGateway): + """""" + + #---------------------------------------------------------------------- + def __init__(self, eventEngine, gatewayName='CS'): + """Constructor""" + super(CshshlpGateway, self).__init__(eventEngine, gatewayName) + + self.mdApi = CshshlpMdApi(self) # 琛屾儏API + self.tdApi = CshshlpTdApi(self) # 浜ゆ槗API + + self.mdConnected = False # 琛屾儏API杩炴帴鐘舵侊紝鐧诲綍瀹屾垚鍚庝负True + self.tdConnected = False # 浜ゆ槗API杩炴帴鐘舵 + + self.qryEnabled = False # 鏄惁瑕佸惎鍔ㄥ惊鐜煡璇 + + #---------------------------------------------------------------------- + def connect(self): + """杩炴帴""" + # 杞藉叆json鏂囦欢 + fileName = self.gatewayName + '_connect.json' + path = os.path.abspath(os.path.dirname(__file__)) + fileName = os.path.join(path, fileName) + + try: + f = file(fileName) + except IOError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = text.LOADING_ERROR + self.onLog(log) + return + + # 瑙f瀽json鏂囦欢 + setting = json.load(f) + + try: + userID = str(setting['userID']) + ctpPassword = str(setting['ctpPassword']) + brokerID = str(setting['brokerID']) + mdAddress = str(setting['mdAddress']) + + opEntrustWay = setting['opEntrustWay'] + opStation = setting['opStation'] + fundAccount = setting['fundAccount'] + password = setting['password'] + except KeyError: + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = u'閰嶇疆鏂囦欢缂哄皯瀛楁' + self.onLog(log) + return + + # 鍒涘缓琛屾儏鍜屼氦鏄撴帴鍙e璞 + self.mdApi.connect(userID, ctpPassword, brokerID, mdAddress) + self.tdApi.connect(opEntrustWay, opStation, fundAccount, password) + + # 鍒濆鍖栧苟鍚姩鏌ヨ + self.initQuery() + + #---------------------------------------------------------------------- + def subscribe(self, subscribeReq): + """璁㈤槄琛屾儏""" + self.mdApi.subscribe(subscribeReq) + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """鍙戝崟""" + return self.tdApi.sendOrder(orderReq) + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelOrderReq): + """鎾ゅ崟""" + self.tdApi.cancelOrder(cancelOrderReq) + + #---------------------------------------------------------------------- + def qryAccount(self): + """鏌ヨ璐︽埛璧勯噾""" + self.tdApi.qryAccount() + + #---------------------------------------------------------------------- + def qryPosition(self): + """鏌ヨ鎸佷粨""" + self.tdApi.qryPosition() + + #---------------------------------------------------------------------- + def close(self): + """鍏抽棴""" + if self.mdConnected: + self.mdApi.close() + + #---------------------------------------------------------------------- + def initQuery(self): + """鍒濆鍖栬繛缁煡璇""" + if self.qryEnabled: + # 闇瑕佸惊鐜殑鏌ヨ鍑芥暟鍒楄〃 + self.qryFunctionList = [self.qryAccount, self.qryPosition] + + self.qryCount = 0 # 鏌ヨ瑙﹀彂鍊掕鏃 + self.qryTrigger = 2 # 鏌ヨ瑙﹀彂鐐 + self.qryNextFunction = 0 # 涓婃杩愯鐨勬煡璇㈠嚱鏁扮储寮 + + self.startQuery() + + #---------------------------------------------------------------------- + def query(self, event): + """娉ㄥ唽鍒颁簨浠跺鐞嗗紩鎿庝笂鐨勬煡璇㈠嚱鏁""" + self.qryCount += 1 + + if self.qryCount > self.qryTrigger: + # 娓呯┖鍊掕鏃 + self.qryCount = 0 + + # 鎵ц鏌ヨ鍑芥暟 + function = self.qryFunctionList[self.qryNextFunction] + function() + + # 璁$畻涓嬫鏌ヨ鍑芥暟鐨勭储寮曪紝濡傛灉瓒呰繃浜嗗垪琛ㄩ暱搴︼紝鍒欓噸鏂拌涓0 + self.qryNextFunction += 1 + if self.qryNextFunction == len(self.qryFunctionList): + self.qryNextFunction = 0 + + #---------------------------------------------------------------------- + def startQuery(self): + """鍚姩杩炵画鏌ヨ""" + self.eventEngine.register(EVENT_TIMER, self.query) + + #---------------------------------------------------------------------- + def setQryEnabled(self, qryEnabled): + """璁剧疆鏄惁瑕佸惎鍔ㄥ惊鐜煡璇""" + self.qryEnabled = qryEnabled + + +######################################################################## +class CshshlpTdApi(CsHsHlp): + """浜ゆ槗API瀹炵幇""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """""" + super(CshshlpTdApi, self).__init__() + + self.gateway = gateway + self.gatewayName = gateway.gatewayName + + self.callbackDict = {} + + self.opBranchNo = '' + self.opEntrustWay = '' + self.opStation = '' + self.branchNo = '' + self.clientId = '' + self.fundAccount = '' + self.password = '' + self.sysnodeId = '' + + #self.batchNo = 0 + self.batchNo = 1000000 + + self.batchEntrustDict = {} # key: batchNo, value: entrustNo + self.entrustBatchDict = {} # key: entrustNo, value: batchNo + + self.orderDict = {} # key: batchNo, value: order + self.cancelDict = {} # key: batchNo, value: cancelReq + + self.loginStatus = False + + self.initCallback() + + #---------------------------------------------------------------------- + def initCallback(self): + """""" + self.callbackDict[FUNCTION_LOGIN] = self.onLogin + self.callbackDict[FUNCTION_SENDORDER] = self.onSendOrder + self.callbackDict[FUNCTION_CANCELORDER] = self.onCancelOrder + self.callbackDict[FUNCTION_QRYCONTRACT] = self.onQryContract + self.callbackDict[FUNCTION_QRYORDER] = self.onQryOrder + self.callbackDict[FUNCTION_QRYTRADE] = self.onQryTrade + self.callbackDict[FUNCTION_QRYPOSITION] = self.onQryPosition + self.callbackDict[FUNCTION_QRYACCOUNT] = self.onQryAccount + + self.callbackDict[ISSUE_ORDER] = self.onRtnOrder + self.callbackDict[ISSUE_TRADE] = self.onRtnTrade + + #---------------------------------------------------------------------- + def onMsg(self, type_, data, reqNo, errorNo, errorInfo): + """鏀跺埌鎺ㄩ""" + #print data + cb = self.callbackDict.get(int(type_), None) + if not cb: + self.writeLog(u'鏃犳硶鎵惧埌瀵瑰簲绫诲瀷鐨勫洖璋冨嚱鏁%s' %type_) + return + + cb(data, reqNo, errorNo, errorInfo) + + #---------------------------------------------------------------------- + def sendReq(self, type_, d): + """鍙戦佽姹""" + self.beginParam() + + for k, v in d.items(): + self.setValue(str(k), str(v)) + + i = self.bizCallAndCommit(type_) + + return i + + #---------------------------------------------------------------------- + def generateReq(self): + """鐢熸垚鏍囧噯濮旀墭瀛楁鐨勫瓧鍏""" + d = { + "op_branch_no": self.branchNo, + "op_entrust_way": self.opEntrustWay, + "op_station": self.opStation, + "branch_no": self.branchNo, + "client_id": self.clientId, + "fund_account": self.fundAccount, + "password": self.password, + "asset_prop": "B", + "sysnode_Id": self.sysnodeId + } + + return d + + #---------------------------------------------------------------------- + def writeError(self, errorNo, errorInfo): + """""" + error = VtErrorData() + error.gatewayName = self.gatewayName + error.errorID = errorNo + error.errorMsg = errorInfo.decode('GBK') + self.gateway.onError(error) + + #---------------------------------------------------------------------- + def writeLog(self, content): + """""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + ########################################################### + + #---------------------------------------------------------------------- + def onLogin(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + self.branchNo = d['branch_no'] + self.clientId = d['client_id'] + self.fundAccount = d['fund_account'] + self.sysnodeId = d['sysnode_id'] + + self.loginStatus = True + self.writeLog(u'浜ゆ槗鏈嶅姟鍣ㄧ櫥褰曞畬鎴') + + self.subscribeOrder() + self.subscribeTrade() + self.qryContract() + + #---------------------------------------------------------------------- + def onSendOrder(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + batchNo = d['batch_no'] + self.batchEntrustDict[batchNo] = d['entrust_no'] + self.entrustBatchDict[d['entrust_no']] = batchNo + + # 妫鏌ユ槸鍚﹂渶瑕佹挙鍗 + if batchNo in self.cancelDict: + cancelReq = self.cancelDict[batchNo] + self.cancelOrder(cancelReq) + + # 鏇存柊鏁版嵁 + order = self.orderDict[batchNo] + t = d['entrust_time'].rjust(6, '0') + order.orderTime = ':'.join([t[:2], t[2:4], t[4:]]) + self.gateway.onOrder(order) + + #---------------------------------------------------------------------- + def onCancelOrder(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + #---------------------------------------------------------------------- + def onQryContract(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + contract = VtContractData() + contract.gatewayName = self.gatewayName + + contract.symbol = d['option_code'] + contract.exchange = exchangeMapReverse.get(d['exchange_type'], EXCHANGE_UNKNOWN) + contract.vtSymbol = '.'.join([contract.symbol, contract.exchange]) + contract.name = d['option_name'].decode('GBK') + contract.size = int(float(d['amount_per_hand'])) + contract.priceTick = float(d['opt_price_step']) + contract.strikePrice = float(d['exercise_price']) + contract.underlyingSymbol = d['stock_code'] + contract.productClass = PRODUCT_OPTION + contract.optionType = optionTypeMapReverse[d['option_type']] + + self.gateway.onContract(contract) + + self.writeLog(u'鍚堢害鏌ヨ瀹屾垚') + + self.qryOrder() + + #---------------------------------------------------------------------- + def onQryOrder(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.symbol = d['option_code'] + order.exchange = exchangeMapReverse.get(d['exchange_type'], EXCHANGE_UNKNOWN) + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + + #self.batchNo += 1 + #batchNo = str(self.batchNo) + batchNo = d['batch_no'] + self.batchNo = max(self.batchNo, int(batchNo)) + + order.orderID = batchNo + order.vtOrderID = '.'.join([order.gatewayName, order.orderID]) + + self.batchEntrustDict[batchNo] = d['entrust_no'] + self.entrustBatchDict[d['entrust_no']] = batchNo + + order.direction = directionMapReverse.get(d['entrust_bs'], DIRECTION_UNKNOWN) + order.offset = offsetMapReverse.get(d['entrust_oc'], OFFSET_UNKNOWN) + #order.status = statusMapReverse.get(d['entrust_status'], STATUS_UNKNOWN) + order.status = statusMapReverse.get(d['entrust_status'], d['entrust_status']) + + order.price = float(d['opt_entrust_price']) + order.totalVolume = int(float(d['entrust_amount'])) + order.tradedVolume = int(float(d['business_amount'])) + + t = d['entrust_time'].rjust(6, '0') + order.orderTime = ':'.join([t[:2], t[2:4], t[4:]]) + + self.gateway.onOrder(order) + + self.orderDict[batchNo] = order + + self.writeLog(u'濮旀墭鏌ヨ瀹屾垚') + + self.qryTrade() + + #---------------------------------------------------------------------- + def onQryTrade(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + trade = VtTradeData() + trade.gatewayName = self.gatewayName + + trade.symbol = d['option_code'] + trade.exchange = exchangeMapReverse.get(d['exchange_type'], EXCHANGE_UNKNOWN) + trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) + + batchNo = self.entrustBatchDict[d['entrust_no']] + trade.orderID = batchNo + trade.vtOrderID = '.'.join([trade.gatewayName, trade.orderID]) + + trade.tradeID = d['business_id'] + trade.vtTradeID = '.'.join([trade.gatewayName, trade.tradeID]) + + trade.direction = directionMapReverse.get(d['entrust_bs'], DIRECTION_UNKNOWN) + trade.offset = offsetMapReverse.get(d['entrust_oc'], OFFSET_UNKNOWN) + + trade.price = float(d['opt_business_price']) + trade.volume = int(float(d['business_amount'])) + + t = d['business_time'].rjust(6, '0') + trade.tradeTime= ':'.join([t[:2], t[2:4], t[4:]]) + + self.gateway.onTrade(trade) + + self.writeLog(u'鎴愪氦鏌ヨ瀹屾垚') + + #---------------------------------------------------------------------- + def onQryPosition(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + pos = VtPositionData() + pos.gatewayName = self.gatewayName + + pos.symbol = d['option_code'] + pos.exchange = exchangeMapReverse.get(d['exchange_type'], EXCHANGE_UNKNOWN) + pos.vtSymbol = '.'.join([pos.symbol, pos.exchange]) + pos.direction = posDirectionMapReverse.get(d['opthold_type'], DIRECTION_UNKNOWN) + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) + + pos.position = int(float(d['current_amount'])) + pos.positionProfit = float(d['income_balance']) + pos.price = float(d['opt_cost_price']) + pos.frozen = int((float(d['current_amount']) - float(d['enable_amount']))) + + self.gateway.onPosition(pos) + + #---------------------------------------------------------------------- + def onQryAccount(self, data, reqNo, errorNo, errorInfo): + """""" + if errorNo: + self.writeError(errorNo, errorInfo) + return + + for d in data: + account = VtAccountData() + account.gatewayName = self.gatewayName + + account.accountID = self.fundAccount + account.vtAccountID = '.'.join([self.gatewayName, account.accountID]) + account.available = float(d['enable_balance']) + account.margin = float(d['real_used_bail']) + account.positionProfit = float(d['income_balance']) + account.balance = float(d['total_asset']) + + self.gateway.onAccount(account) + + #---------------------------------------------------------------------- + def onRtnTrade(self, data, reqNo, errorNo, errorInfo): + """""" + for d in data: + # 鎾ゅ崟鍥炴姤business_amount灏忎簬0锛屽彲浠ラ氳繃鍏惰繘琛岃繃婊 + tradeVolume = int(float(d['business_amount'])) + entrustNo = d['entrust_no'] + batchNo = self.entrustBatchDict.get(entrustNo, '') + + # 鎴愪氦鎺ㄩ侊紝鍙湁褰撴垚浜ゆ暟閲忓ぇ浜0鏃 + if tradeVolume > 0: + trade = VtTradeData() + trade.gatewayName = self.gatewayName + + trade.symbol = d['option_code'] + trade.exchange = exchangeMapReverse.get(d['exchange_type'], EXCHANGE_UNKNOWN) + trade.vtSymbol = '.'.join([trade.symbol, trade.exchange]) + + trade.orderID = batchNo + trade.vtOrderID = '.'.join([trade.gatewayName, trade.orderID]) + + trade.tradeID = d['business_id'] + trade.vtTradeID = '.'.join([trade.gatewayName, trade.tradeID]) + + trade.direction = directionMapReverse.get(d['entrust_bs'], DIRECTION_UNKNOWN) + trade.offset = offsetMapReverse.get(d['entrust_oc'], OFFSET_UNKNOWN) + + trade.price = float(d['opt_business_price']) + trade.volume = int(float(d['business_amount'])) + + t = d['business_time'].rjust(6, '0') + trade.tradeTime= ':'.join([t[:2], t[2:4], t[4:]]) + + self.gateway.onTrade(trade) + + # 濮旀墭鎺ㄩ + order = self.orderDict[batchNo] + + if tradeVolume > 0: + order.tradedVolume += tradeVolume + + order.status = statusMapReverse.get(d['entrust_status'], STATUS_UNKNOWN) + + self.gateway.onOrder(order) + + #---------------------------------------------------------------------- + def onRtnOrder(self, data, reqNo, errorNo, errorInfo): + """""" + for d in data: + entrustNo = d['entrust_no'] + if entrustNo not in self.entrustBatchDict: + return + + batchNo = self.entrustBatchDict[entrustNo] + order = self.orderDict[batchNo] + + order.status = statusMapReverse.get(d['entrust_status'], STATUS_UNKNOWN) + order.tradedVolume = int(float(d['business_amount'])) + + self.gateway.onOrder(order) + + ########################################################### + + #---------------------------------------------------------------------- + def connect(self, opEntrustWay, opStation, fundAccount, password): + """""" + self.opEntrustWay = opEntrustWay + self.opStation = opStation + self.fundAccount = fundAccount + self.password = password + + # 璇诲彇閰嶇疆鏂囦欢 + i = self.loadConfig("Hsconfig.ini") + if i: + self.writeLog(u'浜ゆ槗鍔犺浇閰嶇疆澶辫触锛屽師鍥狅細%s' %self.getErrorMsg().decode('GBK')) + return + self.writeLog(u'浜ゆ槗鍔犺浇閰嶇疆鎴愬姛') + + # 鍒濆鍖 + i = self.init() + if i: + self.writeLog(u'浜ゆ槗鍒濆鍖栧け璐ワ紝鍘熷洜锛%s' %self.getErrorMsg().decode('GBK')) + return + self.writeLog(u'浜ゆ槗鍒濆鍖栨垚鍔') + + # 杩炴帴鏈嶅姟鍣 + i = self.connectServer() + if i: + self.writeLog(u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ュけ璐ワ紝鍘熷洜锛%s' %self.getErrorMsg().decode('GBK')) + return + self.writeLog(u'浜ゆ槗鏈嶅姟鍣ㄨ繛鎺ユ垚鍔') + + # 鐧诲綍 + req = {} + req['identity_type'] = '2' + req['password_type'] = '2' + req['input_content'] = '1' + req['op_entrust_way'] = self.opEntrustWay + req['password'] = self.password + req['account_content'] = self.fundAccount + self.sendReq(FUNCTION_LOGIN, req) + + #---------------------------------------------------------------------- + def sendOrder(self, orderReq): + """""" + req = self.generateReq() + + req['exchange_type'] = exchangeMap.get(orderReq.exchange, '') + req['option_code'] = orderReq.symbol + req['entrust_amount'] = str(orderReq.volume) + req['opt_entrust_price'] = str(orderReq.price) + req['entrust_bs'] = directionMap.get(orderReq.direction, '') + req['entrust_oc'] = offsetMap.get(orderReq.offset, '') + req['covered_flag'] = '' + req['entrust_prop'] = priceTypeMap.get(orderReq.priceType, '') + + self.batchNo += 1 + batchNo = str(self.batchNo) + req['batch_no'] = batchNo + + reqNo = self.sendReq(FUNCTION_SENDORDER, req) + + vtOrderID = '.'.join([self.gatewayName, batchNo]) + + # 缂撳瓨濮旀墭淇℃伅 + order = VtOrderData() + order.gatewayName = self.gatewayName + + order.symbol = orderReq.symbol + order.exchange = orderReq.exchange + order.vtSymbol = '.'.join([order.symbol, order.exchange]) + order.orderID = batchNo + order.vtOrderID = vtOrderID + order.direction = orderReq.direction + order.offset = orderReq.offset + order.price = orderReq.price + order.totalVolume = orderReq.volume + order.status = STATUS_UNKNOWN + + self.orderDict[batchNo] = order + + return vtOrderID + + #---------------------------------------------------------------------- + def cancelOrder(self, cancelReq): + """""" + # 濡傛灉灏氭湭鏀跺埌濮旀墭鐨勬煖鍙扮紪鍙凤紝鍒欑紦瀛樿鎾ゅ崟璇锋眰 + batchNo = cancelReq.orderID + if batchNo not in self.batchEntrustDict: + self.cancelDict[batchNo] = cancelReq + return + + # 鑾峰彇瀵瑰簲鐨勬煖鍙板鎵樺彿锛屽苟鎾ゅ崟 + entrustNo = self.batchEntrustDict[batchNo] + + req = self.generateReq() + req['entrust_no'] = entrustNo + + self.sendReq(FUNCTION_CANCELORDER, req) + + # 绉婚櫎鎾ゅ崟璇锋眰瀛楀吀涓殑缂撳瓨 + if batchNo in self.cancelDict: + del self.cancelDict[batchNo] + + #---------------------------------------------------------------------- + def qryContract(self): + """""" + req = self.generateReq() + #req = {} + self.sendReq(FUNCTION_QRYCONTRACT, req) + + #---------------------------------------------------------------------- + def qryPosition(self): + """""" + if not self.loginStatus: + return + + req = self.generateReq() + d['request_num'] = '1000' + self.sendReq(FUNCTION_QRYPOSITION, req) + + #---------------------------------------------------------------------- + def qryAccount(self): + """""" + if not self.loginStatus: + return + + req = self.generateReq() + d['money_type'] = 'cny' + self.sendReq(FUNCTION_QRYACCOUNT, req) + + #---------------------------------------------------------------------- + def qryTrade(self): + """""" + req = self.generateReq() + self.sendReq(FUNCTION_QRYTRADE, req) + + #---------------------------------------------------------------------- + def qryOrder(self): + """""" + req = self.generateReq() + self.sendReq(FUNCTION_QRYORDER, req) + + #---------------------------------------------------------------------- + def subscribeOrder(self): + """""" + req = {} + req['acc_info'] = '~'.join([self.branchNo, self.fundAccount]) + req['issue_Type'] = ISSUE_ORDER + + self.beginParam() + for k, v in req.items(): + self.setValue(str(k), str(v)) + + l = self.subscribeData(FUNCTION_SUBSCRIBE) + for d in l: + self.writeLog(u'濮旀墭鎺ㄩ侊細%s' %d['result_info'].decode('GBK')) + + #---------------------------------------------------------------------- + def subscribeTrade(self): + """""" + req = {} + req['acc_info'] = '~'.join([self.branchNo, self.fundAccount]) + req['issue_Type'] = ISSUE_TRADE + + self.beginParam() + + for k, v in req.items(): + self.setValue(str(k), str(v)) + + l = self.subscribeData(FUNCTION_SUBSCRIBE) + for d in l: + self.writeLog(u'鎴愪氦鎺ㄩ侊細%s' %d['result_info'].decode('GBK')) + + +######################################################################## +class CshshlpMdApi(MdApi): + """琛屾儏API瀹炵幇锛屼娇鐢ㄧ殑CTP鎺ュ彛锛屼絾鏄瓧娈典笂鍜宑tpGateway鏈夊尯鍒""" + + #---------------------------------------------------------------------- + def __init__(self, gateway): + """Constructor""" + super(CshshlpMdApi, self).__init__() + + self.gateway = gateway # gateway瀵硅薄 + self.gatewayName = gateway.gatewayName # gateway瀵硅薄鍚嶇О + + self.reqID = EMPTY_INT # 鎿嶄綔璇锋眰缂栧彿 + + self.connectionStatus = False # 杩炴帴鐘舵 + self.loginStatus = False # 鐧诲綍鐘舵 + + self.subscribedSymbols = set() # 宸茶闃呭悎绾︿唬鐮 + + self.userID = EMPTY_STRING # 璐﹀彿 + self.password = EMPTY_STRING # 瀵嗙爜 + self.brokerID = EMPTY_STRING # 缁忕邯鍟嗕唬鐮 + self.address = EMPTY_STRING # 鏈嶅姟鍣ㄥ湴鍧 + + #---------------------------------------------------------------------- + def onFrontConnected(self): + """鏈嶅姟鍣ㄨ繛鎺""" + self.connectionStatus = True + + self.writeLog(u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ垚鍔') + + self.login() + + #---------------------------------------------------------------------- + def onFrontDisconnected(self, n): + """鏈嶅姟鍣ㄦ柇寮""" + self.connectionStatus = False + self.loginStatus = False + self.gateway.mdConnected = False + + self.writeLog(u'琛屾儏鏈嶅姟鍣ㄨ繛鎺ユ柇寮') + + #---------------------------------------------------------------------- + def onHeartBeatWarning(self, n): + """蹇冭烦鎶ヨ""" + # 鍥犱负API鐨勫績璺虫姤璀︽瘮杈冨父琚Е鍙戯紝涓斾笌API宸ヤ綔鍏崇郴涓嶅ぇ锛屽洜姝ら夋嫨蹇界暐 + pass + + #---------------------------------------------------------------------- + def onRspError(self, error, n, last): + """閿欒鍥炴姤""" + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onRspUserLogin(self, data, error, n, last): + """鐧婚檰鍥炴姤""" + # 濡傛灉鐧诲綍鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.loginStatus = True + self.gateway.mdConnected = True + + self.writeLog(u'琛屾儏鏈嶅姟鍣ㄧ櫥褰曟垚鍔') + + # 閲嶆柊璁㈤槄涔嬪墠璁㈤槄鐨勫悎绾 + for subscribeReq in self.subscribedSymbols: + self.subscribe(subscribeReq) + + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onRspUserLogout(self, data, error, n, last): + """鐧诲嚭鍥炴姤""" + # 濡傛灉鐧诲嚭鎴愬姛锛屾帹閫佹棩蹇椾俊鎭 + if error['ErrorID'] == 0: + self.loginStatus = False + self.gateway.mdConnected = False + + self.writeLog(u'琛屾儏鏈嶅姟鍣ㄧ櫥鍑烘垚鍔') + + # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 + else: + err = VtErrorData() + err.gatewayName = self.gatewayName + err.errorID = error['ErrorID'] + err.errorMsg = error['ErrorMsg'].decode('gbk') + self.gateway.onError(err) + + #---------------------------------------------------------------------- + def onRspSubMarketData(self, data, error, n, last): + """璁㈤槄鍚堢害鍥炴姤""" + # 閫氬父涓嶅湪涔庤闃呴敊璇紝閫夋嫨蹇界暐 + pass + + #---------------------------------------------------------------------- + def onRspUnSubMarketData(self, data, error, n, last): + """閫璁㈠悎绾﹀洖鎶""" + # 鍚屼笂 + pass + + #---------------------------------------------------------------------- + def onRtnDepthMarketData(self, data): + """琛屾儏鎺ㄩ""" + # 蹇界暐鎴愪氦閲忎负0鐨勬棤鏁坱ick鏁版嵁 + if not data['Volume']: + return + + # 鍒涘缓瀵硅薄 + tick = VtTickData() + tick.gatewayName = self.gatewayName + + tick.symbol = data['InstrumentID'] + tick.exchange = exchangeMapReverse.get(data['ExchangeID'], EXCHANGE_UNKNOWN) + tick.vtSymbol = '.'.join([tick.symbol, tick.exchange]) + + tick.lastPrice = data['LastPrice'] + tick.volume = data['Volume'] + tick.openInterest = data['OpenInterest'] + tick.time = '.'.join([data['UpdateTime'], str(data['UpdateMillisec']/100)]) + tick.date = data['TradingDay'] + + tick.openPrice = data['OpenPrice'] + tick.highPrice = data['HighestPrice'] + tick.lowPrice = data['LowestPrice'] + tick.preClosePrice = data['PreClosePrice'] + + tick.upperLimit = data['UpperLimitPrice'] + tick.lowerLimit = data['LowerLimitPrice'] + + # 鏈熸潈鏈変簲妗h鎯 + tick.bidPrice1 = data['BidPrice1'] + tick.bidPrice2 = data['BidPrice2'] + tick.bidPrice3 = data['BidPrice3'] + tick.bidPrice4 = data['BidPrice4'] + tick.bidPrice5 = data['BidPrice5'] + + tick.askPrice1 = data['AskPrice1'] + tick.askPrice2 = data['AskPrice2'] + tick.askPrice3 = data['AskPrice3'] + tick.askPrice4 = data['AskPrice4'] + tick.askPrice5 = data['AskPrice5'] + + tick.bidVolume1 = data['BidVolume1'] + tick.bidVolume2 = data['BidVolume2'] + tick.bidVolume3 = data['BidVolume3'] + tick.bidVolume4 = data['BidVolume4'] + tick.bidVolume5 = data['BidVolume5'] + + tick.askVolume1 = data['AskVolume1'] + tick.askVolume2 = data['AskVolume2'] + tick.askVolume3 = data['AskVolume3'] + tick.askVolume4 = data['AskVolume4'] + tick.askVolume5 = data['AskVolume5'] + + self.gateway.onTick(tick) + + #---------------------------------------------------------------------- + def onRspSubForQuoteRsp(self, data, error, n, last): + """璁㈤槄鏈熸潈璇环""" + pass + + #---------------------------------------------------------------------- + def onRspUnSubForQuoteRsp(self, data, error, n, last): + """閫璁㈡湡鏉冭浠""" + pass + + #---------------------------------------------------------------------- + def onRtnForQuoteRsp(self, data): + """鏈熸潈璇环鎺ㄩ""" + pass + + #---------------------------------------------------------------------- + def connect(self, userID, password, brokerID, address): + """鍒濆鍖栬繛鎺""" + self.userID = userID # 璐﹀彿 + self.password = password # 瀵嗙爜 + self.brokerID = brokerID # 缁忕邯鍟嗕唬鐮 + self.address = address # 鏈嶅姟鍣ㄥ湴鍧 + + # 濡傛灉灏氭湭寤虹珛鏈嶅姟鍣ㄨ繛鎺ワ紝鍒欒繘琛岃繛鎺 + if not self.connectionStatus: + # 鍒涘缓C++鐜涓殑API瀵硅薄锛岃繖閲屼紶鍏ョ殑鍙傛暟鏄渶瑕佺敤鏉ヤ繚瀛.con鏂囦欢鐨勬枃浠跺す璺緞 + path = os.getcwd() + '/temp/' + self.gatewayName + '/' + if not os.path.exists(path): + os.makedirs(path) + self.createFtdcMdApi(path) + + # 娉ㄥ唽鏈嶅姟鍣ㄥ湴鍧 + self.registerFront(self.address) + + # 鍒濆鍖栬繛鎺ワ紝鎴愬姛浼氳皟鐢╫nFrontConnected + self.init() + + # 鑻ュ凡缁忚繛鎺ヤ絾灏氭湭鐧诲綍锛屽垯杩涜鐧诲綍 + else: + if not self.loginStatus: + self.login() + + #---------------------------------------------------------------------- + def subscribe(self, subscribeReq): + """璁㈤槄鍚堢害""" + # 杩欓噷鐨勮璁℃槸锛屽鏋滃皻鏈櫥褰曞氨璋冪敤浜嗚闃呮柟娉 + # 鍒欏厛淇濆瓨璁㈤槄璇锋眰锛岀櫥褰曞畬鎴愬悗浼氳嚜鍔ㄨ闃 + if self.loginStatus: + self.subscribeMarketData(str(subscribeReq.symbol)) + self.subscribedSymbols.add(subscribeReq) + + #---------------------------------------------------------------------- + def login(self): + """鐧诲綍""" + # 濡傛灉濉叆浜嗙敤鎴峰悕瀵嗙爜绛夛紝鍒欑櫥褰 + if self.userID and self.password and self.brokerID: + req = {} + req['UserID'] = self.userID + req['Password'] = self.password + req['BrokerID'] = self.brokerID + self.reqID += 1 + self.reqUserLogin(req, self.reqID) + + #---------------------------------------------------------------------- + def close(self): + """鍏抽棴""" + self.exit() + + #---------------------------------------------------------------------- + def writeLog(self, content): + """鍙戝嚭鏃ュ織""" + log = VtLogData() + log.gatewayName = self.gatewayName + log.logContent = content + self.gateway.onLog(log) + + + + diff --git a/vnpy/trader/gateway/xspeedGateway/xspeedGateway.py b/vnpy/trader/gateway/xspeedGateway/xspeedGateway.py index b9fddcbf..65ea4307 100644 --- a/vnpy/trader/gateway/xspeedGateway/xspeedGateway.py +++ b/vnpy/trader/gateway/xspeedGateway/xspeedGateway.py @@ -30,9 +30,10 @@ offsetMap = {} offsetMap[OFFSET_OPEN] = defineDict['DFITC_SPD_OPEN'] offsetMap[OFFSET_CLOSE] = defineDict['DFITC_SPD_CLOSE'] offsetMap[OFFSET_CLOSETODAY] = defineDict['DFITC_SPD_CLOSETODAY'] -offsetMap[OFFSET_CLOSEYESTERDAY] = defineDict['DFITC_SPD_CLOSE'] +#offsetMap[OFFSET_CLOSEYESTERDAY] = defineDict['DFITC_SPD_CLOSE'] offsetMapReverse = {v:k for k,v in offsetMap.items()} + # 浜ゆ槗鎵绫诲瀷鏄犲皠 exchangeMap = {} exchangeMap[EXCHANGE_CFFEX] = defineDict['DFITC_EXCHANGE_CFFEX'] @@ -42,6 +43,12 @@ exchangeMap[EXCHANGE_DCE] = defineDict['DFITC_EXCHANGE_DCE'] exchangeMap[EXCHANGE_UNKNOWN] = '' exchangeMapReverse = {v:k for k,v in exchangeMap.items()} +# 鍚堢害绫诲瀷鏄犲皠 +productMap = {} +productMap[PRODUCT_FUTURES] = defineDict["DFITC_COMM_TYPE"] +productMap[PRODUCT_OPTION] = defineDict["DFITC_OPT_TYPE"] +productMapReverse = {v:k for k, v in productMap.items()} + # 濮旀墭鐘舵佺被鍨嬫槧灏 orderStatusMap = {} orderStatusMap[STATUS_ALLTRADED] = defineDict["DFITC_SPD_FILLED"] @@ -128,9 +135,14 @@ class XspeedGateway(VtGateway): self.tdApi.qryAccount() #---------------------------------------------------------------------- - def qryPosition(self): + def qryFuturesPosition(self): """鏌ヨ鎸佷粨""" - self.tdApi.qryPosition() + self.tdApi.qryFuturesPosition() + + #---------------------------------------------------------------------- + def qryOptionPosition(self): + """鏌ヨ鏈熸潈鎸佷粨""" + self.tdApi.qryOptionPosition() #---------------------------------------------------------------------- def close(self): @@ -145,10 +157,10 @@ class XspeedGateway(VtGateway): """鍒濆鍖栬繛缁煡璇""" if self.qryEnabled: # 闇瑕佸惊鐜殑鏌ヨ鍑芥暟鍒楄〃 - self.qryFunctionList = [self.qryAccount, self.qryPosition] + self.qryFunctionList = [self.qryAccount, self.qryFuturesPosition, self.qryOptionPosition] self.qryCount = 0 # 鏌ヨ瑙﹀彂鍊掕鏃 - self.qryTrigger = 2 # 鏌ヨ瑙﹀彂鐐 + self.qryTrigger = 1 # 鏌ヨ瑙﹀彂鐐 self.qryNextFunction = 0 # 涓婃杩愯鐨勬煡璇㈠嚱鏁扮储寮 self.startQuery() @@ -422,8 +434,14 @@ class XspeedTdApi(TdApi): self.sessionID = EMPTY_INT # 浼氳瘽缂栧彿 self.posDict = {} # 缂撳瓨鎸佷粨鏁版嵁鐨勫瓧鍏 + self.optionPosReqID = 0 # 鏈熸潈鎸佷粨鏌ヨID + self.futuresPosReqID = 0 # 鏈熻揣鎸佷粨鏌ヨID + self.optionPosCompleted = False + self.futuresPosCompleted = False + self.orderDict = {} # 缂撳瓨濮旀墭鏁版嵁鐨勫瓧鍏 self.spdOrderDict = {} # 椋炲垱鏌滃彴濮旀墭鍙峰瓧鍏 + self.contractDict = {} # 缂撳瓨鍚堢害鏁版嵁鐨勫瓧鍏 #---------------------------------------------------------------------- def connect(self, accountID, password, address): @@ -466,13 +484,90 @@ class XspeedTdApi(TdApi): self.reqQryCustomerCapital(req) #---------------------------------------------------------------------- - def qryPosition(self): - """鏌ヨ鎸佷粨""" + def qryFuturesPosition(self): + """鏌ヨ鏈熻揣鎸佷粨""" + # 娓呯┖缂撳瓨 + self.posDict.clear() + self.reqID += 1 req = {} req['lRequestID'] = self.reqID req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_COMM_TYPE"] self.reqQryPosition(req) + self.futuresPosReqID = self.reqID + + #---------------------------------------------------------------------- + def qryOptionPosition(self): + """鏌ヨ鏈熸潈鎸佷粨""" + self.posDict.clear() + + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_OPT_TYPE"] + self.reqQryPosition(req) + self.optionPosReqID = self.reqID + + #---------------------------------------------------------------------- + def qryContracts(self): + """鏌ヨ鍚堢害""" + # 鏌ヨ鏈熻揣鍚堢害浠g爜 + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['instrumentType'] = defineDict["DFITC_COMM_TYPE"] + self.reqQryExchangeInstrument(req) + + sleep(1) + + # 鏌ヨ鏈熸潈鍚堢害浠g爜 + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['instrumentType'] = defineDict["DFITC_OPT_TYPE"] + self.reqQryExchangeInstrument(req) + + #---------------------------------------------------------------------- + def qryTrade(self): + """鏌ヨ鎴愪氦""" + # 鏌ヨ鎴愪氦 + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_COMM_TYPE"] + self.reqQryMatchInfo(req) + + sleep(1) + + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_OPT_TYPE"] + self.reqQryMatchInfo(req) + + #---------------------------------------------------------------------- + def qryOrder(self): + """鏌ヨ濮旀墭""" + # 鏌ヨ濮旀墭 + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_COMM_TYPE"] + self.reqQryOrderInfo(req) + + sleep(1) + + self.reqID += 1 + req = {} + req['lRequestID'] = self.reqID + req['accountID'] = self.accountID + req['instrumentType'] = defineDict["DFITC_OPT_TYPE"] + self.reqQryOrderInfo(req) #---------------------------------------------------------------------- def sendOrder(self, orderReq): @@ -499,6 +594,11 @@ class XspeedTdApi(TdApi): req['minMatchAmount'] = 1 # 鏈灏忔垚浜ら噺涓1 req['lRequestID'] = self.reqID + # 鍚堢害绫诲瀷鑾峰彇 + contract = self.contractDict.get(orderReq.symbol, None) + if contract: + req['instrumentType'] = productMap.get(contract.productClass, '') + self.reqInsertOrder(req) # 杩斿洖璁㈠崟鍙凤紙瀛楃涓诧級锛屼究浜庢煇浜涚畻娉曡繘琛屽姩鎬佺鐞 @@ -568,11 +668,7 @@ class XspeedTdApi(TdApi): log.logContent = u'浜ゆ槗鏈嶅姟鍣ㄧ櫥褰曞畬鎴' self.gateway.onLog(log) - # 鏌ヨ鍚堢害浠g爜 - self.reqID += 1 - req = {} - req['lRequestID'] = self.reqID - self.reqQryExchangeInstrument(req) + self.qryContracts() # 鍚﹀垯锛屾帹閫侀敊璇俊鎭 else: @@ -607,6 +703,16 @@ class XspeedTdApi(TdApi): def onRspInsertOrder(self, data, error) : """鍙戝崟閿欒锛堟煖鍙帮級""" if error['nErrorID']: + order = VtOrderData() + order.gatewayName = self.gatewayName + order.symbol = error['instrumentID'] + order.vtSymbol = order.symbol + order.orderID = str(error['localOrderID']) + order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) + order.sessionID = error['sessionID'] + order.status = STATUS_REJECTED + self.gateway.onOrder(order) + err = VtErrorData() err.gatewayName = self.gatewayName err.errorID = error['nErrorID'] @@ -751,43 +857,41 @@ class XspeedTdApi(TdApi): #---------------------------------------------------------------------- def onRspQryOrderInfo(self, data, error, last) : """鏌ヨ濮旀墭鍥炴姤""" - if not data['localOrderID']: - return - - # 鏇存柊鏈澶ф姤鍗曠紪鍙 - newLocalID = data['localOrderID'] - self.localID = max(self.localID, int(newLocalID)) - self.spdOrderDict[newLocalID] = data['spdOrderID'] - - # 鑾峰彇鎶ュ崟鏁版嵁瀵硅薄 - if newLocalID in self.orderDict: - order = self.orderDict[newLocalID] - else: - order = VtOrderData() - self.orderDict[newLocalID] = order - order.gatewayName = self.gatewayName - - # 淇濆瓨鍚庣画涓嶄細鍙樺寲鐨勬暟鎹 - order.symbol = data['instrumentID'] - order.exchange = exchangeMapReverse[data['exchangeID']] - order.vtSymbol = order.symbol + if data['instrumentID']: + # 鏇存柊鏈澶ф姤鍗曠紪鍙 + newLocalID = data['localOrderID'] + self.localID = max(self.localID, int(newLocalID)) + self.spdOrderDict[newLocalID] = data['spdOrderID'] - order.orderID = str(newLocalID) - order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) + # 鑾峰彇鎶ュ崟鏁版嵁瀵硅薄 + if newLocalID in self.orderDict: + order = self.orderDict[newLocalID] + else: + order = VtOrderData() + self.orderDict[newLocalID] = order + order.gatewayName = self.gatewayName - order.direction = directionMapReverse.get(data['buySellType'], DIRECTION_UNKNOWN) - order.offset = offsetMapReverse.get(data['openClose'], OFFSET_UNKNOWN) - - order.price = data['insertPrice'] - order.totalVolume = data['orderAmount'] - #order.sessionID = data['sessionID'] - - order.status = orderStatusMapReverse.get(data['orderStatus'], STATUS_UNKNOWN) - order.tradedVolume = data['matchedAmount'] - order.orderTime = data['commTime'] + # 淇濆瓨鍚庣画涓嶄細鍙樺寲鐨勬暟鎹 + order.symbol = data['instrumentID'] + order.exchange = exchangeMapReverse[data['exchangeID']] + order.vtSymbol = order.symbol + + order.orderID = str(newLocalID) + order.vtOrderID = '.'.join([self.gatewayName, order.orderID]) + + order.direction = directionMapReverse.get(data['buySellType'], DIRECTION_UNKNOWN) + order.offset = offsetMapReverse.get(data['openClose'], OFFSET_UNKNOWN) + + order.price = data['insertPrice'] + order.totalVolume = data['orderAmount'] + #order.sessionID = data['sessionID'] + + order.status = orderStatusMapReverse.get(data['orderStatus'], STATUS_UNKNOWN) + order.tradedVolume = data['matchedAmount'] + order.orderTime = data['commTime'] - # 鎺ㄩ - self.gateway.onOrder(copy(order)) + # 鎺ㄩ + self.gateway.onOrder(copy(order)) if last: log = VtLogData() @@ -798,34 +902,35 @@ class XspeedTdApi(TdApi): #---------------------------------------------------------------------- def onRspQryMatchInfo(self, data, error, last) : """""" - # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 - trade = VtTradeData() - trade.gatewayName = self.gatewayName - - # 淇濆瓨浠g爜鍜屾姤鍗曞彿 - trade.symbol = data['instrumentID'] - trade.exchange = exchangeMapReverse.get(data['exchangeID'], EXCHANGE_UNKNOWN) - trade.vtSymbol = trade.symbol #'.'.join([trade.symbol, trade.exchange]) - - trade.tradeID = data['matchedID'] - trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID]) - - trade.orderID = str(data['localOrderID']) - trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID]) - - # 鏂瑰悜 - trade.direction = directionMapReverse.get(data['buySellType'], DIRECTION_UNKNOWN) + if data['instrumentID']: + # 鍒涘缓鎶ュ崟鏁版嵁瀵硅薄 + trade = VtTradeData() + trade.gatewayName = self.gatewayName - # 寮骞 - trade.offset = offsetMapReverse.get(data['openClose'], OFFSET_UNKNOWN) + # 淇濆瓨浠g爜鍜屾姤鍗曞彿 + trade.symbol = data['instrumentID'] + trade.exchange = exchangeMapReverse.get(data['exchangeID'], EXCHANGE_UNKNOWN) + trade.vtSymbol = trade.symbol #'.'.join([trade.symbol, trade.exchange]) - # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 - trade.price = data['matchedPrice'] - trade.volume = data['matchedAmount'] - trade.tradeTime = data['matchedTime'] - - # 鎺ㄩ - self.gateway.onTrade(trade) + trade.tradeID = data['matchedID'] + trade.vtTradeID = '.'.join([self.gatewayName, trade.tradeID]) + + trade.orderID = str(data['localOrderID']) + trade.vtOrderID = '.'.join([self.gatewayName, trade.orderID]) + + # 鏂瑰悜 + trade.direction = directionMapReverse.get(data['buySellType'], DIRECTION_UNKNOWN) + + # 寮骞 + trade.offset = offsetMapReverse.get(data['openClose'], OFFSET_UNKNOWN) + + # 浠锋牸銆佹姤鍗曢噺绛夋暟鍊 + trade.price = data['matchedPrice'] + trade.volume = data['matchedAmount'] + trade.tradeTime = data['matchedTime'] + + # 鎺ㄩ + self.gateway.onTrade(trade) if last: log = VtLogData() @@ -836,44 +941,50 @@ class XspeedTdApi(TdApi): #---------------------------------------------------------------------- def onRspQryPosition(self, data, error, last) : """鎸佷粨鏌ヨ鍥炴姤""" - # 鑾峰彇缂撳瓨瀛楀吀涓殑鎸佷粨瀵硅薄锛岃嫢鏃犲垯鍒涘缓骞跺垵濮嬪寲 - positionName = '.'.join([data['instrumentID'], str(data['buySellType'])]) - - if positionName in self.posDict: - pos = self.posDict[positionName] - else: - pos = VtPositionData() - self.posDict[positionName] = pos - - pos.gatewayName = self.gatewayName - - # 淇濆瓨浠g爜 - pos.symbol = data['instrumentID'] - pos.vtSymbol = pos.symbol # 杩欓噷鍥犱负data涓病鏈塃xchangeID杩欎釜瀛楁 - - # 鏂瑰悜 - pos.direction = directionMapReverse.get(data['buySellType'], '') - - # VT绯荤粺鎸佷粨鍚 - pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) - - # 鎸佷粨閲 - if data['positionAmount']: - pos.position = data['positionAmount'] - - if data['lastAmount']: - pos.ydPosition = data['lastAmount'] - - # 鎸佷粨鍧囦环 - pos.price = data['positionAvgPrice'] - - # 鎺ㄩ - newpos = copy(pos) - self.gateway.onPosition(newpos) + # 蹇界暐绌烘暟鎹 + if data['instrumentID']: + # 鑾峰彇缂撳瓨瀛楀吀涓殑鎸佷粨瀵硅薄锛岃嫢鏃犲垯鍒涘缓骞跺垵濮嬪寲 + positionName = '.'.join([data['instrumentID'], str(data['buySellType'])]) + + if positionName in self.posDict: + pos = self.posDict[positionName] + else: + pos = VtPositionData() + self.posDict[positionName] = pos + + pos.gatewayName = self.gatewayName + + # 淇濆瓨浠g爜 + pos.symbol = data['instrumentID'] + pos.vtSymbol = pos.symbol # 杩欓噷鍥犱负data涓病鏈塃xchangeID杩欎釜瀛楁 + + # 鏂瑰悜 + pos.direction = directionMapReverse.get(data['buySellType'], '') + + # VT绯荤粺鎸佷粨鍚 + pos.vtPositionName = '.'.join([pos.vtSymbol, pos.direction]) + + # 鎸佷粨閲 + if data['positionAmount']: + pos.position = data['positionAmount'] + + if data['lastAmount']: + pos.ydPosition = data['lastAmount'] + + # 鎸佷粨鍧囦环 + pos.price = data['positionAvgPrice'] + + # 鏌ヨ瀹屾垚鍚庢帹閫 + if last: + for pos in self.posDict.values(): + self.gateway.onPosition(pos) #---------------------------------------------------------------------- def onRspCustomerCapital(self, data, error, last) : """璧勯噾璐︽埛鏌ヨ鍥炴姤""" + if not data['accountID']: + return + account = VtAccountData() account.gatewayName = self.gatewayName @@ -888,7 +999,8 @@ class XspeedTdApi(TdApi): account.margin = data['margin'] account.closeProfit = data['closeProfitLoss'] account.positionProfit = data['positionProfitLoss'] - account.balance = data['todayEquity'] + account.balance = data['todayEquity'] + account.marketValue = account.balance + data['optMarketValue'] # 鎺ㄩ self.gateway.onAccount(account) @@ -902,21 +1014,21 @@ class XspeedTdApi(TdApi): contract.symbol = data['instrumentID'] contract.exchange = exchangeMapReverse.get(data['exchangeID'], EXCHANGE_UNKNOWN) contract.vtSymbol = contract.symbol #'.'.join([contract.symbol, contract.exchange]) - contract.name = data['VarietyName'].decode('GBK') + contract.symbol + if data['VarietyName'] == contract.symbol: + contract.name = data['VarietyName'] + else: + contract.name = data['VarietyName'].decode('GBK') + contract.symbol # 鍚堢害鏁板 - contract.size = data['contractMultiplier'] + contract.size = int(data['contractMultiplier']) contract.priceTick = data['minPriceFluctuation'] contract.strikePrice = data['strikePrice'] contract.underlyingSymbol = data['underlying'] + contract.expiryDate = data['instrumentMaturity'].replace('.', '') # 鍚堢害绫诲瀷 - if data['instrumentType'] == 0: - contract.productClass = PRODUCT_FUTURES - elif data['instrumentType'] == 1: - contract.productClass = PRODUCT_OPTION - else: - contract.productClass = PRODUCT_UNKNOWN + contract.productClass = productMapReverse.get(data['instrumentType'], + PRODUCT_UNKNOWN) # 鏈熸潈绫诲瀷 if data['optionType'] == 1: @@ -926,26 +1038,17 @@ class XspeedTdApi(TdApi): # 鎺ㄩ self.gateway.onContract(contract) + self.contractDict[contract.symbol] = contract - if last: + if last and contract.productClass == PRODUCT_OPTION: log = VtLogData() log.gatewayName = self.gatewayName log.logContent = u'浜ゆ槗鍚堢害淇℃伅鑾峰彇瀹屾垚' self.gateway.onLog(log) - # 鏌ヨ濮旀墭 - self.reqID += 1 - req = {} - req['lRequestID'] = self.reqID - req['accountID'] = self.accountID - self.reqQryOrderInfo(req) - - # 鏌ヨ鎴愪氦 - self.reqID += 1 - req = {} - req['lRequestID'] = self.reqID - req['accountID'] = self.accountID - self.reqQryMatchInfo(req) + self.qryTrade() + sleep(1) + self.qryOrder() #---------------------------------------------------------------------- def onRspArbitrageInstrument(self, data, error, last) : diff --git a/vnpy/trader/language/chinese/constant.py b/vnpy/trader/language/chinese/constant.py index 908f8184..8f1a1c3e 100644 --- a/vnpy/trader/language/chinese/constant.py +++ b/vnpy/trader/language/chinese/constant.py @@ -12,7 +12,8 @@ DIRECTION_LONG = u'澶' DIRECTION_SHORT = u'绌' DIRECTION_UNKNOWN = u'鏈煡' DIRECTION_NET = u'鍑' -DIRECTION_SELL = u'鍗栧嚭' # IB鎺ュ彛 +DIRECTION_SELL = u'鍗栧嚭' # IB鎺ュ彛 +DIRECTION_COVEREDSHORT = u'澶囧厬绌' # 璇佸埜鏈熸潈 # 寮骞冲父閲 OFFSET_NONE = u'鏃犲紑骞' diff --git a/vnpy/trader/language/english/constant.py b/vnpy/trader/language/english/constant.py index 579c15b3..dae1c9bf 100644 --- a/vnpy/trader/language/english/constant.py +++ b/vnpy/trader/language/english/constant.py @@ -13,6 +13,7 @@ DIRECTION_SHORT = u'short' DIRECTION_UNKNOWN = u'unknown' DIRECTION_NET = u'net' DIRECTION_SELL = u'sell' # IB鎺ュ彛 +DIRECTION_COVEREDSHORT = u'covered short' # 璇佸埜鏈熸潈 # 寮骞冲父閲 OFFSET_NONE = u'none' diff --git a/vnpy/trader/riskManager/uiRmWidget.py b/vnpy/trader/riskManager/uiRmWidget.py index 012579bb..ade41c09 100644 --- a/vnpy/trader/riskManager/uiRmWidget.py +++ b/vnpy/trader/riskManager/uiRmWidget.py @@ -24,8 +24,6 @@ class RmSpinBox(QtWidgets.QSpinBox): self.setValue(value) - - ######################################################################## class RmLine(QtWidgets.QFrame): @@ -38,8 +36,6 @@ class RmLine(QtWidgets.QFrame): self.setFrameShape(self.HLine) self.setFrameShadow(self.Sunken) - - ######################################################################## class RmEngineManager(QtWidgets.QWidget): @@ -62,7 +58,7 @@ class RmEngineManager(QtWidgets.QWidget): self.setWindowTitle(text.RISK_MANAGER) # 璁剧疆鐣岄潰 - self.buttonSwitchEngineStatus = QtGui.QPushButton(text.RISK_MANAGER_STOP) + self.buttonSwitchEngineStatus = QtWidgets.QPushButton(text.RISK_MANAGER_STOP) self.spinOrderFlowLimit = RmSpinBox(self.rmEngine.orderFlowLimit) self.spinOrderFlowClear = RmSpinBox(self.rmEngine.orderFlowClear) @@ -71,12 +67,12 @@ class RmEngineManager(QtWidgets.QWidget): self.spinWorkingOrderLimit = RmSpinBox(self.rmEngine.workingOrderLimit) self.spinOrderCancelLimit = RmSpinBox(self.rmEngine.orderCancelLimit) - buttonClearOrderFlowCount = QtGui.QPushButton(text.CLEAR_ORDER_FLOW_COUNT) - buttonClearTradeCount = QtGui.QPushButton(text.CLEAR_TOTAL_FILL_COUNT) - buttonSaveSetting = QtGui.QPushButton(text.SAVE_SETTING) + buttonClearOrderFlowCount = QtWidgets.QPushButton(text.CLEAR_ORDER_FLOW_COUNT) + buttonClearTradeCount = QtWidgets.QPushButton(text.CLEAR_TOTAL_FILL_COUNT) + buttonSaveSetting = QtWidgets.QPushButton(text.SAVE_SETTING) - Label = QtGui.QLabel - grid = QtGui.QGridLayout() + Label = QtWidgets.QLabel + grid = QtWidgets.QGridLayout() grid.addWidget(Label(text.WORKING_STATUS), 0, 0) grid.addWidget(self.buttonSwitchEngineStatus, 0, 1) grid.addWidget(RmLine(), 1, 0, 1, 2) @@ -97,13 +93,13 @@ class RmEngineManager(QtWidgets.QWidget): grid.addWidget(Label(text.CONTRACT_CANCEL_LIMIT), 11, 0) grid.addWidget(self.spinOrderCancelLimit, 11, 1) - hbox = QtGui.QHBoxLayout() + hbox = QtWidgets.QHBoxLayout() hbox.addWidget(buttonClearOrderFlowCount) hbox.addWidget(buttonClearTradeCount) hbox.addStretch() hbox.addWidget(buttonSaveSetting) - vbox = QtGui.QVBoxLayout() + vbox = QtWidgets.QVBoxLayout() vbox.addLayout(grid) vbox.addLayout(hbox) self.setLayout(vbox) diff --git a/vnpy/trader/uiBasicWidget.py b/vnpy/trader/uiBasicWidget.py index 4f1d7fdd..6f02f910 100644 --- a/vnpy/trader/uiBasicWidget.py +++ b/vnpy/trader/uiBasicWidget.py @@ -101,9 +101,9 @@ class DirectionCell(QtWidgets.QTableWidgetItem): def setContent(self, text): """璁剧疆鍐呭""" if text == DIRECTION_LONG or text == DIRECTION_NET: - self.setForeground(QtWidgets.QColor('red')) + self.setForeground(QtGui.QColor('red')) elif text == DIRECTION_SHORT: - self.setForeground(QtWidgets.QColor('green')) + self.setForeground(QtGui.QColor('green')) self.setText(text) @@ -144,8 +144,8 @@ class BidCell(QtWidgets.QTableWidgetItem): super(BidCell, self).__init__() self.data = None - self.setForeground(QtWidgets.QColor('black')) - self.setBackground(QtWidgets.QColor(255,174,201)) + self.setForeground(QtGui.QColor('black')) + self.setBackground(QtGui.QColor(255,174,201)) if text: self.setContent(text) @@ -166,8 +166,8 @@ class AskCell(QtWidgets.QTableWidgetItem): super(AskCell, self).__init__() self.data = None - self.setForeground(QtWidgets.QColor('black')) - self.setBackground(QtWidgets.QColor(160,255,160)) + self.setForeground(QtGui.QColor('black')) + self.setBackground(QtGui.QColor(160,255,160)) if text: self.setContent(text) @@ -392,7 +392,8 @@ class BasicMonitor(QtWidgets.QTableWidget): path = QtWidgets.QFileDialog.getSaveFileName(self, vtText.SAVE_DATA, '', 'CSV(*.csv)') try: - if not path.isEmpty(): + #if not path.isEmpty(): + if path: with open(unicode(path), 'wb') as f: writer = csv.writer(f) @@ -427,7 +428,7 @@ class BasicMonitor(QtWidgets.QTableWidget): #---------------------------------------------------------------------- def contextMenuEvent(self, event): """鍙抽敭鐐瑰嚮浜嬩欢""" - self.menu.popup(QtWidgets.QCursor.pos()) + self.menu.popup(QtGui.QCursor.pos()) ######################################################################## diff --git a/vnpy/trader/uiMainWindow.py b/vnpy/trader/uiMainWindow.py index 5090bf94..e7a6bf95 100644 --- a/vnpy/trader/uiMainWindow.py +++ b/vnpy/trader/uiMainWindow.py @@ -160,7 +160,7 @@ class MainWindow(QtWidgets.QMainWindow): if not displayName: displayName = gatewayName - displayName = gatewayName + actionName = vtText.CONNECT + displayName menu.addAction(self.createAction(actionName, connect)) diff --git a/vnpy/trader/vtClient.py b/vnpy/trader/vtClient.py index 1e801309..65672293 100644 --- a/vnpy/trader/vtClient.py +++ b/vnpy/trader/vtClient.py @@ -73,7 +73,7 @@ class ClientEngine(object): #---------------------------------------------------------------------- def sendOrder(self, orderReq, gatewayName): """瀵圭壒瀹氭帴鍙e彂鍗""" - self.client.sendOrder(orderReq, gatewayName) + return self.client.sendOrder(orderReq, gatewayName) #---------------------------------------------------------------------- def cancelOrder(self, cancelOrderReq, gatewayName): diff --git a/vnpy/trader/vtEngine.py b/vnpy/trader/vtEngine.py index 9b242791..1d39617b 100644 --- a/vnpy/trader/vtEngine.py +++ b/vnpy/trader/vtEngine.py @@ -85,7 +85,7 @@ class MainEngine(object): gateway.connect() # 鎺ュ彛杩炴帴鍚庤嚜鍔ㄦ墽琛屾暟鎹簱杩炴帴鐨勪换鍔 - self.dbConnect() + #self.dbConnect() #---------------------------------------------------------------------- def subscribe(self, subscribeReq, gatewayName):