insight-proxy-client 0.0.1__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.
@@ -0,0 +1,4 @@
1
+ """No vendor SDK is imported on the client side."""
2
+ from .client import InsightClient, BridgeError
3
+
4
+ __all__ = ["InsightClient", "BridgeError"]
@@ -0,0 +1,183 @@
1
+ """Thread-safe request/response multiplexing with a bounded event queue."""
2
+ import itertools
3
+ import queue
4
+ import socket
5
+ import ssl
6
+ import threading
7
+
8
+ from .protocol import frame_size, pack, unpack, restore_dates
9
+
10
+
11
+ class BridgeError(RuntimeError):
12
+ def __init__(self, code, message):
13
+ self.code = code
14
+ super().__init__(f"{code}: {message}")
15
+
16
+
17
+ class InsightClient:
18
+ def __init__(self, host="127.0.0.1", port=8765, *, token="", timeout=30,
19
+ event_queue_size=10000, ssl_context=None):
20
+ self.host, self.port = host, port
21
+ self.token, self.timeout = token, timeout
22
+ self.ssl_context = ssl_context
23
+ self._sock = None
24
+ self._reader = None
25
+ self._send_lock = threading.Lock()
26
+ self._lock = threading.Lock()
27
+ self._ids = itertools.count(1)
28
+ self._pending = {}
29
+ self._events = queue.Queue(maxsize=event_queue_size)
30
+ self._failure = None
31
+
32
+ def connect(self):
33
+ if self._sock is not None:
34
+ raise RuntimeError("Already connected; create a new client for reconnect")
35
+ sock = socket.create_connection((self.host, self.port), self.timeout)
36
+ try:
37
+ if self.ssl_context:
38
+ sock = self.ssl_context.wrap_socket(sock, server_hostname=self.host)
39
+ sock.settimeout(None)
40
+ sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
41
+ self._sock = sock
42
+ self._reader = threading.Thread(target=self._read_loop, daemon=True)
43
+ self._reader.start()
44
+ self.request("hello", {"version": 1, "token": self.token})
45
+ return self
46
+ except BaseException:
47
+ sock.close()
48
+ self.close()
49
+ raise
50
+
51
+ def _exact(self, size):
52
+ chunks = bytearray()
53
+ while len(chunks) < size:
54
+ chunk = self._sock.recv(size - len(chunks))
55
+ if not chunk:
56
+ raise ConnectionError("Bridge disconnected; reconnect and resubscribe")
57
+ chunks.extend(chunk)
58
+ return bytes(chunks)
59
+
60
+ def _fail(self, error):
61
+ with self._lock:
62
+ if self._failure is None:
63
+ self._failure = error
64
+ pending, self._pending = self._pending, {}
65
+ for waiter in pending.values():
66
+ waiter.put(self._failure)
67
+ if self._sock:
68
+ try:
69
+ self._sock.shutdown(socket.SHUT_RDWR)
70
+ except OSError:
71
+ pass
72
+ self._sock.close()
73
+
74
+ def _read_loop(self):
75
+ try:
76
+ while True:
77
+ message = restore_dates(unpack(self._exact(frame_size(self._exact(4)))))
78
+ if message.get("type") == "response":
79
+ with self._lock:
80
+ waiter = self._pending.pop(message.get("id"), None)
81
+ if waiter:
82
+ waiter.put(message)
83
+ elif message.get("type") == "event":
84
+ try:
85
+ self._events.put_nowait(message)
86
+ except queue.Full:
87
+ raise BridgeError("slow_consumer", "Client event queue full; connection closed to signal a data gap")
88
+ else:
89
+ raise ValueError("Unknown server message")
90
+ except Exception as exc:
91
+ self._fail(exc)
92
+
93
+ def request(self, method, params=None, *, timeout=None):
94
+ request_id = next(self._ids)
95
+ waiter = queue.Queue()
96
+ frame = pack({"id": request_id, "method": method, "params": params or {}})
97
+ with self._lock:
98
+ if self._failure:
99
+ raise self._failure
100
+ if self._sock is None:
101
+ raise ConnectionError("Call connect() first")
102
+ self._pending[request_id] = waiter
103
+ try:
104
+ with self._send_lock:
105
+ self._sock.sendall(frame)
106
+ try:
107
+ reply = waiter.get(timeout=self.timeout if timeout is None else timeout)
108
+ except queue.Empty:
109
+ raise TimeoutError(f"{method} timed out; upstream execution may still finish") from None
110
+ if isinstance(reply, Exception):
111
+ raise reply
112
+ if not reply.get("ok"):
113
+ error = reply["error"]
114
+ raise BridgeError(error["code"], error["message"])
115
+ return reply.get("result")
116
+ finally:
117
+ with self._lock:
118
+ self._pending.pop(request_id, None)
119
+
120
+ def ping(self):
121
+ return self.request("ping")
122
+
123
+ def status(self):
124
+ return self.request("status")
125
+
126
+ def methods(self):
127
+ return self.request("methods")
128
+
129
+ def query(self, name, **params):
130
+ """Returns {columns, records, dtypes}; datetime parameters are encoded automatically."""
131
+ return self.request("query", {"name": name, "kwargs": params})
132
+
133
+ def snapshot(self, symbols, datatype):
134
+ return self.query("get_gdp_recent_snap", htsc_code=symbols, data_type=datatype)
135
+
136
+ def static(self, symbols):
137
+ return self.query("get_gdp_static_by_id", htsc_code=symbols)
138
+
139
+ def subscribe(self, datatype, symbols=None):
140
+ """symbols=None subscribes the entire datatype. Returns submitted, not confirmed."""
141
+ return self.request("subscribe", {"datatype": datatype, "symbols": symbols})
142
+
143
+ def unsubscribe(self, datatype, symbols=None):
144
+ return self.request("unsubscribe", {"datatype": datatype, "symbols": symbols})
145
+
146
+ def subscribe_tick(self, symbols):
147
+ """Legacy SDK stock/futures/ETF tick subscription with explicit codes."""
148
+ return self.request("subscribe_tick", {"symbols": symbols})
149
+
150
+ def unsubscribe_tick(self, symbols):
151
+ return self.request("unsubscribe_tick", {"symbols": symbols})
152
+
153
+ def unsubscribe_all(self):
154
+ return self.request("unsubscribe_all")
155
+
156
+ def next_event(self, timeout=None):
157
+ # Check failure first: do not silently serve buffered stale data after a gap.
158
+ import time
159
+ deadline = None if timeout is None else time.monotonic() + timeout
160
+ while True:
161
+ if self._failure:
162
+ raise self._failure
163
+ wait = 0.2 if deadline is None else max(0, min(0.2, deadline - time.monotonic()))
164
+ try:
165
+ return self._events.get(timeout=wait)
166
+ except queue.Empty:
167
+ if deadline is not None and time.monotonic() >= deadline:
168
+ raise TimeoutError("No event received") from None
169
+
170
+ def events(self):
171
+ while True:
172
+ yield self.next_event()
173
+
174
+ def close(self):
175
+ self._fail(ConnectionError("Client closed"))
176
+ if self._reader and threading.current_thread() is not self._reader:
177
+ self._reader.join(timeout=2)
178
+
179
+ def __enter__(self):
180
+ return self.connect()
181
+
182
+ def __exit__(self, *_):
183
+ self.close()
@@ -0,0 +1 @@
1
+ """Insight-compatible module namespace."""
@@ -0,0 +1,9 @@
1
+ """Insight 6.1.2 data API over TCP, for Python 3.9-3.12.
2
+
3
+ Change SDK imports to this package and replace login/initialization with connect().
4
+ An SDK-compatible connection exclusively owns the server's native login session.
5
+ """
6
+ from ._session import Client, connect, close, SDKError
7
+ from . import query, subscribe, playback, market_service
8
+
9
+ __all__ = ['Client', 'connect', 'close', 'SDKError', 'query', 'subscribe', 'playback', 'market_service']
@@ -0,0 +1,2 @@
1
+ """Pinned public API contract, generated from SDK 6.1.2."""
2
+ CONTRACT = {'sdk_version': '6.1.2', 'modules': {'query': {'query_fin_info': '(query_type, params)', 'get_kline': "(htsc_code=None, time=None, frequency='daily', fq='pre')", 'get_derived': '(htsc_code=None, trading_day=None, type=None)', 'get_trade_distribution': '(htsc_code=None, trading_day=None)', 'get_chip_distribution': '(htsc_code=None, trading_day=None)', 'get_money_flow': '(htsc_code=None, trading_day=None)', 'get_change_summary': '(market=None, trading_day=None)', 'get_billboard': '(type=None, market=None)', 'get_stock_info': '(htsc_code=None, listing_date=None, listing_state=None)', 'get_all_stocks_info': '(listing_date=None, exchange=None, listing_state=None)', 'get_trading_days': '(exchange=None, trading_day=None, count=None)', 'get_industries': '(classified=None)', 'get_industry': "(htsc_code=None, classified='sw')", 'get_industry_stocks': "(industry_code=None, classified='sw')", 'get_new_share': '(htsc_code=None, book_start_date_online=None, listing_date=None)', 'get_daily_basic': '(htsc_code=None, trading_day=None)', 'get_stock_valuation': '(htsc_code=None, trading_day=None)', 'get_bond_info': '(htsc_code=None, secu_category_code=None, listing_date=None, issue_start_date=None, end_date=None)', 'get_all_bonds': '(exchange=None, secu_category_code=None, listing_date=None, issue_start_date=None, end_date=None)', 'get_repo_price': '(htsc_code=None, exchange=None, trading_day=None)', 'get_new_con_bond': '(htsc_code=None, exchange=None, book_start_date_online=None, listing_date=None, issue_date=None, convert_code=None)', 'get_bond_price': '(htsc_code=None, exchange=None, trading_day=None)', 'get_con_bond_redemption': '(htsc_code=None, exchange=None, register_date=None)', 'get_con_bond_2_shares_change': '(htsc_code=None, exchange=None, pub_date=None, convert_code=None)', 'get_con_bond_2_shares': '(htsc_code=None, pub_date=None, exer_begin_date=None, exer_end_date=None, convert_code=None, exchange=None)', 'get_income_statement': '(htsc_code=None, end_date=None, period=None)', 'get_balance_sheet': '(htsc_code=None, end_date=None, period=None)', 'get_cashflow_statement': '(htsc_code=None, end_date=None, period=None)', 'get_fin_indicator': '(htsc_code=None, end_date=None, period=None)', 'get_newest_stock_value': '(htsc_code=None, exchange=None)', 'get_company_info': '(htsc_code=None, name=None)', 'get_shareholder_num': '(htsc_code=None, name=None, end_date=None)', 'get_additional_share': '(htsc_code=None, listing_date=None)', 'get_allotment_share': '(htsc_code=None, ini_pub_date=None, is_allot_half_year=None)', 'get_capital_structure': '(htsc_code=None, end_date=None)', 'get_dividend': '(htsc_code=None, right_reg_date=None, ex_divi_date=None, divi_pay_date=None)', 'get_north_bound': '(htsc_code=None, trading_day=None)', 'get_margin_target': '(htsc_code=None, exchange=None)', 'get_margin_summary': '(htsc_code=None, trading_day=None)', 'get_margin_detail': '(exchange=None, trading_day=None)', 'get_shareholders_top10': '(htsc_code=None, change_date=None)', 'get_shareholders_floating_top10': '(htsc_code=None, change_date=None)', 'get_tick': '(htsc_code=None, security_type=None, trading_day=None)', 'get_adj_factor': '(htsc_code=None, begin_date=None)', 'get_locked_shares': '(htsc_code=None, listing_date=None)', 'get_frozen_shares': '(htsc_code=None, freezing_start_date=None)', 'get_hk_industry': '(htsc_code=None)', 'get_hk_industry_stocks': '(industry_code=None)', 'get_hk_daily_basic': '(htsc_code=None, trading_day=None)', 'get_hk_stock_valuation': '(htsc_code=None, trading_day=None)', 'get_hk_stock_basic_info': '(htsc_code=None, listing_date=None, listing_state=None)', 'get_hk_dividend': '(htsc_code=None, ex_divi_date=None)', 'get_hk_index_mapping': '(month=None)', 'get_main_product_info': '(htsc_code=None, product_code=None, product_level=None)', 'get_htsc_margin_target': '()', 'get_htsc_margin_by_id': '(htsc_code=None, data_type=None)', 'get_htsc_margin_by_type': '(data_type=None, security_type=None, is_async=False)', 'get_index_info': '(htsc_code=None, trading_day=None)', 'get_all_index': '(exchange=None, trading_day=None)', 'get_index_component': '(htsc_code=None, name=None, stock_code=None, trading_day=None)', 'get_index_component_pro': '(htsc_code=None, name=None, stock_code=None, trading_day=None)', 'get_factors': '(htsc_code=None, factor_name=None, trading_day=None)', 'get_fund_info': '(htsc_code=None, trading_day=None)', 'get_fund_target': '(htsc_code=None, exchange=None, end_date=None)', 'get_etf_component': '(htsc_code=None, pub_date=None, trading_day=None)', 'get_public_fund_portfolio': '(htsc_code=None, name=None, exchange=None, end_date=None)', 'get_etf_redemption': '(htsc_code=None, exchange=None, trading_day=None)', 'get_basic_info': '(htsc_code=None)', 'get_all_basic_info': '(security_type=None, exchange=None, today=True)', 'get_news': '(htsc_code=None, event_ids=None, pub_date=None)', 'find_edb_index': '(name=None)', 'edb': '(indexes=None, pub_date=None)', 'get_rpt_basicinfo_ht': '(id=None, report_code=None, time=None, title=None, language=None, is_valid=None)', 'get_rpt_stk_ht': '(report_code=None)', 'get_rpt_industry_ht': '(report_code=None)', 'get_rpt_author_ht': '(report_code=None)', 'get_rpt_annex_ht': '(report_code=None)', 'get_rpt_stkpredict_ht': '(report_code=None)', 'get_etf_info': '(query)', 'query_mdcontant': '(security_idsource_and_types, security_id_list)'}, 'subscribe': {'subscribe_tick_by_id': "(htsc_code, mode='coverage')", 'subscribe_tick_by_type': "(query=None, mode='coverage')", 'subscribe_kline_by_id': "(htsc_code=None, frequency=None, mode='coverage')", 'subscribe_kline_by_type': "(query=None, frequency=None, mode='coverage')", 'subscribe_trans_and_order_by_id': "(htsc_code=None, mode='coverage')", 'subscribe_trans_and_order_by_type': "(query=None, mode='coverage')", 'subscribe_htsc_margin_by_id': "(htsc_code=None, data_type=None, mode='coverage')", 'subscribe_htsc_margin_by_type': "(security_type=None, data_type=None, mode='coverage')", 'subscribe_derived': "(type=None, htsc_code=None, exchange=None, frequency='1min', mode='coverage')", 'subscribe_news_by_type': "(query=None, mode='coverage')", 'subscribe_news_by_id': "(htsc_code=None, mode='coverage')", 'sync': '()'}, 'playback': {'playback_tick': "(htsc_code=None, replay_time=None, fq='pre', timeout=600)", 'playback_trans_and_order': "(htsc_code=None, replay_time=None, fq='pre', timeout=600)"}}, 'sha256': {'query': '17976b193d25e5a05e8e3492b9f04ad54a93ddd1a700a30212b721cd09e3b4a7', 'subscribe': 'b7920962f688aac4cb8bedd8c5a60c80846a729b347eafc94719c5faba9913b0', 'playback': 'fdd2d88a9a67f564eae0c6a048916a4c25c0e1ca2bcd38ec03d24a3a5e2e2ddf'}, 'callbacks': ['on_subscribe_tick', 'on_subscribe_kline', 'on_subscribe_trans_and_order', 'on_subscribe_derived', 'on_subscribe_htsc_margin', 'on_subscribe_news', 'on_playback_tick', 'on_playback_trans_and_order', 'onPlaybackStatus', 'onPlaybackResponse', 'onPlaybackControlResponse', 'on_query_response', 'on_query_margin_response']}
@@ -0,0 +1,179 @@
1
+ import builtins
2
+ import functools
3
+ import importlib
4
+ import inspect
5
+ import logging
6
+ import queue
7
+ import threading
8
+
9
+ from ...client import InsightClient, BridgeError
10
+ from ...typed_codec import encode, decode
11
+ from ._contract import CONTRACT
12
+ from .market_service import market_service
13
+
14
+ LOG = logging.getLogger('insight_proxy.compat')
15
+ _default = None
16
+ _default_lock = threading.RLock()
17
+ _EXCEPTIONS = {name: getattr(builtins, name) for name in (
18
+ 'ValueError', 'TypeError', 'KeyError', 'IndexError', 'RuntimeError', 'AttributeError',
19
+ 'NotImplementedError', 'AssertionError', 'ZeroDivisionError', 'OverflowError',
20
+ 'NameError', 'UnboundLocalError', 'TimeoutError', 'OSError', 'ConnectionError',
21
+ 'PermissionError', 'FileNotFoundError', 'ImportError', 'ModuleNotFoundError')}
22
+
23
+
24
+ class SDKError(RuntimeError):
25
+ """A vendor exception whose class is not part of the safe builtin allowlist."""
26
+
27
+
28
+ class _Namespace:
29
+ def __init__(self, client, module):
30
+ self._client, self._module = client, module
31
+
32
+ def __dir__(self):
33
+ return list(CONTRACT['modules'][self._module])
34
+
35
+ def __getattr__(self, name):
36
+ if name not in CONTRACT['modules'][self._module]:
37
+ raise AttributeError(name)
38
+ template = getattr(importlib.import_module('.' + self._module, __package__), name)
39
+ if name == 'sync':
40
+ return template
41
+ signature = inspect.signature(template)
42
+
43
+ @functools.wraps(template)
44
+ def invoke(*args, **kwargs):
45
+ bound = signature.bind(*args, **kwargs)
46
+ bound.apply_defaults()
47
+ return self._client._call(self._module, name, dict(bound.arguments))
48
+ return invoke
49
+
50
+
51
+ class Client:
52
+ """Explicit session alternative to module-level connect/query/subscribe.
53
+
54
+ Callback exceptions are logged and placed in errors. Transport failures are
55
+ also placed there and close the session; neither is silently swallowed.
56
+ on_event receives bridge status/ack/error events, outside the SDK callback API.
57
+ """
58
+ def __init__(self, marketservice=None, *, host='127.0.0.1', port=8765, token='123456',
59
+ timeout=30, ssl_context=None, event_queue_size=10000, on_event=None):
60
+ self.transport = InsightClient(host, port, token=token, timeout=timeout,
61
+ ssl_context=ssl_context, event_queue_size=event_queue_size)
62
+ self.marketservice = market_service() if marketservice is None else marketservice
63
+ self.on_event = on_event
64
+ self.errors = queue.Queue(maxsize=100)
65
+ self.query = _Namespace(self, 'query')
66
+ self.subscribe = _Namespace(self, 'subscribe')
67
+ self.playback = _Namespace(self, 'playback')
68
+ self._closed = threading.Event()
69
+ self._thread = None
70
+ self._connected = False
71
+ self.capabilities = None
72
+
73
+ def connect(self):
74
+ # Fail early with an actionable dependency message, before claiming a login.
75
+ try:
76
+ import pandas # noqa: F401
77
+ except ImportError as exc:
78
+ raise ImportError('Install insight-proxy-client (pandas >=1.5,<3)') from exc
79
+ try:
80
+ self.transport.connect()
81
+ self.capabilities = self.transport.request('sdk_open', {'sdk_version': '6.1.2', 'codec': 1})
82
+ if self.capabilities.get('modules') != CONTRACT['modules']:
83
+ raise BridgeError('incompatible_sdk', 'Server API contract differs from Insight 6.1.2')
84
+ self._connected = True
85
+ self._thread = threading.Thread(target=self._callbacks, name='insight-callbacks', daemon=True)
86
+ self._thread.start()
87
+ return self
88
+ except BaseException:
89
+ self.close()
90
+ raise
91
+
92
+ def _call(self, module, name, kwargs):
93
+ if not self._connected or self._closed.is_set():
94
+ raise ConnectionError('Call connect() first; create a new Client after close()')
95
+ timeout = self.transport.timeout
96
+ # Native playback is blocking and has its own public timeout argument.
97
+ if module == 'playback' and isinstance(kwargs.get('timeout'), (int, float)):
98
+ timeout = max(timeout, kwargs['timeout'] + 15)
99
+ result = self.transport.request('sdk_call', {'module': module, 'name': name,
100
+ 'kwargs': encode(kwargs)}, timeout=timeout)
101
+ if 'exception' in result:
102
+ error = result['exception']
103
+ cls = _EXCEPTIONS.get(error['type'], SDKError)
104
+ raise cls(*decode(error['args']))
105
+ return decode(result['value'])
106
+
107
+ def _record_error(self, error):
108
+ try:
109
+ self.errors.put_nowait(error)
110
+ except queue.Full:
111
+ self.close()
112
+
113
+ def _callbacks(self):
114
+ while not self._closed.is_set():
115
+ try:
116
+ event = self.transport.next_event(timeout=0.2)
117
+ except TimeoutError:
118
+ continue
119
+ except Exception as exc:
120
+ if not self._closed.is_set():
121
+ self._record_error(exc)
122
+ LOG.error('Insight connection ended: %s', exc)
123
+ self.close()
124
+ break
125
+ try:
126
+ if event['event'] == 'sdk_callback':
127
+ name = event['data']['name']
128
+ if name not in CONTRACT['callbacks']:
129
+ raise ValueError('Unknown SDK callback: ' + str(name))
130
+ callback = getattr(self.marketservice, name, None)
131
+ if callback is not None:
132
+ callback(decode(event['data']['value']))
133
+ elif event['event'] == 'sdk_callback_error':
134
+ raise SDKError(event['data']['message'])
135
+ elif self.on_event:
136
+ self.on_event(event)
137
+ except Exception as exc:
138
+ self._record_error(exc)
139
+ LOG.exception('Insight callback failed')
140
+
141
+ def close(self):
142
+ self._closed.set()
143
+ self._connected = False
144
+ self.transport.close()
145
+ if self._thread and threading.current_thread() is not self._thread:
146
+ self._thread.join(timeout=2)
147
+ # The server resets the native login before another compatibility lease.
148
+
149
+ def __enter__(self):
150
+ return self.connect()
151
+
152
+ def __exit__(self, *_):
153
+ self.close()
154
+
155
+
156
+ def connect(marketservice=None, **connection):
157
+ """Initialize module-level APIs; credentials remain in the server config."""
158
+ global _default
159
+ with _default_lock:
160
+ if _default is not None and not _default._closed.is_set():
161
+ raise RuntimeError('A default connection is already active; call close() first')
162
+ _default = Client(marketservice, **connection).connect()
163
+ return _default
164
+
165
+
166
+ def close():
167
+ global _default
168
+ with _default_lock:
169
+ if _default is not None:
170
+ _default.close()
171
+ _default = None
172
+
173
+
174
+ def call(module, name, kwargs):
175
+ with _default_lock:
176
+ client = _default
177
+ if client is None:
178
+ raise ConnectionError('Call insight_proxy.com.insight.connect() first')
179
+ return client._call(module, name, kwargs)
@@ -0,0 +1,43 @@
1
+ """Override these callbacks exactly as with Insight 6.1.2."""
2
+ class market_service:
3
+ def __init__(self):
4
+ pass
5
+
6
+ def on_subscribe_tick(self, result):
7
+ pass
8
+
9
+ def on_subscribe_kline(self, result):
10
+ pass
11
+
12
+ def on_subscribe_trans_and_order(self, result):
13
+ pass
14
+
15
+ def on_subscribe_derived(self, result):
16
+ pass
17
+
18
+ def on_subscribe_htsc_margin(self, result):
19
+ pass
20
+
21
+ def on_subscribe_news(self, result):
22
+ pass
23
+
24
+ def on_playback_tick(self, result):
25
+ pass
26
+
27
+ def on_playback_trans_and_order(self, result):
28
+ pass
29
+
30
+ def onPlaybackStatus(self, status):
31
+ pass
32
+
33
+ def onPlaybackResponse(self, response):
34
+ pass
35
+
36
+ def onPlaybackControlResponse(self, response):
37
+ pass
38
+
39
+ def on_query_response(self, result):
40
+ pass
41
+
42
+ def on_query_margin_response(self, result):
43
+ pass
@@ -0,0 +1,13 @@
1
+ """Insight 6.1.2 signatures. Generated by tools/generate-compat.py."""
2
+ from ._session import call as _call
3
+
4
+
5
+ def playback_tick(htsc_code=None, replay_time=None, fq='pre', timeout=600):
6
+ """Socket equivalent of Insight 6.1.2 playback.playback_tick."""
7
+ return _call('playback', 'playback_tick', locals())
8
+
9
+ def playback_trans_and_order(htsc_code=None, replay_time=None, fq='pre', timeout=600):
10
+ """Socket equivalent of Insight 6.1.2 playback.playback_trans_and_order."""
11
+ return _call('playback', 'playback_trans_and_order', locals())
12
+
13
+ __all__ = ['playback_tick', 'playback_trans_and_order']
@@ -0,0 +1,325 @@
1
+ """Insight 6.1.2 signatures. Generated by tools/generate-compat.py."""
2
+ from ._session import call as _call
3
+
4
+
5
+ def query_fin_info(query_type, params):
6
+ """Socket equivalent of Insight 6.1.2 query.query_fin_info."""
7
+ return _call('query', 'query_fin_info', locals())
8
+
9
+ def get_kline(htsc_code=None, time=None, frequency='daily', fq='pre'):
10
+ """Socket equivalent of Insight 6.1.2 query.get_kline."""
11
+ return _call('query', 'get_kline', locals())
12
+
13
+ def get_derived(htsc_code=None, trading_day=None, type=None):
14
+ """Socket equivalent of Insight 6.1.2 query.get_derived."""
15
+ return _call('query', 'get_derived', locals())
16
+
17
+ def get_trade_distribution(htsc_code=None, trading_day=None):
18
+ """Socket equivalent of Insight 6.1.2 query.get_trade_distribution."""
19
+ return _call('query', 'get_trade_distribution', locals())
20
+
21
+ def get_chip_distribution(htsc_code=None, trading_day=None):
22
+ """Socket equivalent of Insight 6.1.2 query.get_chip_distribution."""
23
+ return _call('query', 'get_chip_distribution', locals())
24
+
25
+ def get_money_flow(htsc_code=None, trading_day=None):
26
+ """Socket equivalent of Insight 6.1.2 query.get_money_flow."""
27
+ return _call('query', 'get_money_flow', locals())
28
+
29
+ def get_change_summary(market=None, trading_day=None):
30
+ """Socket equivalent of Insight 6.1.2 query.get_change_summary."""
31
+ return _call('query', 'get_change_summary', locals())
32
+
33
+ def get_billboard(type=None, market=None):
34
+ """Socket equivalent of Insight 6.1.2 query.get_billboard."""
35
+ return _call('query', 'get_billboard', locals())
36
+
37
+ def get_stock_info(htsc_code=None, listing_date=None, listing_state=None):
38
+ """Socket equivalent of Insight 6.1.2 query.get_stock_info."""
39
+ return _call('query', 'get_stock_info', locals())
40
+
41
+ def get_all_stocks_info(listing_date=None, exchange=None, listing_state=None):
42
+ """Socket equivalent of Insight 6.1.2 query.get_all_stocks_info."""
43
+ return _call('query', 'get_all_stocks_info', locals())
44
+
45
+ def get_trading_days(exchange=None, trading_day=None, count=None):
46
+ """Socket equivalent of Insight 6.1.2 query.get_trading_days."""
47
+ return _call('query', 'get_trading_days', locals())
48
+
49
+ def get_industries(classified=None):
50
+ """Socket equivalent of Insight 6.1.2 query.get_industries."""
51
+ return _call('query', 'get_industries', locals())
52
+
53
+ def get_industry(htsc_code=None, classified='sw'):
54
+ """Socket equivalent of Insight 6.1.2 query.get_industry."""
55
+ return _call('query', 'get_industry', locals())
56
+
57
+ def get_industry_stocks(industry_code=None, classified='sw'):
58
+ """Socket equivalent of Insight 6.1.2 query.get_industry_stocks."""
59
+ return _call('query', 'get_industry_stocks', locals())
60
+
61
+ def get_new_share(htsc_code=None, book_start_date_online=None, listing_date=None):
62
+ """Socket equivalent of Insight 6.1.2 query.get_new_share."""
63
+ return _call('query', 'get_new_share', locals())
64
+
65
+ def get_daily_basic(htsc_code=None, trading_day=None):
66
+ """Socket equivalent of Insight 6.1.2 query.get_daily_basic."""
67
+ return _call('query', 'get_daily_basic', locals())
68
+
69
+ def get_stock_valuation(htsc_code=None, trading_day=None):
70
+ """Socket equivalent of Insight 6.1.2 query.get_stock_valuation."""
71
+ return _call('query', 'get_stock_valuation', locals())
72
+
73
+ def get_bond_info(htsc_code=None, secu_category_code=None, listing_date=None, issue_start_date=None, end_date=None):
74
+ """Socket equivalent of Insight 6.1.2 query.get_bond_info."""
75
+ return _call('query', 'get_bond_info', locals())
76
+
77
+ def get_all_bonds(exchange=None, secu_category_code=None, listing_date=None, issue_start_date=None, end_date=None):
78
+ """Socket equivalent of Insight 6.1.2 query.get_all_bonds."""
79
+ return _call('query', 'get_all_bonds', locals())
80
+
81
+ def get_repo_price(htsc_code=None, exchange=None, trading_day=None):
82
+ """Socket equivalent of Insight 6.1.2 query.get_repo_price."""
83
+ return _call('query', 'get_repo_price', locals())
84
+
85
+ def get_new_con_bond(htsc_code=None, exchange=None, book_start_date_online=None, listing_date=None, issue_date=None, convert_code=None):
86
+ """Socket equivalent of Insight 6.1.2 query.get_new_con_bond."""
87
+ return _call('query', 'get_new_con_bond', locals())
88
+
89
+ def get_bond_price(htsc_code=None, exchange=None, trading_day=None):
90
+ """Socket equivalent of Insight 6.1.2 query.get_bond_price."""
91
+ return _call('query', 'get_bond_price', locals())
92
+
93
+ def get_con_bond_redemption(htsc_code=None, exchange=None, register_date=None):
94
+ """Socket equivalent of Insight 6.1.2 query.get_con_bond_redemption."""
95
+ return _call('query', 'get_con_bond_redemption', locals())
96
+
97
+ def get_con_bond_2_shares_change(htsc_code=None, exchange=None, pub_date=None, convert_code=None):
98
+ """Socket equivalent of Insight 6.1.2 query.get_con_bond_2_shares_change."""
99
+ return _call('query', 'get_con_bond_2_shares_change', locals())
100
+
101
+ def get_con_bond_2_shares(htsc_code=None, pub_date=None, exer_begin_date=None, exer_end_date=None, convert_code=None, exchange=None):
102
+ """Socket equivalent of Insight 6.1.2 query.get_con_bond_2_shares."""
103
+ return _call('query', 'get_con_bond_2_shares', locals())
104
+
105
+ def get_income_statement(htsc_code=None, end_date=None, period=None):
106
+ """Socket equivalent of Insight 6.1.2 query.get_income_statement."""
107
+ return _call('query', 'get_income_statement', locals())
108
+
109
+ def get_balance_sheet(htsc_code=None, end_date=None, period=None):
110
+ """Socket equivalent of Insight 6.1.2 query.get_balance_sheet."""
111
+ return _call('query', 'get_balance_sheet', locals())
112
+
113
+ def get_cashflow_statement(htsc_code=None, end_date=None, period=None):
114
+ """Socket equivalent of Insight 6.1.2 query.get_cashflow_statement."""
115
+ return _call('query', 'get_cashflow_statement', locals())
116
+
117
+ def get_fin_indicator(htsc_code=None, end_date=None, period=None):
118
+ """Socket equivalent of Insight 6.1.2 query.get_fin_indicator."""
119
+ return _call('query', 'get_fin_indicator', locals())
120
+
121
+ def get_newest_stock_value(htsc_code=None, exchange=None):
122
+ """Socket equivalent of Insight 6.1.2 query.get_newest_stock_value."""
123
+ return _call('query', 'get_newest_stock_value', locals())
124
+
125
+ def get_company_info(htsc_code=None, name=None):
126
+ """Socket equivalent of Insight 6.1.2 query.get_company_info."""
127
+ return _call('query', 'get_company_info', locals())
128
+
129
+ def get_shareholder_num(htsc_code=None, name=None, end_date=None):
130
+ """Socket equivalent of Insight 6.1.2 query.get_shareholder_num."""
131
+ return _call('query', 'get_shareholder_num', locals())
132
+
133
+ def get_additional_share(htsc_code=None, listing_date=None):
134
+ """Socket equivalent of Insight 6.1.2 query.get_additional_share."""
135
+ return _call('query', 'get_additional_share', locals())
136
+
137
+ def get_allotment_share(htsc_code=None, ini_pub_date=None, is_allot_half_year=None):
138
+ """Socket equivalent of Insight 6.1.2 query.get_allotment_share."""
139
+ return _call('query', 'get_allotment_share', locals())
140
+
141
+ def get_capital_structure(htsc_code=None, end_date=None):
142
+ """Socket equivalent of Insight 6.1.2 query.get_capital_structure."""
143
+ return _call('query', 'get_capital_structure', locals())
144
+
145
+ def get_dividend(htsc_code=None, right_reg_date=None, ex_divi_date=None, divi_pay_date=None):
146
+ """Socket equivalent of Insight 6.1.2 query.get_dividend."""
147
+ return _call('query', 'get_dividend', locals())
148
+
149
+ def get_north_bound(htsc_code=None, trading_day=None):
150
+ """Socket equivalent of Insight 6.1.2 query.get_north_bound."""
151
+ return _call('query', 'get_north_bound', locals())
152
+
153
+ def get_margin_target(htsc_code=None, exchange=None):
154
+ """Socket equivalent of Insight 6.1.2 query.get_margin_target."""
155
+ return _call('query', 'get_margin_target', locals())
156
+
157
+ def get_margin_summary(htsc_code=None, trading_day=None):
158
+ """Socket equivalent of Insight 6.1.2 query.get_margin_summary."""
159
+ return _call('query', 'get_margin_summary', locals())
160
+
161
+ def get_margin_detail(exchange=None, trading_day=None):
162
+ """Socket equivalent of Insight 6.1.2 query.get_margin_detail."""
163
+ return _call('query', 'get_margin_detail', locals())
164
+
165
+ def get_shareholders_top10(htsc_code=None, change_date=None):
166
+ """Socket equivalent of Insight 6.1.2 query.get_shareholders_top10."""
167
+ return _call('query', 'get_shareholders_top10', locals())
168
+
169
+ def get_shareholders_floating_top10(htsc_code=None, change_date=None):
170
+ """Socket equivalent of Insight 6.1.2 query.get_shareholders_floating_top10."""
171
+ return _call('query', 'get_shareholders_floating_top10', locals())
172
+
173
+ def get_tick(htsc_code=None, security_type=None, trading_day=None):
174
+ """Socket equivalent of Insight 6.1.2 query.get_tick."""
175
+ return _call('query', 'get_tick', locals())
176
+
177
+ def get_adj_factor(htsc_code=None, begin_date=None):
178
+ """Socket equivalent of Insight 6.1.2 query.get_adj_factor."""
179
+ return _call('query', 'get_adj_factor', locals())
180
+
181
+ def get_locked_shares(htsc_code=None, listing_date=None):
182
+ """Socket equivalent of Insight 6.1.2 query.get_locked_shares."""
183
+ return _call('query', 'get_locked_shares', locals())
184
+
185
+ def get_frozen_shares(htsc_code=None, freezing_start_date=None):
186
+ """Socket equivalent of Insight 6.1.2 query.get_frozen_shares."""
187
+ return _call('query', 'get_frozen_shares', locals())
188
+
189
+ def get_hk_industry(htsc_code=None):
190
+ """Socket equivalent of Insight 6.1.2 query.get_hk_industry."""
191
+ return _call('query', 'get_hk_industry', locals())
192
+
193
+ def get_hk_industry_stocks(industry_code=None):
194
+ """Socket equivalent of Insight 6.1.2 query.get_hk_industry_stocks."""
195
+ return _call('query', 'get_hk_industry_stocks', locals())
196
+
197
+ def get_hk_daily_basic(htsc_code=None, trading_day=None):
198
+ """Socket equivalent of Insight 6.1.2 query.get_hk_daily_basic."""
199
+ return _call('query', 'get_hk_daily_basic', locals())
200
+
201
+ def get_hk_stock_valuation(htsc_code=None, trading_day=None):
202
+ """Socket equivalent of Insight 6.1.2 query.get_hk_stock_valuation."""
203
+ return _call('query', 'get_hk_stock_valuation', locals())
204
+
205
+ def get_hk_stock_basic_info(htsc_code=None, listing_date=None, listing_state=None):
206
+ """Socket equivalent of Insight 6.1.2 query.get_hk_stock_basic_info."""
207
+ return _call('query', 'get_hk_stock_basic_info', locals())
208
+
209
+ def get_hk_dividend(htsc_code=None, ex_divi_date=None):
210
+ """Socket equivalent of Insight 6.1.2 query.get_hk_dividend."""
211
+ return _call('query', 'get_hk_dividend', locals())
212
+
213
+ def get_hk_index_mapping(month=None):
214
+ """Socket equivalent of Insight 6.1.2 query.get_hk_index_mapping."""
215
+ return _call('query', 'get_hk_index_mapping', locals())
216
+
217
+ def get_main_product_info(htsc_code=None, product_code=None, product_level=None):
218
+ """Socket equivalent of Insight 6.1.2 query.get_main_product_info."""
219
+ return _call('query', 'get_main_product_info', locals())
220
+
221
+ def get_htsc_margin_target():
222
+ """Socket equivalent of Insight 6.1.2 query.get_htsc_margin_target."""
223
+ return _call('query', 'get_htsc_margin_target', locals())
224
+
225
+ def get_htsc_margin_by_id(htsc_code=None, data_type=None):
226
+ """Socket equivalent of Insight 6.1.2 query.get_htsc_margin_by_id."""
227
+ return _call('query', 'get_htsc_margin_by_id', locals())
228
+
229
+ def get_htsc_margin_by_type(data_type=None, security_type=None, is_async=False):
230
+ """Socket equivalent of Insight 6.1.2 query.get_htsc_margin_by_type."""
231
+ return _call('query', 'get_htsc_margin_by_type', locals())
232
+
233
+ def get_index_info(htsc_code=None, trading_day=None):
234
+ """Socket equivalent of Insight 6.1.2 query.get_index_info."""
235
+ return _call('query', 'get_index_info', locals())
236
+
237
+ def get_all_index(exchange=None, trading_day=None):
238
+ """Socket equivalent of Insight 6.1.2 query.get_all_index."""
239
+ return _call('query', 'get_all_index', locals())
240
+
241
+ def get_index_component(htsc_code=None, name=None, stock_code=None, trading_day=None):
242
+ """Socket equivalent of Insight 6.1.2 query.get_index_component."""
243
+ return _call('query', 'get_index_component', locals())
244
+
245
+ def get_index_component_pro(htsc_code=None, name=None, stock_code=None, trading_day=None):
246
+ """Socket equivalent of Insight 6.1.2 query.get_index_component_pro."""
247
+ return _call('query', 'get_index_component_pro', locals())
248
+
249
+ def get_factors(htsc_code=None, factor_name=None, trading_day=None):
250
+ """Socket equivalent of Insight 6.1.2 query.get_factors."""
251
+ return _call('query', 'get_factors', locals())
252
+
253
+ def get_fund_info(htsc_code=None, trading_day=None):
254
+ """Socket equivalent of Insight 6.1.2 query.get_fund_info."""
255
+ return _call('query', 'get_fund_info', locals())
256
+
257
+ def get_fund_target(htsc_code=None, exchange=None, end_date=None):
258
+ """Socket equivalent of Insight 6.1.2 query.get_fund_target."""
259
+ return _call('query', 'get_fund_target', locals())
260
+
261
+ def get_etf_component(htsc_code=None, pub_date=None, trading_day=None):
262
+ """Socket equivalent of Insight 6.1.2 query.get_etf_component."""
263
+ return _call('query', 'get_etf_component', locals())
264
+
265
+ def get_public_fund_portfolio(htsc_code=None, name=None, exchange=None, end_date=None):
266
+ """Socket equivalent of Insight 6.1.2 query.get_public_fund_portfolio."""
267
+ return _call('query', 'get_public_fund_portfolio', locals())
268
+
269
+ def get_etf_redemption(htsc_code=None, exchange=None, trading_day=None):
270
+ """Socket equivalent of Insight 6.1.2 query.get_etf_redemption."""
271
+ return _call('query', 'get_etf_redemption', locals())
272
+
273
+ def get_basic_info(htsc_code=None):
274
+ """Socket equivalent of Insight 6.1.2 query.get_basic_info."""
275
+ return _call('query', 'get_basic_info', locals())
276
+
277
+ def get_all_basic_info(security_type=None, exchange=None, today=True):
278
+ """Socket equivalent of Insight 6.1.2 query.get_all_basic_info."""
279
+ return _call('query', 'get_all_basic_info', locals())
280
+
281
+ def get_news(htsc_code=None, event_ids=None, pub_date=None):
282
+ """Socket equivalent of Insight 6.1.2 query.get_news."""
283
+ return _call('query', 'get_news', locals())
284
+
285
+ def find_edb_index(name=None):
286
+ """Socket equivalent of Insight 6.1.2 query.find_edb_index."""
287
+ return _call('query', 'find_edb_index', locals())
288
+
289
+ def edb(indexes=None, pub_date=None):
290
+ """Socket equivalent of Insight 6.1.2 query.edb."""
291
+ return _call('query', 'edb', locals())
292
+
293
+ def get_rpt_basicinfo_ht(id=None, report_code=None, time=None, title=None, language=None, is_valid=None):
294
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_basicinfo_ht."""
295
+ return _call('query', 'get_rpt_basicinfo_ht', locals())
296
+
297
+ def get_rpt_stk_ht(report_code=None):
298
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_stk_ht."""
299
+ return _call('query', 'get_rpt_stk_ht', locals())
300
+
301
+ def get_rpt_industry_ht(report_code=None):
302
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_industry_ht."""
303
+ return _call('query', 'get_rpt_industry_ht', locals())
304
+
305
+ def get_rpt_author_ht(report_code=None):
306
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_author_ht."""
307
+ return _call('query', 'get_rpt_author_ht', locals())
308
+
309
+ def get_rpt_annex_ht(report_code=None):
310
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_annex_ht."""
311
+ return _call('query', 'get_rpt_annex_ht', locals())
312
+
313
+ def get_rpt_stkpredict_ht(report_code=None):
314
+ """Socket equivalent of Insight 6.1.2 query.get_rpt_stkpredict_ht."""
315
+ return _call('query', 'get_rpt_stkpredict_ht', locals())
316
+
317
+ def get_etf_info(query):
318
+ """Socket equivalent of Insight 6.1.2 query.get_etf_info."""
319
+ return _call('query', 'get_etf_info', locals())
320
+
321
+ def query_mdcontant(security_idsource_and_types, security_id_list):
322
+ """Socket equivalent of Insight 6.1.2 query.query_mdcontant."""
323
+ return _call('query', 'query_mdcontant', locals())
324
+
325
+ __all__ = ['query_fin_info', 'get_kline', 'get_derived', 'get_trade_distribution', 'get_chip_distribution', 'get_money_flow', 'get_change_summary', 'get_billboard', 'get_stock_info', 'get_all_stocks_info', 'get_trading_days', 'get_industries', 'get_industry', 'get_industry_stocks', 'get_new_share', 'get_daily_basic', 'get_stock_valuation', 'get_bond_info', 'get_all_bonds', 'get_repo_price', 'get_new_con_bond', 'get_bond_price', 'get_con_bond_redemption', 'get_con_bond_2_shares_change', 'get_con_bond_2_shares', 'get_income_statement', 'get_balance_sheet', 'get_cashflow_statement', 'get_fin_indicator', 'get_newest_stock_value', 'get_company_info', 'get_shareholder_num', 'get_additional_share', 'get_allotment_share', 'get_capital_structure', 'get_dividend', 'get_north_bound', 'get_margin_target', 'get_margin_summary', 'get_margin_detail', 'get_shareholders_top10', 'get_shareholders_floating_top10', 'get_tick', 'get_adj_factor', 'get_locked_shares', 'get_frozen_shares', 'get_hk_industry', 'get_hk_industry_stocks', 'get_hk_daily_basic', 'get_hk_stock_valuation', 'get_hk_stock_basic_info', 'get_hk_dividend', 'get_hk_index_mapping', 'get_main_product_info', 'get_htsc_margin_target', 'get_htsc_margin_by_id', 'get_htsc_margin_by_type', 'get_index_info', 'get_all_index', 'get_index_component', 'get_index_component_pro', 'get_factors', 'get_fund_info', 'get_fund_target', 'get_etf_component', 'get_public_fund_portfolio', 'get_etf_redemption', 'get_basic_info', 'get_all_basic_info', 'get_news', 'find_edb_index', 'edb', 'get_rpt_basicinfo_ht', 'get_rpt_stk_ht', 'get_rpt_industry_ht', 'get_rpt_author_ht', 'get_rpt_annex_ht', 'get_rpt_stkpredict_ht', 'get_etf_info', 'query_mdcontant']
@@ -0,0 +1,55 @@
1
+ """Insight 6.1.2 signatures. Generated by tools/generate-compat.py."""
2
+ from ._session import call as _call
3
+
4
+
5
+ def subscribe_tick_by_id(htsc_code, mode='coverage'):
6
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_tick_by_id."""
7
+ return _call('subscribe', 'subscribe_tick_by_id', locals())
8
+
9
+ def subscribe_tick_by_type(query=None, mode='coverage'):
10
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_tick_by_type."""
11
+ return _call('subscribe', 'subscribe_tick_by_type', locals())
12
+
13
+ def subscribe_kline_by_id(htsc_code=None, frequency=None, mode='coverage'):
14
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_kline_by_id."""
15
+ return _call('subscribe', 'subscribe_kline_by_id', locals())
16
+
17
+ def subscribe_kline_by_type(query=None, frequency=None, mode='coverage'):
18
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_kline_by_type."""
19
+ return _call('subscribe', 'subscribe_kline_by_type', locals())
20
+
21
+ def subscribe_trans_and_order_by_id(htsc_code=None, mode='coverage'):
22
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_trans_and_order_by_id."""
23
+ return _call('subscribe', 'subscribe_trans_and_order_by_id', locals())
24
+
25
+ def subscribe_trans_and_order_by_type(query=None, mode='coverage'):
26
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_trans_and_order_by_type."""
27
+ return _call('subscribe', 'subscribe_trans_and_order_by_type', locals())
28
+
29
+ def subscribe_htsc_margin_by_id(htsc_code=None, data_type=None, mode='coverage'):
30
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_htsc_margin_by_id."""
31
+ return _call('subscribe', 'subscribe_htsc_margin_by_id', locals())
32
+
33
+ def subscribe_htsc_margin_by_type(security_type=None, data_type=None, mode='coverage'):
34
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_htsc_margin_by_type."""
35
+ return _call('subscribe', 'subscribe_htsc_margin_by_type', locals())
36
+
37
+ def subscribe_derived(type=None, htsc_code=None, exchange=None, frequency='1min', mode='coverage'):
38
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_derived."""
39
+ return _call('subscribe', 'subscribe_derived', locals())
40
+
41
+ def subscribe_news_by_type(query=None, mode='coverage'):
42
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_news_by_type."""
43
+ return _call('subscribe', 'subscribe_news_by_type', locals())
44
+
45
+ def subscribe_news_by_id(htsc_code=None, mode='coverage'):
46
+ """Socket equivalent of Insight 6.1.2 subscribe.subscribe_news_by_id."""
47
+ return _call('subscribe', 'subscribe_news_by_id', locals())
48
+
49
+ def sync():
50
+ """Socket equivalent of Insight 6.1.2 subscribe.sync."""
51
+ line = input()
52
+ if line:
53
+ print("sync: input-->>" + str(line) + ",then exit this sync.")
54
+
55
+ __all__ = ['subscribe_tick_by_id', 'subscribe_tick_by_type', 'subscribe_kline_by_id', 'subscribe_kline_by_type', 'subscribe_trans_and_order_by_id', 'subscribe_trans_and_order_by_type', 'subscribe_htsc_margin_by_id', 'subscribe_htsc_margin_by_type', 'subscribe_derived', 'subscribe_news_by_type', 'subscribe_news_by_id', 'sync']
@@ -0,0 +1,58 @@
1
+ """Wire v1: 4 byte unsigned big endian length + UTF-8 JSON object."""
2
+ import datetime as dt
3
+ import json
4
+ import math
5
+ import struct
6
+
7
+ MAX_FRAME = 32 * 1024 * 1024
8
+
9
+
10
+ def wire_value(value):
11
+ if isinstance(value, dt.datetime):
12
+ return {"$datetime": value.isoformat()}
13
+ if isinstance(value, dt.date):
14
+ return {"$datetime": dt.datetime.combine(value, dt.time()).isoformat()}
15
+ if isinstance(value, dict):
16
+ return {str(k): wire_value(v) for k, v in value.items()}
17
+ if isinstance(value, (list, tuple)):
18
+ return [wire_value(v) for v in value]
19
+ if isinstance(value, float) and not math.isfinite(value):
20
+ return None
21
+ if value is None or isinstance(value, (str, int, float, bool)):
22
+ return value
23
+ # numpy scalars, without requiring numpy on the client.
24
+ if hasattr(value, "item"):
25
+ return wire_value(value.item())
26
+ raise TypeError("Unsupported wire value: " + type(value).__name__)
27
+
28
+
29
+ def restore_dates(value):
30
+ if isinstance(value, dict):
31
+ if set(value) == {"$datetime"}:
32
+ return dt.datetime.fromisoformat(value["$datetime"])
33
+ return {k: restore_dates(v) for k, v in value.items()}
34
+ if isinstance(value, list):
35
+ return [restore_dates(v) for v in value]
36
+ return value
37
+
38
+
39
+ def pack(message):
40
+ payload = json.dumps(wire_value(message), ensure_ascii=False,
41
+ allow_nan=False, separators=(",", ":")).encode("utf-8")
42
+ if not 0 < len(payload) <= MAX_FRAME:
43
+ raise ValueError("Frame exceeds 32 MiB; narrow the query")
44
+ return struct.pack("!I", len(payload)) + payload
45
+
46
+
47
+ def unpack(payload):
48
+ message = json.loads(payload, parse_constant=lambda _: (_ for _ in ()).throw(ValueError("Invalid JSON number")))
49
+ if not isinstance(message, dict):
50
+ raise ValueError("Message must be an object")
51
+ return message
52
+
53
+
54
+ def frame_size(header):
55
+ size, = struct.unpack("!I", header)
56
+ if not 0 < size <= MAX_FRAME:
57
+ raise ValueError("Invalid frame length")
58
+ return size
@@ -0,0 +1,160 @@
1
+ """Versioned, non-executable JSON codec for SDK data; no pickle or eval.
2
+
3
+ Every container is tagged, so user dictionary keys cannot collide with tags.
4
+ Pandas is imported only when the compatibility API is used.
5
+ """
6
+ import base64
7
+ import datetime as dt
8
+ from decimal import Decimal
9
+ import math
10
+
11
+
12
+ def encode(value):
13
+ import numpy as np
14
+ import pandas as pd
15
+ if value is pd.NA:
16
+ return {'t': 'NA'}
17
+ if value is pd.NaT:
18
+ return {'t': 'NaT'}
19
+ if isinstance(value, pd.DataFrame):
20
+ return {'t': 'frame', 'index': encode(value.index), 'columns': encode(value.columns),
21
+ 'series': [encode(value.iloc[:, i]) for i in range(len(value.columns))],
22
+ 'attrs': encode(value.attrs)}
23
+ if isinstance(value, pd.Series):
24
+ return {'t': 'series', 'index': encode(value.index), 'name': encode(value.name),
25
+ 'dtype': _dtype(value.dtype), 'values': encode(value.tolist()), 'attrs': encode(value.attrs)}
26
+ if isinstance(value, pd.MultiIndex):
27
+ return {'t': 'multiindex', 'levels': [encode(x) for x in value.levels],
28
+ 'codes': [x.tolist() for x in value.codes], 'names': encode(value.names),
29
+ 'sortorder': value.sortorder}
30
+ if isinstance(value, pd.RangeIndex):
31
+ return {'t': 'rangeindex', 'start': value.start, 'stop': value.stop,
32
+ 'step': value.step, 'name': encode(value.name)}
33
+ if isinstance(value, pd.Index):
34
+ return {'t': 'index', 'values': encode(value.tolist()), 'dtype': _dtype(value.dtype),
35
+ 'name': encode(value.name), 'freq': getattr(value, 'freqstr', None)}
36
+ if isinstance(value, pd.Timestamp):
37
+ return {'t': 'timestamp', 'v': value.isoformat(), 'tz': str(value.tz) if value.tz else None}
38
+ if isinstance(value, pd.Timedelta):
39
+ return {'t': 'timedelta_ns', 'v': value.value}
40
+ if isinstance(value, np.ndarray):
41
+ if value.dtype.hasobject:
42
+ return {'t': 'object_array', 'shape': list(value.shape), 'v': encode(value.ravel().tolist())}
43
+ if value.dtype.fields:
44
+ raise TypeError('Structured numpy arrays are not supported by codec v1')
45
+ return {'t': 'array', 'dtype': value.dtype.str, 'shape': list(value.shape),
46
+ 'v': base64.b64encode(value.tobytes(order='C')).decode('ascii')}
47
+ if isinstance(value, np.generic):
48
+ return {'t': 'scalar', 'v': encode(np.asarray(value))}
49
+ if isinstance(value, dt.datetime):
50
+ return {'t': 'datetime', 'v': value.isoformat(), 'fold': value.fold}
51
+ if isinstance(value, dt.date):
52
+ return {'t': 'date', 'v': value.isoformat()}
53
+ if isinstance(value, dt.time):
54
+ return {'t': 'time', 'v': value.isoformat(), 'fold': value.fold}
55
+ if isinstance(value, dt.timedelta):
56
+ return {'t': 'timedelta', 'days': value.days, 'seconds': value.seconds, 'microseconds': value.microseconds}
57
+ if isinstance(value, Decimal):
58
+ return {'t': 'decimal', 'v': str(value)}
59
+ if isinstance(value, bytes):
60
+ return {'t': 'bytes', 'v': base64.b64encode(value).decode('ascii')}
61
+ if isinstance(value, dict):
62
+ return {'t': 'dict', 'v': [[encode(k), encode(v)] for k, v in value.items()]}
63
+ if isinstance(value, (list, tuple)):
64
+ return {'t': 'tuple' if isinstance(value, tuple) else 'list', 'v': [encode(v) for v in value]}
65
+ if isinstance(value, float) and not math.isfinite(value):
66
+ return {'t': 'float', 'v': 'nan' if math.isnan(value) else 'inf' if value > 0 else '-inf'}
67
+ if value is None or type(value) in (str, int, float, bool):
68
+ return value
69
+ raise TypeError('Unsupported SDK data type: ' + type(value).__name__)
70
+
71
+
72
+ def _dtype(dtype):
73
+ import pandas as pd
74
+ if isinstance(dtype, pd.CategoricalDtype):
75
+ return {'category': encode(dtype.categories), 'ordered': dtype.ordered}
76
+ return str(dtype)
77
+
78
+
79
+ def _restore_dtype(dtype):
80
+ import pandas as pd
81
+ if isinstance(dtype, dict):
82
+ return pd.CategoricalDtype(decode(dtype['category']), ordered=dtype['ordered'])
83
+ return dtype
84
+
85
+
86
+ def decode(value):
87
+ import numpy as np
88
+ import pandas as pd
89
+ if value is None or type(value) in (str, int, float, bool):
90
+ return value
91
+ if not isinstance(value, dict) or 't' not in value:
92
+ raise ValueError('Invalid SDK codec value')
93
+ tag = value['t']
94
+ if tag == 'dict':
95
+ return {decode(k): decode(v) for k, v in value['v']}
96
+ if tag in ('list', 'tuple'):
97
+ result = [decode(v) for v in value['v']]
98
+ return tuple(result) if tag == 'tuple' else result
99
+ if tag == 'frame':
100
+ columns, index = decode(value['columns']), decode(value['index'])
101
+ series = [decode(v) for v in value['series']]
102
+ if len(columns) != len(series) or any(not s.index.equals(index) for s in series):
103
+ raise ValueError('Invalid DataFrame axes')
104
+ result = pd.concat(series, axis=1) if series else pd.DataFrame(index=index)
105
+ result.index, result.columns = index, columns
106
+ result.attrs = decode(value['attrs'])
107
+ return result
108
+ if tag == 'series':
109
+ result = pd.Series(decode(value['values']), index=decode(value['index']),
110
+ dtype=_restore_dtype(value['dtype']), name=decode(value['name']))
111
+ result.attrs = decode(value['attrs'])
112
+ return result
113
+ if tag == 'multiindex':
114
+ return pd.MultiIndex(levels=[decode(x) for x in value['levels']], codes=value['codes'],
115
+ names=decode(value['names']), sortorder=value['sortorder'])
116
+ if tag == 'rangeindex':
117
+ return pd.RangeIndex(value['start'], value['stop'], value['step'], name=decode(value['name']))
118
+ if tag == 'index':
119
+ result = pd.Index(decode(value['values']), dtype=_restore_dtype(value['dtype']), name=decode(value['name']))
120
+ if value.get('freq') is not None:
121
+ result.freq = value['freq']
122
+ return result
123
+ if tag == 'timestamp':
124
+ result = pd.Timestamp(value['v'])
125
+ return result.tz_convert(value['tz']) if value['tz'] else result
126
+ if tag == 'timedelta_ns':
127
+ return pd.Timedelta(value['v'], unit='ns')
128
+ if tag == 'NaT':
129
+ return pd.NaT
130
+ if tag == 'NA':
131
+ return pd.NA
132
+ if tag == 'datetime':
133
+ return dt.datetime.fromisoformat(value['v']).replace(fold=value.get('fold', 0))
134
+ if tag == 'date':
135
+ return dt.date.fromisoformat(value['v'])
136
+ if tag == 'time':
137
+ return dt.time.fromisoformat(value['v']).replace(fold=value.get('fold', 0))
138
+ if tag == 'timedelta':
139
+ return dt.timedelta(days=value['days'], seconds=value['seconds'], microseconds=value['microseconds'])
140
+ if tag == 'decimal':
141
+ return Decimal(value['v'])
142
+ if tag == 'float':
143
+ if value['v'] not in ('nan', 'inf', '-inf'):
144
+ raise ValueError('Invalid non-finite float')
145
+ return float(value['v'])
146
+ if tag == 'bytes':
147
+ return base64.b64decode(value['v'], validate=True)
148
+ if tag == 'scalar':
149
+ return decode(value['v'])[()]
150
+ if tag == 'array':
151
+ dtype = np.dtype(value['dtype'])
152
+ if dtype.hasobject or dtype.fields:
153
+ raise ValueError('Unsafe numpy dtype')
154
+ return np.frombuffer(base64.b64decode(value['v'], validate=True), dtype=dtype).reshape(value['shape']).copy()
155
+ if tag == 'object_array':
156
+ data = decode(value['v'])
157
+ result = np.empty(len(data), dtype=object)
158
+ result[:] = data
159
+ return result.reshape(value['shape'])
160
+ raise ValueError('Unknown SDK codec tag: ' + str(tag))
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: insight-proxy-client
3
+ Version: 0.0.1
4
+ Summary: Python client for insight_proxy with Insight 6.1.2 compatible data APIs
5
+ Classifier: Programming Language :: Python :: 3
6
+ Classifier: Programming Language :: Python :: 3.9
7
+ Classifier: Programming Language :: Python :: 3.10
8
+ Classifier: Programming Language :: Python :: 3.11
9
+ Classifier: Programming Language :: Python :: 3.12
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.9
12
+ Description-Content-Type: text/markdown
13
+ Requires-Dist: pandas<3,>=1.5
14
+ Requires-Dist: numpy<3,>=1.23
15
+
16
+ # insight-proxy-client
17
+
18
+ Python client for the **insight_proxy** TCP service. Data APIs target **Insight 6.1.2**;
19
+ the import namespace is `insight_proxy.com.insight`.
20
+ This is an independent adapter, not the official Insight SDK.
21
+
22
+ ## Installation
23
+
24
+ ```shell
25
+ python -m pip install insight-proxy-client==0.0.1
26
+ ```
27
+
28
+ Supports Python 3.9–3.12. pandas and NumPy are installed as dependencies.
29
+ The client does not require the vendor SDK or native DLLs. A separately deployed
30
+ insight_proxy server with Insight 6.1.2 and valid data access is required.
31
+ This package does not include the server executable or account credentials.
32
+
33
+ ## Quick start
34
+
35
+ ```python
36
+ from datetime import datetime
37
+ from insight_proxy.com.insight import Client
38
+ from insight_proxy.com.insight.market_service import market_service
39
+
40
+ class Market(market_service):
41
+ def on_subscribe_tick(self, result):
42
+ print(result)
43
+
44
+ def on_query_response(self, result):
45
+ print(result)
46
+
47
+ # Both Client() and Client(Market()) are supported.
48
+ # Defaults: host="127.0.0.1", port=8765, token="123456".
49
+ # The token must match the server configuration.
50
+ with Client(Market()) as client:
51
+ frame = client.query.get_kline(
52
+ "601688.SH",
53
+ [datetime(2026, 10, 19), datetime(2026, 10, 26, 23, 59, 59)],
54
+ frequency="daily", fq="none",
55
+ )
56
+ print(frame)
57
+ client.subscribe.subscribe_tick_by_id(["601688.SH"], mode="coverage")
58
+ input("Press Enter to close the subscription session.\n")
59
+ ```
60
+
61
+ Construction does not open a connection. Use `client.connect()` / `client.close()`
62
+ or a `with` block. Override connection settings using keyword arguments:
63
+ `Client(Market(), host="127.0.0.1", port=8765, token="your-server-token")`.
64
+ Example dates are fixed historical values; select dates and instruments available
65
+ to your server account.
66
+
67
+ ## Migrating SDK data calls
68
+
69
+ Replace `insight_python.com.insight` imports with `insight_proxy.com.insight`.
70
+ Replace SDK login and initialization with the proxy connection:
71
+
72
+ ```python
73
+ from insight_proxy.com.insight import connect, close, query, subscribe, playback
74
+
75
+ connect() # or connect(Market(), host="...", port=8765, token="...")
76
+ try:
77
+ result = query.get_kline() # retains the SDK's missing-argument response
78
+ finally:
79
+ close()
80
+ ```
81
+
82
+ The compatibility layer exposes 80 query functions, 11 data subscription functions,
83
+ local `subscribe.sync()`, two playback functions and the `market_service` callbacks.
84
+ It preserves Insight 6.1.2 data function signatures, DataFrame/Series values,
85
+ column ordering, indexes, dtypes, datetime values, tuples and callback names.
86
+ SDK login/logging helpers and native gateway types are outside this client API.
87
+ One compatibility session exclusively owns the server's native SDK login.
88
+ Native SDK permissions and availability still determine which requests succeed.
89
+
90
+ Do not install the older combined `insight_proxy` distribution alongside this
91
+ client package in the same environment: they provide the same import namespace.
@@ -0,0 +1,16 @@
1
+ insight_proxy/__init__.py,sha256=tF1vGxFCs6nJieYSvQR7B8ygocwtyE43VdhhgE3_-o4,147
2
+ insight_proxy/client.py,sha256=eFGaFVnIssNb5ojRcbcs6geEOlDagCT2L9blIWF7xXc,7047
3
+ insight_proxy/protocol.py,sha256=Qbs8t31I5MOZCAzSiVbU_koHvn7LRC-Q8B9_rKgn56U,2074
4
+ insight_proxy/typed_codec.py,sha256=dWvYqjBdo-PqPtY48JeNf0ndV0aSnFoPRnUyqBXN3Sg,7693
5
+ insight_proxy/com/__init__.py,sha256=lyzWltItjQ8xZ-YeffVvPEdwUJ6tOdIUJKGCptvpi9s,44
6
+ insight_proxy/com/insight/__init__.py,sha256=CgWUNP8zpC_T6eHRBuUP5R-vVOb4W8fMxxq0dzyEMvQ,454
7
+ insight_proxy/com/insight/_contract.py,sha256=lwYNV5pamrEA_2oMyK5hGEWZAmyJs-ZfNv7ZyICnUvE,7053
8
+ insight_proxy/com/insight/_session.py,sha256=c96hjWpy9nfNcjnxRNrxcIY4L7MB7sJYIZdWEzUCLT0,7333
9
+ insight_proxy/com/insight/market_service.py,sha256=fN2rmHKr_uGrZpZTGbGdR16FTT2Tc3u58A850yC4jDM,929
10
+ insight_proxy/com/insight/playback.py,sha256=fW1PaHsfPL0pHN3Gi56Nj8-g6LX0d3H32gV6wVn1lVw,615
11
+ insight_proxy/com/insight/query.py,sha256=JGunc3AAPtLW0_EKqQYDWZ_BePy-mi-sl9A1RXVr0LA,17556
12
+ insight_proxy/com/insight/subscribe.py,sha256=SNmFmNK1fzZPDyxO0CIN6ZmParBT4DwZ_vQHqOLpkec,3106
13
+ insight_proxy_client-0.0.1.dist-info/METADATA,sha256=vJix0U7BxBBm-Og6HUuvC1cH0d_ewjyFgnigXEvQEts,3626
14
+ insight_proxy_client-0.0.1.dist-info/WHEEL,sha256=mOdXR9C3wMVov7cSY8PY-XCzo3SmmWCHvGQr5csJoao,91
15
+ insight_proxy_client-0.0.1.dist-info/top_level.txt,sha256=PFcyp7boXpP2NXvMo99R4BWLIHbNd4zb4nqEOLKJOn8,14
16
+ insight_proxy_client-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.2.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ insight_proxy