cfquant 0.2.0__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.
- LTtx/__init__.py +2 -0
- LTtx/tx/Config.txt +8 -0
- LTtx/tx/LTtx_server.py +1177 -0
- LTtx/tx/__init__.py +5 -0
- LTtx/tx/tx.py +1935 -0
- cfquant/__init__.py +26 -0
- cfquant/account_routing.py +119 -0
- cfquant/channels.py +76 -0
- cfquant/cli.py +266 -0
- cfquant/client.py +365 -0
- cfquant/config.py +86 -0
- cfquant/hub.py +304 -0
- cfquant/logging_i18n.py +348 -0
- cfquant/normal_bridge.py +676 -0
- cfquant/pipe_bridge.py +249 -0
- cfquant/pipe_client.py +223 -0
- cfquant/pipe_hub.py +602 -0
- cfquant/pipe_transport.py +493 -0
- cfquant/protocol.py +238 -0
- cfquant/qmt_bridge.py +1081 -0
- cfquant/runtime_report.py +334 -0
- cfquant/tx.py +1898 -0
- cfquant/tx_trade_bridge.py +1905 -0
- cfquant/version.py +5 -0
- cfquant/xtconstant.py +262 -0
- cfquant/xtdata.py +462 -0
- cfquant/xttrader.py +955 -0
- cfquant/xttype.py +586 -0
- cfquant-0.2.0.dist-info/LICENSE +21 -0
- cfquant-0.2.0.dist-info/METADATA +144 -0
- cfquant-0.2.0.dist-info/RECORD +90 -0
- cfquant-0.2.0.dist-info/WHEEL +5 -0
- cfquant-0.2.0.dist-info/entry_points.txt +4 -0
- cfquant-0.2.0.dist-info/top_level.txt +6 -0
- cfquant_pipe_hub.py +45 -0
- cfquant_web_server.py +12137 -0
- qmt_scripts/CFQUANT.py +507 -0
- qmt_scripts/CFQUANT_CTYPE_ALL_LOWLAT.py +830 -0
- qmt_scripts/CFQUANT_LITE.py +4928 -0
- qmt_scripts/CFQUANT_TRADE_LOWLAT.py +382 -0
- qmt_scripts/__init__.py +1 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_CTYPE_ALL_LOWLAT_SH.py +866 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_CTYPE_ALL_LOWLAT_SZ.py +866 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_LITE_SH.py +5020 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_LITE_SZ.py +5020 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_TRADE_LOWLAT_SH.py +436 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/CFQUANT_TRADE_LOWLAT_SZ.py +436 -0
- qmt_scripts//321/205/320/240/320/234/321/210/342/224/244/320/266/321/205/320/237/342/225/226/321/207/320/233/320/274/321/207/320/273/320/233/321/205/342/225/225/320/222/321/205/320/254/342/225/221/readme.md +95 -0
- web_dashboard/__init__.py +1 -0
- web_dashboard/app.js +9847 -0
- web_dashboard/avatars/amber-pulse.svg +15 -0
- web_dashboard/avatars/copper-grid.svg +15 -0
- web_dashboard/avatars/market-blue.svg +15 -0
- web_dashboard/avatars/rose-circuit.svg +15 -0
- web_dashboard/avatars/signal-green.svg +15 -0
- web_dashboard/avatars/slate-wave.svg +15 -0
- web_dashboard/avatars/teal-orbit.svg +16 -0
- web_dashboard/avatars/violet-node.svg +15 -0
- web_dashboard/favicon.svg +5 -0
- web_dashboard/image/qmt_deploy/image-10.png +0 -0
- web_dashboard/image/qmt_deploy/image-11.png +0 -0
- web_dashboard/image/qmt_deploy/image-12.png +0 -0
- web_dashboard/image/qmt_deploy/image-13.png +0 -0
- web_dashboard/image/qmt_deploy/image-14.png +0 -0
- web_dashboard/image/qmt_deploy/image-15.png +0 -0
- web_dashboard/image/qmt_deploy/image-16.png +0 -0
- web_dashboard/image/qmt_deploy/image-17.png +0 -0
- web_dashboard/image/qmt_deploy/image-18.png +0 -0
- web_dashboard/image/qmt_deploy/image-19.png +0 -0
- web_dashboard/image/qmt_deploy/image-20.png +0 -0
- web_dashboard/image/qmt_deploy/image-21.png +0 -0
- web_dashboard/image/qmt_deploy/image-4.png +0 -0
- web_dashboard/image/qmt_deploy/image-5.png +0 -0
- web_dashboard/image/qmt_deploy/image-6.png +0 -0
- web_dashboard/image/qmt_deploy/image-7.png +0 -0
- web_dashboard/image/qmt_deploy/image-8.png +0 -0
- web_dashboard/image/qmt_deploy/image-9.png +0 -0
- web_dashboard/image//321/211/320/220/320/252/321/207/320/244/320/270/321/206/320/270/320/261/321/205/342/225/235/320/237/321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/image-1.png +0 -0
- web_dashboard/image//321/211/320/220/320/252/321/207/320/244/320/270/321/206/320/270/320/261/321/205/342/225/235/320/237/321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/image-2.png +0 -0
- web_dashboard/image//321/211/320/220/320/252/321/207/320/244/320/270/321/206/320/270/320/261/321/205/342/225/235/320/237/321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/image-3.png +0 -0
- web_dashboard/image//321/211/320/220/320/252/321/207/320/244/320/270/321/206/320/270/320/261/321/205/342/225/235/320/237/321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/image.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783479325179.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783479745262.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783480178700.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783480428759.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783489807217.png +0 -0
- web_dashboard/image//321/211/320/223/320/270/321/207/342/225/234/342/226/223/321/206/320/234/320/227/321/205/320/235/320/247/1783490503491.png +0 -0
- web_dashboard/index.html +2317 -0
- web_dashboard/styles.css +7817 -0
- web_dashboard/vendor/mermaid.min.js +2029 -0
cfquant/protocol.py
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
import base64
|
|
3
|
+
import json
|
|
4
|
+
import math
|
|
5
|
+
import time
|
|
6
|
+
import uuid
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
PROTOCOL_VERSION = 1
|
|
10
|
+
MESSAGE_PREFIX = "cfquant:"
|
|
11
|
+
_pd = None
|
|
12
|
+
_pd_loaded = False
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def now_ms():
|
|
16
|
+
return int(time.time() * 1000)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def new_id(prefix="req"):
|
|
20
|
+
return "%s_%s_%s" % (prefix, now_ms(), uuid.uuid4().hex[:12])
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def dumps_message(payload):
|
|
24
|
+
data = dict(payload)
|
|
25
|
+
data.setdefault("protocol", "cfquant")
|
|
26
|
+
data.setdefault("version", PROTOCOL_VERSION)
|
|
27
|
+
data.setdefault("ts", now_ms())
|
|
28
|
+
return MESSAGE_PREFIX + json.dumps(data, ensure_ascii=False, separators=(",", ":"))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def loads_message(raw):
|
|
32
|
+
if isinstance(raw, bytes):
|
|
33
|
+
raw = raw.decode("utf-8", errors="replace")
|
|
34
|
+
if not isinstance(raw, str):
|
|
35
|
+
return None
|
|
36
|
+
if "|" in raw:
|
|
37
|
+
_, raw = raw.split("|", 1)
|
|
38
|
+
if not raw.startswith(MESSAGE_PREFIX):
|
|
39
|
+
return None
|
|
40
|
+
try:
|
|
41
|
+
data = json.loads(raw[len(MESSAGE_PREFIX):])
|
|
42
|
+
except Exception:
|
|
43
|
+
return None
|
|
44
|
+
if data.get("protocol") != "cfquant":
|
|
45
|
+
return None
|
|
46
|
+
return data
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def pack_request(action, params=None, reply_channel=None, client_id=None, request_id=None, timeout=None):
|
|
50
|
+
payload = {
|
|
51
|
+
"type": "request",
|
|
52
|
+
"id": request_id or new_id("req"),
|
|
53
|
+
"action": action,
|
|
54
|
+
"params": params or {},
|
|
55
|
+
"reply_channel": reply_channel,
|
|
56
|
+
"client_id": client_id,
|
|
57
|
+
}
|
|
58
|
+
if timeout is not None:
|
|
59
|
+
payload["timeout"] = float(timeout)
|
|
60
|
+
return dumps_message(payload)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def pack_response(request_id, ok=True, result=None, error=None, meta=None):
|
|
64
|
+
return dumps_message({
|
|
65
|
+
"type": "response",
|
|
66
|
+
"id": request_id,
|
|
67
|
+
"ok": bool(ok),
|
|
68
|
+
"result": encode_value(result),
|
|
69
|
+
"error": encode_error(error),
|
|
70
|
+
"meta": meta or {},
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def pack_event(event, data=None, client_id=None, subscription_id=None, meta=None):
|
|
75
|
+
return dumps_message({
|
|
76
|
+
"type": "event",
|
|
77
|
+
"event": event,
|
|
78
|
+
"client_id": client_id,
|
|
79
|
+
"subscription_id": subscription_id,
|
|
80
|
+
"data": encode_value(data),
|
|
81
|
+
"meta": meta or {},
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def encode_error(error):
|
|
86
|
+
if error is None:
|
|
87
|
+
return None
|
|
88
|
+
if isinstance(error, dict):
|
|
89
|
+
return error
|
|
90
|
+
return {
|
|
91
|
+
"type": type(error).__name__,
|
|
92
|
+
"message": str(error),
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def encode_value(value):
|
|
97
|
+
if value is None or isinstance(value, (str, bool, int)):
|
|
98
|
+
return value
|
|
99
|
+
if isinstance(value, float):
|
|
100
|
+
if math.isnan(value) or math.isinf(value):
|
|
101
|
+
return None
|
|
102
|
+
return value
|
|
103
|
+
if isinstance(value, bytes):
|
|
104
|
+
return {
|
|
105
|
+
"__cf_type__": "bytes",
|
|
106
|
+
"data": base64.b64encode(value).decode("ascii"),
|
|
107
|
+
}
|
|
108
|
+
if isinstance(value, dict):
|
|
109
|
+
return {str(k): encode_value(v) for k, v in value.items()}
|
|
110
|
+
if isinstance(value, (list, tuple, set)):
|
|
111
|
+
return [encode_value(v) for v in value]
|
|
112
|
+
if _looks_like_dataframe(value):
|
|
113
|
+
return _encode_dataframe(value)
|
|
114
|
+
if _looks_like_series(value):
|
|
115
|
+
return _encode_series(value)
|
|
116
|
+
pd = _get_pandas()
|
|
117
|
+
if pd is not None and isinstance(value, pd.DataFrame):
|
|
118
|
+
return _encode_dataframe(value)
|
|
119
|
+
if pd is not None and isinstance(value, pd.Series):
|
|
120
|
+
return _encode_series(value)
|
|
121
|
+
if hasattr(value, "__dict__"):
|
|
122
|
+
return {
|
|
123
|
+
"__cf_type__": "object",
|
|
124
|
+
"class": type(value).__name__,
|
|
125
|
+
"attrs": encode_value(vars(value)),
|
|
126
|
+
}
|
|
127
|
+
return str(value)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _get_pandas():
|
|
131
|
+
global _pd, _pd_loaded
|
|
132
|
+
if _pd_loaded:
|
|
133
|
+
return _pd
|
|
134
|
+
_pd_loaded = True
|
|
135
|
+
try:
|
|
136
|
+
import pandas as pd
|
|
137
|
+
_pd = pd
|
|
138
|
+
except Exception:
|
|
139
|
+
_pd = None
|
|
140
|
+
return _pd
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def _looks_like_dataframe(value):
|
|
144
|
+
return (
|
|
145
|
+
hasattr(value, "columns")
|
|
146
|
+
and hasattr(value, "index")
|
|
147
|
+
and hasattr(value, "values")
|
|
148
|
+
and hasattr(value, "to_dict")
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _looks_like_series(value):
|
|
153
|
+
return (
|
|
154
|
+
hasattr(value, "index")
|
|
155
|
+
and hasattr(value, "values")
|
|
156
|
+
and hasattr(value, "name")
|
|
157
|
+
and not hasattr(value, "columns")
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def _clean_cell(value):
|
|
162
|
+
if value is None:
|
|
163
|
+
return None
|
|
164
|
+
if isinstance(value, float) and (math.isnan(value) or math.isinf(value)):
|
|
165
|
+
return None
|
|
166
|
+
return encode_value(value)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def _encode_dataframe(value):
|
|
170
|
+
try:
|
|
171
|
+
raw_rows = value.values.tolist()
|
|
172
|
+
except Exception:
|
|
173
|
+
raw_rows = []
|
|
174
|
+
rows = []
|
|
175
|
+
for row in raw_rows:
|
|
176
|
+
rows.append([_clean_cell(v) for v in row])
|
|
177
|
+
index_name = getattr(getattr(value, "index", None), "name", None)
|
|
178
|
+
return {
|
|
179
|
+
"__cf_type__": "dataframe",
|
|
180
|
+
"columns": [str(c) for c in getattr(value, "columns", [])],
|
|
181
|
+
"index": [str(i) for i in getattr(value, "index", [])],
|
|
182
|
+
"data": rows,
|
|
183
|
+
"index_name": str(index_name) if index_name is not None else None,
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _encode_series(value):
|
|
188
|
+
try:
|
|
189
|
+
raw_values = value.values.tolist()
|
|
190
|
+
except Exception:
|
|
191
|
+
raw_values = []
|
|
192
|
+
return {
|
|
193
|
+
"__cf_type__": "series",
|
|
194
|
+
"index": [str(i) for i in getattr(value, "index", [])],
|
|
195
|
+
"data": [_clean_cell(v) for v in raw_values],
|
|
196
|
+
"name": str(value.name) if getattr(value, "name", None) is not None else None,
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def decode_value(value):
|
|
201
|
+
if isinstance(value, list):
|
|
202
|
+
return [decode_value(v) for v in value]
|
|
203
|
+
if not isinstance(value, dict):
|
|
204
|
+
return value
|
|
205
|
+
|
|
206
|
+
value_type = value.get("__cf_type__")
|
|
207
|
+
if value_type == "bytes":
|
|
208
|
+
return base64.b64decode(value.get("data", ""))
|
|
209
|
+
if value_type == "dataframe":
|
|
210
|
+
import pandas as pd
|
|
211
|
+
df = pd.DataFrame(value.get("data", []), columns=value.get("columns", []))
|
|
212
|
+
index = value.get("index", [])
|
|
213
|
+
if len(index) == len(df):
|
|
214
|
+
df.index = index
|
|
215
|
+
if value.get("index_name"):
|
|
216
|
+
df.index.name = value.get("index_name")
|
|
217
|
+
return df
|
|
218
|
+
if value_type == "series":
|
|
219
|
+
import pandas as pd
|
|
220
|
+
return pd.Series(
|
|
221
|
+
[decode_value(v) for v in value.get("data", [])],
|
|
222
|
+
index=value.get("index", []),
|
|
223
|
+
name=value.get("name"),
|
|
224
|
+
)
|
|
225
|
+
if value_type == "object":
|
|
226
|
+
return SimpleObject(**decode_value(value.get("attrs", {})))
|
|
227
|
+
return {k: decode_value(v) for k, v in value.items()}
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
class SimpleObject(object):
|
|
231
|
+
def __init__(self, **kwargs):
|
|
232
|
+
self.__dict__.update(kwargs)
|
|
233
|
+
|
|
234
|
+
def __repr__(self):
|
|
235
|
+
return "%s(%s)" % (
|
|
236
|
+
type(self).__name__,
|
|
237
|
+
", ".join("%s=%r" % item for item in sorted(self.__dict__.items())),
|
|
238
|
+
)
|