Skip to content

Commit 7db97fb

Browse files
committed
升级ctp api至v6.6.9
0 parents  commit 7db97fb

14 files changed

+619
-0
lines changed

README.md

+236
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# 简介
2+
3+
AlgoPlus是上期技术CTP API的Python封装。
4+
5+
# 官网
6+
7+
<http://algo.plus>
8+
9+
# 安装
10+
11+
首先配置Python环境,然后安装:```pip install AlgoPlus```。 或者下载AlgoPlus包文件,解压后放在项目目录中。
12+
13+
# 版本对应关系
14+
15+
| AlgoPlus版本号 | CTP API版本 | Python版本 |
16+
| :----: | :----: | :----: |
17+
| 3.0 | v6.6.9_20220914 9:57:19.2466 | 3.7、3.8、3.9 |
18+
19+
# 入门视频教程
20+
21+
* [配置Python环境与安装AlgoPlus](https://www.bilibili.com/video/BV1p54y1m77t)
22+
* [CTP API的工作原理](https://www.bilibili.com/video/BV17v411C73r)
23+
24+
# 应用范例
25+
26+
这里就给大家介绍介个基于AlgoPlus实现的应用范例,供大家参考。
27+
28+
## 1、获取实时行情
29+
30+
发布实时行情是交易所实现价值发现职能的重要工作,而且是交易决策的重要依据。
31+
32+
CTP通过一个独立的MdApi接口发布行情。MdApi功能比较单一,只需要在与服务器建立连接后订阅相关合约,就可以自动接收到到实时行情。
33+
34+
AlgoPlus对MdApi进行了封装,我们只需要将账户信息及合约名称作为参数传进去,就可以接收到字典形式的实时行情数据。
35+
36+
演示这个功能的例子是`examples/get_tick.py`,运行之后可以看到如下的输出结果:
37+
38+
![](./img/get_tick.png)
39+
40+
从输出日志可以看到,AlgoPlus第一步连接服务器,第二步登陆账户,第三步订阅行情,最后就是接收行情数据。
41+
42+
### 1.1 期货合约规范:
43+
44+
* 上期/能源所:小写+4个数字
45+
* 大商所:小写+4个数字
46+
* 中金所:大写+4个数字
47+
* 郑商所:大写+3个数字
48+
49+
### 1.2 期权合约规范:
50+
51+
* 上期所/能源所:小写+4个数字+C(或者P)+行权价
52+
* 郑商所:大写+3个数字+C(或者P)+行权价
53+
* 中金所:大写+4个数字+-C-(或者-P-)+行权价
54+
* 大商所:小写+4个数字+-C-(或者-P-)+行权价
55+
56+
## 2、将行情存为CSV文件
57+
58+
因为MdApi只推送实时行情,所以存储数据是量化交易至关重要的一项工作。虽然有多种数据库可以选择,但是简单起见,`examples/tick_to_csv.py`使用了csv文件。运行这个例子后,实时行情数据自动被存入`MarketData`文件夹下的csv文件中。
59+
60+
## 3、合成K线
61+
62+
MdApi推送的实时行情是固定时间间隔(一般间隔是500ms)的快照,也就是我们常说Tick数据。
63+
64+
而交易决策的逻辑基础往往是K线数据,所谓的K线就是用固定时间间隔内开盘价、最高价、最低价、收盘价代理此间所有Tick。
65+
66+
K线自诞生以来就被二级市场所广泛使用。合理的选择K线周期,可以帮助我们抓住主线趋势,避免陷于短期波动。
67+
68+
`examples/get_bar.py`为大家演示了如何将Tick数据合成1分钟K线数据,字段内容如下:
69+
70+
```python
71+
{
72+
'InstrumentID': b'', # 合约代码
73+
'UpdateTime': b'00:46:00', # K线开始时间
74+
'LastPrice': 3454.0, # 收盘价
75+
'HighPrice': 3454.0, # 最高价
76+
'LowPrice': 3454.0, # 最低价
77+
'OpenPrice': 3454.0, # 开盘价
78+
'BarVolume': 7, # 成交量
79+
'BarTurnover': 24178.0, # 成交额
80+
'BarSettlement': 3454.0, # K线成交均价
81+
'BVolume': 0, # 主动买量
82+
'SVolume': 7, # 主动卖量
83+
'FVolume': 0, # 非主动买卖量
84+
'DayVolume': 1381157, # 全天成交量
85+
'DayTurnover': 4771897578.0, # 全天成交额
86+
'DaySettlement': 3455.000103536383, # 全天成交均价
87+
'OpenInterest': 1577415.0, # 持仓量
88+
'TradingDay': b'20200508' # 交易日
89+
}
90+
```
91+
92+
除了1分钟K线之外,大家也可以参考如下条件合成其他周期K线:
93+
94+
```python
95+
# 1分钟K线条件
96+
is_new_1minute = (pDepthMarketData['UpdateTime'][:-2] != last_update_time[:-2]) and pDepthMarketData['UpdateTime'] != b'21:00:00'
97+
# 5分钟K线条件
98+
is_new_5minute = is_new_1minute and int(pDepthMarketData['UpdateTime'][-4]) % 5 == 0
99+
# 10分钟K线条件
100+
is_new_10minute = is_new_1minute and pDepthMarketData['UpdateTime'][-4] == b"0"
101+
# 15分钟K线条件
102+
is_new_10minute = is_new_1minute and int(pDepthMarketData['UpdateTime'][-5:-3]) % 15 == 0
103+
# 30分钟K线条件
104+
is_new_30minute = is_new_1minute and int(pDepthMarketData['UpdateTime'][-5:-3]) % 30 == 0
105+
# 60分钟K线条件
106+
is_new_hour = is_new_1minute and int(pDepthMarketData['UpdateTime'][-5:-3]) % 60 == 0
107+
```
108+
109+
运行结果如下:
110+
111+
![](./img/get_bar.png)
112+
113+
## 4、看穿式认证
114+
115+
由于监管要求,接入期货公司的交易程序必须经过看穿式认证。简单的说,就是用交易程序在期货公司提供的仿真环境中完成指定的交易、查询任务就可以了。完成后,期货公司会提供用于生产环境的授权码。所谓的直连模式和中继模式,只要是自己用的都属于直连模式。
116+
117+
`examples/authenticate.py`这个例子虽然是为了方便大家做认证,但是其中的基础操作对熟悉交易接口是很有帮助的,例如:
118+
119+
```python
120+
# 买开仓
121+
self.buy_open(...)
122+
# 卖平仓
123+
self.sell_close(...)
124+
# 卖开仓
125+
self.sell_open(...)
126+
# 买平仓
127+
self.buy_close(...)
128+
# 撤单
129+
self.req_order_action(...)
130+
# 查询订单
131+
self.req_qry_order(...)
132+
# 查询成交
133+
self.req_qry_trade()
134+
# 查询持仓
135+
self.req_qry_investor_position()
136+
# 查询资金
137+
self.req_qry_trading_account()
138+
```
139+
140+
需要注意的是交易接口的查询功能是有流控限制的,每秒限制只能查询1次。买卖报单以及撤单不受流控限制。
141+
142+
![](./img/authenticate.png)
143+
144+
## 5、滚动交易
145+
146+
延时是很多量化交易会关注的问题,但是这又是一个很复杂的问题。
147+
148+
为了简单起见,我们设计了`examples/rolling_trade.py`这个滚动交易策略:收到前次报单成交回报时发起新的交易请求。完成300次交易之后,我们统计一下1秒内的交易次数,就可以计算出交易环境的延时,包括网络、交易程序、期货公司系统、交易所系统总的用时。
149+
150+
我使用simnow的7*24测试环境在阿里云服务器上运行该例子,1s内完成110笔成交。但是,需要说明的是,这个数据并不真实,因为7*24测试环境负载非常低。建议大家在正常的交易时间使用simnow仿真环境测试,可以获得相对更有价值的数据。
151+
152+
![](./img/rolling_trade.png)
153+
154+
## 6、盈损管理
155+
156+
`examples/risk_manager.py`是一个相对复杂的例子,启动后可以监控账户的所有的成交,包括从快期或者其他终端软件报的单,当达到止盈止损条件时,就会自动平仓。启动前需要设置好止盈止损参数:
157+
158+
```python
159+
pl_parameter = {
160+
'StrategyID': 9,
161+
# 盈损参数,'0'代表止盈, '1'代表止损,绝对价差
162+
'ProfitLossParameter': {
163+
b'rb2010': {'0': [2], '1': [2]},
164+
b'ni2007': {'0': [20], '1': [20]},
165+
},
166+
}
167+
```
168+
169+
简单起见,这里只实现了固定止盈止损,大家可以参考实现更复杂、有效的止损策略。这篇文章为大家提供一些关于止盈止损的思路:[http://algo.plus/researches/0002.html](http://algo.plus/researches/0002.html)
170+
171+
另外,我们也可以将这个策略部署到服务器上,成为属于自己的云端条件单系统。
172+
173+
因为目的是为了让大家快速熟悉AlgoPlus,所以很多问题都浅尝辄止,以后有机会我们再进行深入探讨,也欢迎大家在后台留言讨论。
174+
175+
## 7、订阅全市场行情并落地为csv文件
176+
177+
期货合约都是有期限的,订阅全市场行情需要先使用`AlgoPlus.CTP.TraderApi.run_query_instrument`查询当前挂牌交易的所有合约,然后再交给`run_mdrecorder`订阅并存储。`subscribe_all.py`演示了具体如何使用。
178+
179+
# 仿真交易测试
180+
181+
## 1、`SimNow同步仿真环境`
182+
183+
```
184+
BrokerID = "9999"
185+
TraderFrontAddress = "tcp://180.168.146.187:10201"
186+
MdFrontAddress = "tcp://180.168.146.187:10211"
187+
AppID = "simnow_client_test"
188+
AuthCode = "0000000000000000"
189+
```
190+
191+
## 2、`SimNow同步仿真环境`
192+
193+
```
194+
BrokerID = "9999"
195+
TraderFrontAddress = tcp://180.168.146.187:10202
196+
MdFrontAddress = tcp://180.168.146.187:10212
197+
AppID = "simnow_client_test"
198+
AuthCode = "0000000000000000"
199+
```
200+
201+
## 3、`SimNow同步仿真环境`
202+
203+
```
204+
BrokerID = "9999"
205+
TraderFrontAddress = "tcp://218.202.237.33:10203"
206+
MdFrontAddress = "tcp://218.202.237.33:10213"
207+
AppID = "simnow_client_test"
208+
AuthCode = "0000000000000000"
209+
```
210+
211+
## 4、`SimNow7*24仿真环境`
212+
213+
```
214+
BrokerID = "9999"
215+
TraderFrontAddress = "tcp://180.168.146.187:10130"
216+
MdFrontAddress = "tcp://180.168.146.187:10131"
217+
AppID = "simnow_client_test"
218+
AuthCode = "0000000000000000"
219+
```
220+
221+
# 地址
222+
223+
1. 码云:<https://gitee.com/AlgoPlus/>
224+
2. GitHub:<https://github.com/keyalgo/AlgoPlus>
225+
226+
### 自媒体账号
227+
228+
* bilibili账号:**AlgoPlus**
229+
230+
* 微信公众号:**AlgoPlus**
231+
232+
![](./img/微信公众号AlgoPlus.jpg)
233+
234+
* QQ群:**866469866**
235+
236+
![](./img/QQ群866469866.png)

examples/authenticate.py

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# 微信公众号:AlgoPlus
4+
# 官网:http://algo.plus
5+
# 项目地址:https://gitee.com/AlgoPlus/
6+
7+
from multiprocessing import Queue
8+
from AlgoPlus.CTP.AuthenticateHelper import run_authenticate
9+
from AlgoPlus.CTP.FutureAccount import get_simulate_account
10+
11+
if __name__ == '__main__':
12+
# 账户
13+
account = get_simulate_account(
14+
investor_id='', # 账户
15+
password='', # 密码
16+
server_name='', # 电信1、电信2、移动、TEST、N视界
17+
)
18+
19+
# future_account = FutureAccount(
20+
# broker_id='', # 期货公司BrokerID
21+
# server_dict={'TDServer': "ip:port", 'MDServer': 'ip:port'}, # TDServer为交易服务器,MDServer为行情服务器。服务器地址格式为"ip:port。"
22+
# reserve_server_dict={}, # 备用服务器地址
23+
# investor_id='', # 账户
24+
# password='', # 密码
25+
# app_id='simnow_client_test', # 认证使用AppID
26+
# auth_code='0000000000000000', # 认证使用授权码
27+
# subscribe_list=[], # 订阅合约列表
28+
# md_flow_path='./log', # MdApi流文件存储地址,默认MD_LOCATION
29+
# td_flow_path='./log', # TraderApi流文件存储地址,默认TD_LOCATION
30+
# )
31+
32+
# 参数
33+
parameter_dict = {
34+
'ExchangeID': b'SHFE', # 交易所
35+
'InstrumentID': b'rb2310', # 合约代码
36+
'UpperLimitPrice': 4380, # 涨停板
37+
'LowerLimitPrice': 3511, # 跌停板
38+
'Volume': 1, # 报单手数
39+
}
40+
41+
# 共享队列
42+
share_queue = Queue(maxsize=100)
43+
share_queue.put(parameter_dict)
44+
45+
#
46+
run_authenticate(account, share_queue)

examples/get_bar.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# 微信公众号:AlgoPlus
4+
# 官网:http://algo.plus
5+
# 项目地址:https://gitee.com/AlgoPlus/
6+
7+
from multiprocessing import Process, Queue
8+
from AlgoPlus.CTP.MdApi import run_bar_engine
9+
from AlgoPlus.CTP.FutureAccount import get_simulate_account
10+
11+
12+
def print_bar(md_queue):
13+
while True:
14+
if not md_queue.empty():
15+
print(md_queue.get(block=False))
16+
17+
18+
if __name__ == '__main__':
19+
# 账户
20+
future_account = get_simulate_account(
21+
investor_id='', # 账户
22+
password='', # 密码
23+
server_name='', # 电信1、电信2、移动、TEST、N视界
24+
subscribe_list=[b'IC2304'], # 合约列表
25+
)
26+
27+
# future_account = FutureAccount(
28+
# broker_id='', # 期货公司BrokerID
29+
# server_dict={'TDServer': "ip:port", 'MDServer': 'ip:port'}, # TDServer为交易服务器,MDServer为行情服务器。服务器地址格式为"ip:port。"
30+
# reserve_server_dict={}, # 备用服务器地址
31+
# investor_id='', # 账户
32+
# password='', # 密码
33+
# app_id='simnow_client_test', # 认证使用AppID
34+
# auth_code='0000000000000000', # 认证使用授权码
35+
# subscribe_list=[], # 订阅合约列表
36+
# md_flow_path='./log', # MdApi流文件存储地址,默认MD_LOCATION
37+
# td_flow_path='./log', # TraderApi流文件存储地址,默认TD_LOCATION
38+
# )
39+
40+
# 共享队列
41+
share_queue = Queue(maxsize=100)
42+
43+
# 行情进程
44+
md_process = Process(target=run_bar_engine, args=(future_account, [share_queue]))
45+
# 交易进程
46+
print_process = Process(target=print_bar, args=(share_queue,))
47+
48+
md_process.start()
49+
print_process.start()
50+
51+
md_process.join()
52+
print_process.join()

examples/get_tick.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# -*- coding: utf-8 -*-
2+
3+
# 微信公众号:AlgoPlus
4+
# 官网:http://algo.plus
5+
# 项目地址:https://gitee.com/AlgoPlus/
6+
7+
from multiprocessing import Process, Queue
8+
from AlgoPlus.CTP.MdApi import run_tick_engine
9+
from AlgoPlus.CTP.FutureAccount import get_simulate_account
10+
11+
12+
def print_tick(md_queue):
13+
while True:
14+
if not md_queue.empty():
15+
print(md_queue.get(block=False))
16+
17+
18+
if __name__ == '__main__':
19+
future_account = get_simulate_account(
20+
investor_id='', # 账户
21+
password='', # 密码
22+
server_name='', # 电信1、电信2、移动、TEST、N视界
23+
subscribe_list=[b'IC2304'], # 合约列表
24+
)
25+
26+
# future_account = FutureAccount(
27+
# broker_id='', # 期货公司BrokerID
28+
# server_dict={'TDServer': "ip:port", 'MDServer': 'ip:port'}, # TDServer为交易服务器,MDServer为行情服务器。服务器地址格式为"ip:port。"
29+
# reserve_server_dict={}, # 备用服务器地址
30+
# investor_id='', # 账户
31+
# password='', # 密码
32+
# app_id='simnow_client_test', # 认证使用AppID
33+
# auth_code='0000000000000000', # 认证使用授权码
34+
# subscribe_list=[], # 订阅合约列表
35+
# md_flow_path='./log', # MdApi流文件存储地址,默认MD_LOCATION
36+
# td_flow_path='./log', # TraderApi流文件存储地址,默认TD_LOCATION
37+
# )
38+
39+
# 共享队列
40+
share_queue = Queue(maxsize=100)
41+
42+
# 行情进程
43+
md_process = Process(target=run_tick_engine, args=(future_account, [share_queue]))
44+
# 交易进程
45+
print_process = Process(target=print_tick, args=(share_queue,))
46+
47+
md_process.start()
48+
print_process.start()
49+
50+
md_process.join()
51+
print_process.join()

0 commit comments

Comments
 (0)