@@ -53,8 +53,8 @@ class TqApi(object):
53
53
DEFAULT_INS_URL = "https://openmd.shinnytech.com/t/md/symbols/latest.json"
54
54
55
55
def __init__ (self , account : Union ['TqAccount' , TqSim , 'TqApi' , None ] = None , url : Optional [str ] = None ,
56
- backtest : Optional [TqBacktest ] = None , debug : Optional [str ] = None ,
57
- loop : Optional [asyncio .AbstractEventLoop ] = None , _ins_url = None , _md_url = None , _td_url = None , web_gui = False , _http_server_port = None ) -> None :
56
+ backtest : Optional [TqBacktest ] = None , web_gui : bool = False , debug : Optional [str ] = None ,
57
+ loop : Optional [asyncio .AbstractEventLoop ] = None , _ins_url = None , _md_url = None , _td_url = None ) -> None :
58
58
"""
59
59
创建天勤接口实例
60
60
@@ -87,25 +87,33 @@ def __init__(self, account: Union['TqAccount', TqSim, 'TqApi', None] = None, url
87
87
* 为了图形化界面能够接收到程序传输的数据并且刷新,在程序中,需要循环调用 api.wait_update的形式去更新和获取数据
88
88
* 推荐打开图形化界面的浏览器为Google Chrome 或 Firefox
89
89
90
- Example ::
90
+ Example1 ::
91
91
92
92
# 使用实盘帐号直连行情和交易服务器
93
93
from tqsdk import TqApi, TqAccount
94
94
api = TqApi(TqAccount("H海通期货", "022631", "123456"))
95
95
96
+ Example2::
97
+
96
98
# 使用模拟帐号直连行情服务器
97
99
from tqsdk import TqApi, TqSim
98
100
api = TqApi(TqSim()) # 不填写参数则默认为 TqSim() 模拟账号
99
101
102
+ Example3::
103
+
100
104
# 进行策略回测
101
105
from datetime import date
102
106
from tqsdk import TqApi, TqSim, TqBacktest
103
107
api = TqApi(TqSim(), backtest=TqBacktest(start_dt=date(2018, 5, 1), end_dt=date(2018, 10, 1)))
104
108
109
+ Example4::
110
+
105
111
# 开启 web_gui 功能
106
112
from tqsdk import TqApi
107
113
api = TqApi(web_gui=True)
114
+
108
115
"""
116
+
109
117
# 记录参数
110
118
if account is None :
111
119
account = TqSim ()
@@ -126,10 +134,8 @@ def __init__(self, account: Union['TqAccount', TqSim, 'TqApi', None] = None, url
126
134
if _td_url :
127
135
self ._td_url = _td_url
128
136
self ._loop = asyncio .SelectorEventLoop () if loop is None else loop # 创建一个新的 ioloop, 避免和其他框架/环境产生干扰
129
- self ._tq_web_helper = TqWebHelper (_http_server_port = _http_server_port , enabled_web_gui = web_gui )
130
137
131
138
# 初始化 logger
132
-
133
139
self ._logger = logging .getLogger ("TqApi" )
134
140
self ._logger .setLevel (logging .DEBUG )
135
141
if not self ._logger .handlers :
@@ -183,8 +189,10 @@ def __init__(self, account: Union['TqAccount', TqSim, 'TqApi', None] = None, url
183
189
self ._master ._slaves .append (self )
184
190
self ._account = self ._master ._account
185
191
self ._to_tq = self ._master ._to_tq
192
+ self ._web_gui = False # 如果是slave, _web_gui 一定是 False
186
193
return # 注: 如果是slave,则初始化到这里结束并返回,以下代码不执行
187
194
195
+ self ._web_gui = web_gui
188
196
# 初始化
189
197
if sys .platform .startswith ("win" ):
190
198
self .create_task (self ._windows_patch ()) # Windows系统下asyncio不支持KeyboardInterrupt的临时补丁
@@ -1129,11 +1137,10 @@ def _setup_connection(self):
1129
1137
self ._account ._run (self , self ._send_chan , self ._recv_chan , ws_md_send_chan , ws_md_recv_chan ,
1130
1138
ws_td_send_chan , ws_td_recv_chan ))
1131
1139
1132
- # 与web配合, 行情和交易都要 对接到 backtest 上
1133
- if self ._tq_web_helper :
1134
- web_send_chan , web_recv_chan = TqChan (self ), TqChan (self )
1135
- self .create_task (self ._tq_web_helper ._run (self , web_send_chan , web_recv_chan , self ._send_chan , self ._recv_chan ))
1136
- self ._send_chan , self ._recv_chan = web_send_chan , web_recv_chan
1140
+ # 与 web 配合, 在 tq_web_helper 内部中处理 web_gui 选项
1141
+ web_send_chan , web_recv_chan = TqChan (self ), TqChan (self )
1142
+ self .create_task (TqWebHelper ()._run (self , web_send_chan , web_recv_chan , self ._send_chan , self ._recv_chan ))
1143
+ self ._send_chan , self ._recv_chan = web_send_chan , web_recv_chan
1137
1144
1138
1145
# 抄送部分数据包到天勤
1139
1146
if tq_send_chan and tq_recv_chan :
@@ -1451,7 +1458,7 @@ def _process_chart_data_for_web(self, serial, symbol, duration, col, count, righ
1451
1458
"color" : int (data .get (".color" , [0xFFFF0000 ])[- 1 ]),
1452
1459
"width" : int (data .get (".width" , [1 ])[- 1 ]),
1453
1460
"board" : data .get (".board" , ["MAIN" ])[- 1 ]
1454
- })
1461
+ }, aid = "set_web_chart_data" )
1455
1462
elif data_type == "KSERIAL" :
1456
1463
send_data = {}
1457
1464
range_left = right - count
@@ -1468,11 +1475,11 @@ def _process_chart_data_for_web(self, serial, symbol, duration, col, count, righ
1468
1475
"range_left" : right - count ,
1469
1476
"range_right" : right - 1 ,
1470
1477
"board" : data .get (".board" , ["MAIN" ])[- 1 ]
1471
- })
1478
+ }, aid = "set_web_chart_data" )
1472
1479
1473
- def _send_series_data (self , symbol , duration , serial_id , serial_data ):
1480
+ def _send_series_data (self , symbol , duration , serial_id , serial_data , aid = "set_chart_data" ):
1474
1481
pack = {
1475
- "aid" : "set_chart_data" ,
1482
+ "aid" : aid ,
1476
1483
"symbol" : symbol ,
1477
1484
"dur_nano" : duration ,
1478
1485
"datas" : {
@@ -1551,8 +1558,7 @@ async def _connect(self, url, send_chan, recv_chan):
1551
1558
}) as client :
1552
1559
# 发送网络连接建立的通知,code = 2019112901
1553
1560
notify_id = uuid .UUID (int = TqApi .RD .getrandbits (128 )).hex
1554
- notify = {}
1555
- notify [notify_id ] = {
1561
+ notify = {
1556
1562
"type" : "MESSAGE" ,
1557
1563
"level" : "INFO" ,
1558
1564
"code" : 2019112901 ,
@@ -1561,6 +1567,8 @@ async def _connect(self, url, send_chan, recv_chan):
1561
1567
}
1562
1568
1563
1569
if not first_connect : # 如果不是第一次连接, 即为重连
1570
+ # 发送网络连接重新建立的通知,code = 2019112902
1571
+ notify ["code" ] = 2019112902
1564
1572
notify ["level" ] = "WARNING"
1565
1573
notify ["content" ] = "与 %s 的网络连接已恢复" % url
1566
1574
un_processed = True # 重连后数据未处理完
@@ -1570,10 +1578,10 @@ async def _connect(self, url, send_chan, recv_chan):
1570
1578
if url == self ._md_url : # 获取重连时需发送的所有 set_chart 指令包
1571
1579
set_chart_packs = {k : v for k , v in resend_request .items () if v .get ("aid" ) == "set_chart" }
1572
1580
1573
- # 发送网络连接建立的通知,code = 2019112901,这里区分了第一次连接和重连
1581
+ # 发送网络连接建立的通知,code = 2019112901 or 2019112902 ,这里区分了第一次连接和重连
1574
1582
await recv_chan .send ({
1575
1583
"aid" : "rtn_data" ,
1576
- "data" : [{"notify" : notify }]
1584
+ "data" : [{"notify" : { notify_id : notify } }]
1577
1585
})
1578
1586
send_task = self .create_task (
1579
1587
self ._send_handler (client , url , resend_request , send_chan , first_connect ))
@@ -1682,19 +1690,18 @@ async def _connect(self, url, send_chan, recv_chan):
1682
1690
# 希望做到的效果是遇到网络问题可以断线重连, 但是可能抛出的例外太多了(TimeoutError,socket.gaierror等), 又没有文档或工具可以理出 try 代码中所有可能遇到的例外
1683
1691
# 而这里的 except 又需要处理所有子函数及子函数的子函数等等可能抛出的例外, 因此这里只能遇到问题之后再补, 并且无法避免 false positive 和 false negative
1684
1692
except (websockets .exceptions .ConnectionClosed , OSError ):
1685
- # 发送网络连接断开的通知,code = 2019112902
1693
+ # 发送网络连接断开的通知,code = 2019112911
1686
1694
notify_id = uuid .UUID (int = TqApi .RD .getrandbits (128 )).hex
1687
- notify = {}
1688
- notify [notify_id ] = {
1695
+ notify = {
1689
1696
"type" : "MESSAGE" ,
1690
1697
"level" : "WARNING" ,
1691
- "code" : 2019112902 ,
1698
+ "code" : 2019112911 ,
1692
1699
"content" : "与 %s 的网络连接断开,请检查客户端及网络是否正常" % url ,
1693
1700
"url" : url
1694
1701
}
1695
1702
await recv_chan .send ({
1696
1703
"aid" : "rtn_data" ,
1697
- "data" : [{"notify" : notify }]
1704
+ "data" : [{"notify" : { notify_id : notify } }]
1698
1705
})
1699
1706
finally :
1700
1707
if first_connect :
0 commit comments