tushare 1.4.6__py3-none-any.whl → 1.4.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tushare/__init__.py +1 -1
- tushare/pro/data_pro.py +18 -10
- tushare/subs/model/tick.py +128 -128
- tushare/subs/tgw_subs/convert.py +20 -20
- {tushare-1.4.6.dist-info → tushare-1.4.7.dist-info}/METADATA +98 -101
- {tushare-1.4.6.dist-info → tushare-1.4.7.dist-info}/RECORD +9 -46
- {tushare-1.4.6.dist-info → tushare-1.4.7.dist-info}/WHEEL +1 -1
- {tushare-1.4.6.dist-info → tushare-1.4.7.dist-info}/top_level.txt +0 -1
- baks/__init__.py +0 -0
- baks/demo.py +0 -184
- baks/rtqc.py +0 -612
- baks/setup.py +0 -15
- baks/sss.py +0 -56
- test/__init__.py +0 -0
- test/bar_test.py +0 -23
- test/billboard_test.py +0 -35
- test/build_pyd/__init__.py +0 -8
- test/build_pyd/rtqc.py +0 -612
- test/build_pyd/setup.py +0 -15
- test/build_pyd//321/206/320/231/320/243/321/205/320/234/320/225pyd/321/205/320/241/342/225/234/321/204/342/225/227/320/264.txt +0 -1
- test/classifying_test.py +0 -50
- test/dateu_test.py +0 -19
- test/fund_test.py +0 -43
- test/indictor_test.py +0 -23
- test/macro_test.py +0 -50
- test/nav_test.py +0 -104
- test/news_test.py +0 -38
- test/pro_test.py +0 -11
- test/ref_test.py +0 -57
- test/shibor_test.py +0 -33
- test/storing_test.py +0 -61
- test/test_query.py +0 -16
- test/test_realtime.py +0 -24
- test/test_realtime_quote.py +0 -13
- test/test_sdk_event.py +0 -21
- test/test_stk_mins.py +0 -16
- test/test_stock_basic.py +0 -16
- test/test_tgw_subscribe.py +0 -28
- test/test_ts_subscribe.py +0 -22
- test/test_websocket.py +0 -52
- test/trading_test.py +0 -43
- tushare/stock/rtqc.pyd +0 -0
- tushare/subs/ht_subs/service/__init__.py +0 -0
- tushare/subs/ht_subs/service/covert.py +0 -189
- tushare/subs/ts_subs.py +0 -192
- {tushare-1.4.6.dist-info → tushare-1.4.7.dist-info}/LICENSE +0 -0
tushare/subs/ts_subs.py
DELETED
@@ -1,192 +0,0 @@
|
|
1
|
-
# -*- coding:utf-8 -*-
|
2
|
-
'''
|
3
|
-
@group:waditu
|
4
|
-
@author: DY
|
5
|
-
'''
|
6
|
-
import _thread as thread
|
7
|
-
import fnmatch
|
8
|
-
import json
|
9
|
-
|
10
|
-
import logging, sys
|
11
|
-
import re
|
12
|
-
import ssl
|
13
|
-
import threading
|
14
|
-
import time
|
15
|
-
from collections import defaultdict
|
16
|
-
from functools import wraps
|
17
|
-
from multiprocessing.context import Process
|
18
|
-
|
19
|
-
import websocket
|
20
|
-
from websocket import WebSocketConnectionClosedException
|
21
|
-
|
22
|
-
logging.basicConfig(stream=sys.stdout, level=logging.ERROR, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
23
|
-
import logging
|
24
|
-
|
25
|
-
logger = logging.getLogger(__name__)
|
26
|
-
|
27
|
-
|
28
|
-
class Subs(object):
|
29
|
-
|
30
|
-
def __init__(self, token='', callback_mode='multi-thread', debug=False):
|
31
|
-
self.url = 'wss://ws.tushare.pro/listening'
|
32
|
-
self.token = token
|
33
|
-
self.debug = debug
|
34
|
-
|
35
|
-
self.callback_mode = callback_mode
|
36
|
-
self.topics = defaultdict(lambda: list())
|
37
|
-
self.callback_funcs = defaultdict(lambda: list())
|
38
|
-
|
39
|
-
self.websocket = None
|
40
|
-
|
41
|
-
def threading_keepalive_ping(self):
|
42
|
-
def ping():
|
43
|
-
time.sleep(30)
|
44
|
-
req_data = {
|
45
|
-
"action": "ping"
|
46
|
-
}
|
47
|
-
self.websocket.send(json.dumps(req_data))
|
48
|
-
logger.debug('send ping message')
|
49
|
-
threading.Thread(target=ping).start()
|
50
|
-
|
51
|
-
def on_open(self, *args, **kwargs):
|
52
|
-
req_data = {
|
53
|
-
"action": "listening",
|
54
|
-
"token": self.token,
|
55
|
-
"data": self.topics
|
56
|
-
}
|
57
|
-
self.websocket.send(json.dumps(req_data))
|
58
|
-
logger.info('application starting...')
|
59
|
-
self.threading_keepalive_ping()
|
60
|
-
|
61
|
-
def on_message(self, message, *args, **kwargs):
|
62
|
-
logger.debug(message)
|
63
|
-
if isinstance(message, (str, bytes, bytearray)):
|
64
|
-
resp_data = json.loads(message)
|
65
|
-
if not resp_data.get('status'):
|
66
|
-
logger.error(resp_data.get('message'))
|
67
|
-
return
|
68
|
-
else:
|
69
|
-
logger.info(message)
|
70
|
-
return
|
71
|
-
data = resp_data.get('data', {})
|
72
|
-
if not data or not isinstance(data, dict):
|
73
|
-
return
|
74
|
-
|
75
|
-
topic = data.get('topic')
|
76
|
-
code = data.get('code')
|
77
|
-
record = data.get('record')
|
78
|
-
if not topic or not code or not record:
|
79
|
-
logger.warning('get invalid response-data(%s)' % resp_data)
|
80
|
-
return
|
81
|
-
|
82
|
-
self._do_callback_function(topic, code, record)
|
83
|
-
|
84
|
-
def on_error(self, error, *args, **kwargs):
|
85
|
-
if self.debug:
|
86
|
-
logging.error(str(error), exc_info=True)
|
87
|
-
|
88
|
-
def on_close(self, *args, **kwargs):
|
89
|
-
logger.error('close')
|
90
|
-
_type, _value, _traceback = sys.exc_info()
|
91
|
-
if _type in [WebSocketConnectionClosedException, ConnectionRefusedError]:
|
92
|
-
time.sleep(1)
|
93
|
-
self.run()
|
94
|
-
|
95
|
-
def run(self):
|
96
|
-
if not self.topics:
|
97
|
-
logger.error('no data.')
|
98
|
-
return
|
99
|
-
|
100
|
-
self.websocket = websocket.WebSocketApp(
|
101
|
-
self.url,
|
102
|
-
on_message=self.on_message,
|
103
|
-
on_error=self.on_error,
|
104
|
-
on_close=self.on_close,
|
105
|
-
on_open=self.on_open
|
106
|
-
)
|
107
|
-
if self.url.startswith('wss:'):
|
108
|
-
self.websocket.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
|
109
|
-
else:
|
110
|
-
self.websocket.run_forever()
|
111
|
-
|
112
|
-
def register(self, topic, codes):
|
113
|
-
codes = set(codes)
|
114
|
-
|
115
|
-
def decorator(func):
|
116
|
-
func.codes = set()
|
117
|
-
func.pcodes = set()
|
118
|
-
for code in codes:
|
119
|
-
if not re.match(r'[\d\w\.\*]+', code):
|
120
|
-
logger.error('error code')
|
121
|
-
exit(1)
|
122
|
-
|
123
|
-
if '*' in code:
|
124
|
-
for code1 in func.pcodes:
|
125
|
-
if fnmatch.fnmatch(code1, code) or fnmatch.fnmatch(code, code1):
|
126
|
-
logger.error('duplicate code')
|
127
|
-
exit(1)
|
128
|
-
for code1 in func.codes:
|
129
|
-
if fnmatch.fnmatch(code1, code):
|
130
|
-
logger.error('duplicate code')
|
131
|
-
exit(1)
|
132
|
-
func.pcodes.add(code)
|
133
|
-
else:
|
134
|
-
for code1 in func.pcodes:
|
135
|
-
if fnmatch.fnmatch(code, code1):
|
136
|
-
logger.error('duplicate code')
|
137
|
-
exit(1)
|
138
|
-
func.codes.add(code)
|
139
|
-
|
140
|
-
self.topics[topic] += codes
|
141
|
-
self.callback_funcs[topic].append(func)
|
142
|
-
|
143
|
-
@wraps(func)
|
144
|
-
def inner(*args, **kwargs):
|
145
|
-
""" should receive a message-value parameter """
|
146
|
-
return func(*args, **kwargs)
|
147
|
-
|
148
|
-
return inner
|
149
|
-
|
150
|
-
return decorator
|
151
|
-
|
152
|
-
def _do_callback_function(self, topic, code, value):
|
153
|
-
for func in self.callback_funcs[topic]:
|
154
|
-
checked = False
|
155
|
-
if code in func.codes:
|
156
|
-
checked = True
|
157
|
-
else:
|
158
|
-
for pcode in func.pcodes:
|
159
|
-
if fnmatch.fnmatch(code, pcode):
|
160
|
-
checked = True
|
161
|
-
break
|
162
|
-
|
163
|
-
if not checked:
|
164
|
-
continue
|
165
|
-
|
166
|
-
if self.callback_mode == 'single-thread':
|
167
|
-
func(value)
|
168
|
-
elif self.callback_mode == 'multi-thread':
|
169
|
-
thread.start_new_thread(func, (value,))
|
170
|
-
elif self.callback_mode == 'multi-process':
|
171
|
-
p = Process(target=func, args=(value,))
|
172
|
-
p.start()
|
173
|
-
|
174
|
-
|
175
|
-
def test():
|
176
|
-
app = Subs(token='')
|
177
|
-
|
178
|
-
# code 可以包含 * (通配符)
|
179
|
-
@app.register(topic='HQ_STK_TICK', codes=["000001.SZ"])
|
180
|
-
def print_message(record):
|
181
|
-
"""
|
182
|
-
订阅主题topic,并指定codes列表,在接收到topic的推送消息时,符合code条件,就会执行回调
|
183
|
-
:param record:
|
184
|
-
:return:
|
185
|
-
"""
|
186
|
-
print('用户定义业务代码输出 print_message(%s)' % str(record))
|
187
|
-
|
188
|
-
app.run()
|
189
|
-
|
190
|
-
|
191
|
-
if __name__ == '__main__':
|
192
|
-
test()
|
File without changes
|