• vnpy_ctp源码下载后转变为python可用的处理过程


    目录

    写在前面 

    下载源码并解压

    创建python项目

    环境

    过程

    编译vnpy_ctp源码

    验证可用性


    写在前面 

    window系统中必须安装有Visual Studio ,后面源码安装时需要进行C++编译

    下载源码并解压

    GitHub - vnpy/vnpy_ctp: VeighNa框架的CTP交易接口

    下载zip压缩包

    解压

    要在python中能执行,要有.pyd文件,解压后的文件夹内没有.pyd文件

    创建python项目

    新建一个python项目,项目在一个新的虚拟环境中执行。

    环境

    操作系统:window10 64位

    开发工具:pycharm

    python版本:python3.8.10

    过程

    编译vnpy_ctp源码

    打开项目下方的terminal面板

    cd 到解压后setup.py 所在文件夹  

    执行 python setup.py build 

    大概2到3分钟,编译完毕,在setup.py所在文件夹下多出一个build文件夹

    在build下找到与操作系统和python版本对应的文件夹,以本文为例,操作系统是64位,那文件夹名称中就会有amd64,python版本3.8,文件夹名称中就会包含3.8,所以本文的文件夹名为lib.win-amd64-3.8

    我们需要的是 build>lib.win-amd64-3.8>vnpy_ctp文件夹下的api文件夹,我们把api文件夹复制到项目目录下

    验证可用性

    创建Md调用的类和Td调用的类

    1. import datetime,sys,os,time,pytz
    2. from api import (
    3. TdApi,
    4. MdApi
    5. )
    6. class CtpMdApi(MdApi):
    7. def __init__(self)->None:
    8. super().__init__()
    9. self.reqid:int = 0
    10. self.connect_status: bool = False
    11. self.login_status: bool = False
    12. self.subscribed: set = set()
    13. self.userid: str = ""
    14. self.password: str = ""
    15. self.brokerid: str = ""
    16. self.current_date: str = datetime.date.today().strftime('%Y%m%d')
    17. pass
    18. def connect(self, address: str, userid: str, password: str, brokerid: str)->None:
    19. self.userid = userid
    20. self.password = password
    21. self.brokerid = brokerid
    22. if not self.connect_status:
    23. con_body_path = CTP_MD_CON_DIR
    24. con_body_path = con_body_path.replace('/','\\')
    25. self.createFtdcMdApi(con_body_path)
    26. self.registerFront(address)
    27. self.init()
    28. self.connect_status = True
    29. pass
    30. pass
    31. def login(self)->None:
    32. ctp_req: dict = {
    33. 'UserID':self.userid,
    34. 'Password':self.password,
    35. 'BrokerID':self.brokerid
    36. }
    37. self.reqid += 1
    38. self.reqUserLogin(ctp_req,self.reqid)
    39. pass
    40. def subscribe(self,req:dict):
    41. if self.login_status:
    42. self.subscribeMarketData(req['symbol'])
    43. self.subscribed.add(req['symbol'])
    44. pass
    45. def close(self)->None:
    46. if self.connect_status:
    47. self.exit()
    48. pass
    49. def update_date(self)->None:
    50. self.current_date = datetime.date.today().strftime('%Y%m%d')
    51. pass
    52. def onFrontConnected(self)->None:
    53. self.login()
    54. pass
    55. def onFrontDisconnected(self,reason:int)->None:
    56. self.login_status = False
    57. pass
    58. def onRspUserLogin(self,data:dict,error:dict,reqid:int,last:bool)->None:
    59. if not error['ErrorID']:
    60. self.login_status = True
    61. for symbol in self.subscribed:
    62. self.subscribeMarketData(symbol)
    63. pass
    64. else:
    65. print(f"行情服务器登录失败。{error['ErrorID']}.{error['ErrorMsg']}")
    66. pass
    67. def onRspError(self, error: dict, reqid: int, last: bool)->None:
    68. print('行情接口报错。', error['ErrorID'], error['ErrorMsg'])
    69. pass
    70. def onRspSubMarketData(self, data: dict, error: dict, reqid: int, last: bool):
    71. if not error or not error['ErrorID']:
    72. return
    73. print('行情订阅失败。',error['ErrorID'],error['ErrorMsg'])
    74. pass
    75. def onRtnDepthMarketData(self,data:dict)->None:
    76. if not data['UpdateTime']:
    77. return
    78. print('tick返回',data['InstrumentID'],data['LastPrice'])
    79. pass
    80. pass
    81. class CtpTdApi(TdApi):
    82. def __init__(self)->None:
    83. super().__init__()
    84. self.reqid: int = 0
    85. self.order_ref: int = 0
    86. self.connect_status: bool = False
    87. self.login_status: bool = False
    88. self.auth_status: bool = False
    89. self.login_failed: bool = False
    90. self.auth_failed: bool = False
    91. self.contract_inited: bool = False
    92. self.userid: str = ""
    93. self.password: str = ""
    94. self.brokerid: str = ""
    95. self.auth_code: str = ""
    96. self.appid: str = ""
    97. self.frontid: int = 0
    98. self.sessionid: int = 0
    99. pass
    100. def connect(self,address:str,userid:str,password:str,brokerid:str,auth_code:str,appid:str)->None:
    101. self.userid = userid
    102. self.password = password
    103. self.brokerid = brokerid
    104. self.auth_code = auth_code
    105. self.appid = appid
    106. if not self.connect_status:
    107. con_body_path = CTP_TD_CON_DIR + self.userid + os.path.sep
    108. if not os.path.exists(con_body_path):
    109. os.mkdir(con_body_path)
    110. con_body_path = con_body_path.replace('/','\\')
    111. self.createFtdcTraderApi(con_body_path)
    112. self.subscribePrivateTopic(0)
    113. self.subscribePublicTopic(0)
    114. self.registerFront(address)
    115. self.init()
    116. self.connect_status = True
    117. pass
    118. else:
    119. self.authenticate()
    120. pass
    121. def authenticate(self)->None:
    122. if self.auth_failed:
    123. return
    124. ctp_req: dict = {
    125. "UserID": self.userid,
    126. "BrokerID": self.brokerid,
    127. "AuthCode": self.auth_code,
    128. "AppID": self.appid
    129. }
    130. self.reqid += 1
    131. self.reqAuthenticate(ctp_req, self.reqid)
    132. pass
    133. def login(self)->None:
    134. if self.login_failed:
    135. return
    136. ctp_req: dict = {
    137. "UserID": self.userid,
    138. "Password": self.password,
    139. "BrokerID": self.brokerid,
    140. "AppID": self.appid
    141. }
    142. self.reqid += 1
    143. self.reqUserLogin(ctp_req, self.reqid)
    144. pass
    145. def close(self)->None:
    146. if self.connect_status:
    147. self.exit()
    148. pass
    149. def onFrontConnected(self)->None:
    150. if self.auth_code:
    151. self.authenticate()
    152. else:
    153. self.login()
    154. pass
    155. def onFrontDisconnected(self,reason:int)->None:
    156. self.login_status = False
    157. pass
    158. def onRspAuthenticate(self, data: dict, error: dict, reqid: int, last: bool)->None:
    159. if not error['ErrorID']:
    160. self.auth_status = True
    161. self.login()
    162. else:
    163. self.auth_failed = True
    164. print('交易服务器验证失败。',error['ErrorID'],error['ErrorMsg'])
    165. pass
    166. def onRspUserLogin(self,data: dict, error: dict, reqid: int, last: bool)->None:
    167. if not error["ErrorID"]:
    168. self.frontid = data["FrontID"]
    169. self.sessionid = data["SessionID"]
    170. self.login_status = True
    171. # 自动确认结算单
    172. ctp_req: dict = {
    173. "BrokerID": self.brokerid,
    174. "InvestorID": self.userid
    175. }
    176. self.reqid += 1
    177. self.reqSettlementInfoConfirm(ctp_req, self.reqid)
    178. else:
    179. self.login_failed = True
    180. print("交易服务器登录失败", error['ErrorID'], error['ErrorMsg'])
    181. pass
    182. def onRspSettlementInfoConfirm(self,data: dict, error: dict, reqid: int, last: bool)->None:
    183. while True:
    184. self.reqid += 1
    185. n: int = self.reqQryInstrument({}, self.reqid)
    186. if not n:
    187. break
    188. else:
    189. time.sleep(1)
    190. pass
    191. def onRspQryInstrument(self, data: dict, error: dict, reqid: int, last: bool) -> None:
    192. print(data['ProductClass'],data['InstrumentID'],data['ProductID'],reqid,last)
    193. if last:
    194. self.contract_inited = True
    195. print('合约信息查询完毕')
    196. pass
    197. pass

    执行代码

    1. if __name__ == '__main__':
    2. investorid = ""
    3. brokerid=""
    4. password= ""
    5. appid= ""
    6. auth_code= "0000000000000000"
    7. md_ip= "180.168.146.187:10211"
    8. trader_ip= "180.168.146.187:10201"
    9. temp_api = CtpTdApi()
    10. address = f"tcp://{trader_ip}"
    11. temp_api.connect(address,investorid,password,brokerid,auth_code,appid)
    12. import keyboard
    13. keyboard.wait('esc')
    14. sys.exit()
    15. pass

    能登录td服务器,并正常查询合约,可用 

  • 相关阅读:
    vue的模板属性和渲染方法配置
    数据结构与算法之字典: Leetcode 349. 两个数组的交集 (Typescript版)
    面试:你印象最深的BUG,举个例子
    【3D人脸】MediaPipe Face Mesh 调研
    【面试题】2022前端面试真题
    Hadoop2——Hadoop程序实现
    Varchar(10)和Varchar(100)的差别
    常见的spark mllib分类算法详解
    组合总和(Lc39)——排序+剪枝+回溯
    java计算机毕业设计springboot+vue城市公园信息管理系统(源码+系统+mysql数据库+Lw文档)
  • 原文地址:https://blog.csdn.net/m0_37967652/article/details/134326622