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.
Files changed (90) hide show
  1. LTtx/__init__.py +2 -0
  2. LTtx/tx/Config.txt +8 -0
  3. LTtx/tx/LTtx_server.py +1177 -0
  4. LTtx/tx/__init__.py +5 -0
  5. LTtx/tx/tx.py +1935 -0
  6. cfquant/__init__.py +26 -0
  7. cfquant/account_routing.py +119 -0
  8. cfquant/channels.py +76 -0
  9. cfquant/cli.py +266 -0
  10. cfquant/client.py +365 -0
  11. cfquant/config.py +86 -0
  12. cfquant/hub.py +304 -0
  13. cfquant/logging_i18n.py +348 -0
  14. cfquant/normal_bridge.py +676 -0
  15. cfquant/pipe_bridge.py +249 -0
  16. cfquant/pipe_client.py +223 -0
  17. cfquant/pipe_hub.py +602 -0
  18. cfquant/pipe_transport.py +493 -0
  19. cfquant/protocol.py +238 -0
  20. cfquant/qmt_bridge.py +1081 -0
  21. cfquant/runtime_report.py +334 -0
  22. cfquant/tx.py +1898 -0
  23. cfquant/tx_trade_bridge.py +1905 -0
  24. cfquant/version.py +5 -0
  25. cfquant/xtconstant.py +262 -0
  26. cfquant/xtdata.py +462 -0
  27. cfquant/xttrader.py +955 -0
  28. cfquant/xttype.py +586 -0
  29. cfquant-0.2.0.dist-info/LICENSE +21 -0
  30. cfquant-0.2.0.dist-info/METADATA +144 -0
  31. cfquant-0.2.0.dist-info/RECORD +90 -0
  32. cfquant-0.2.0.dist-info/WHEEL +5 -0
  33. cfquant-0.2.0.dist-info/entry_points.txt +4 -0
  34. cfquant-0.2.0.dist-info/top_level.txt +6 -0
  35. cfquant_pipe_hub.py +45 -0
  36. cfquant_web_server.py +12137 -0
  37. qmt_scripts/CFQUANT.py +507 -0
  38. qmt_scripts/CFQUANT_CTYPE_ALL_LOWLAT.py +830 -0
  39. qmt_scripts/CFQUANT_LITE.py +4928 -0
  40. qmt_scripts/CFQUANT_TRADE_LOWLAT.py +382 -0
  41. qmt_scripts/__init__.py +1 -0
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. web_dashboard/__init__.py +1 -0
  50. web_dashboard/app.js +9847 -0
  51. web_dashboard/avatars/amber-pulse.svg +15 -0
  52. web_dashboard/avatars/copper-grid.svg +15 -0
  53. web_dashboard/avatars/market-blue.svg +15 -0
  54. web_dashboard/avatars/rose-circuit.svg +15 -0
  55. web_dashboard/avatars/signal-green.svg +15 -0
  56. web_dashboard/avatars/slate-wave.svg +15 -0
  57. web_dashboard/avatars/teal-orbit.svg +16 -0
  58. web_dashboard/avatars/violet-node.svg +15 -0
  59. web_dashboard/favicon.svg +5 -0
  60. web_dashboard/image/qmt_deploy/image-10.png +0 -0
  61. web_dashboard/image/qmt_deploy/image-11.png +0 -0
  62. web_dashboard/image/qmt_deploy/image-12.png +0 -0
  63. web_dashboard/image/qmt_deploy/image-13.png +0 -0
  64. web_dashboard/image/qmt_deploy/image-14.png +0 -0
  65. web_dashboard/image/qmt_deploy/image-15.png +0 -0
  66. web_dashboard/image/qmt_deploy/image-16.png +0 -0
  67. web_dashboard/image/qmt_deploy/image-17.png +0 -0
  68. web_dashboard/image/qmt_deploy/image-18.png +0 -0
  69. web_dashboard/image/qmt_deploy/image-19.png +0 -0
  70. web_dashboard/image/qmt_deploy/image-20.png +0 -0
  71. web_dashboard/image/qmt_deploy/image-21.png +0 -0
  72. web_dashboard/image/qmt_deploy/image-4.png +0 -0
  73. web_dashboard/image/qmt_deploy/image-5.png +0 -0
  74. web_dashboard/image/qmt_deploy/image-6.png +0 -0
  75. web_dashboard/image/qmt_deploy/image-7.png +0 -0
  76. web_dashboard/image/qmt_deploy/image-8.png +0 -0
  77. web_dashboard/image/qmt_deploy/image-9.png +0 -0
  78. 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
  79. 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
  80. 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
  81. 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
  82. 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
  83. 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
  84. 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
  85. 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
  86. 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
  87. 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
  88. web_dashboard/index.html +2317 -0
  89. web_dashboard/styles.css +7817 -0
  90. web_dashboard/vendor/mermaid.min.js +2029 -0
@@ -0,0 +1,382 @@
1
+ #coding:gbk
2
+ #! /usr/bin/python
3
+
4
+ import os
5
+ import sys
6
+ import importlib
7
+ import io
8
+ import json
9
+
10
+
11
+ _trade_bridge = None
12
+ DEFAULT_ACCOUNT_ID = ""
13
+ USER_BRIDGE_ID = "default"
14
+ BRIDGE_ID = os.environ.get("CFQUANT_BRIDGE_ID", USER_BRIDGE_ID)
15
+ RUNTIME_CONFIG = {}
16
+ RUNTIME_CHANNELS = {}
17
+ QMT_MARKET = os.environ.get("CFQUANT_MARKET", "").strip().upper()
18
+
19
+
20
+ def _entry_file_path():
21
+ path = globals().get("__file__") or ""
22
+ path = str(path or "").strip()
23
+ if path and not path.startswith("<"):
24
+ try:
25
+ return os.path.abspath(path)
26
+ except Exception:
27
+ return path
28
+ return ""
29
+
30
+
31
+ def _entry_base_dir():
32
+ entry_file = _entry_file_path()
33
+ if entry_file:
34
+ return os.path.dirname(entry_file)
35
+ for name in ("CFQUANT_QMT_SCRIPT_DIR", "CFQUANT_SCRIPT_DIR", "CFQUANT_ENTRY_DIR"):
36
+ path = str(os.environ.get(name) or "").strip()
37
+ if path and os.path.isdir(path):
38
+ return os.path.abspath(path)
39
+ try:
40
+ cwd = os.path.abspath(os.getcwd())
41
+ if (
42
+ os.path.isfile(os.path.join(cwd, "CFQUANT_TRADE_LOWLAT.py"))
43
+ or os.path.isfile(os.path.join(cwd, "cfquant_bridge_config.json"))
44
+ or os.path.isdir(os.path.join(cwd, "cfquant"))
45
+ ):
46
+ return cwd
47
+ except Exception:
48
+ pass
49
+ for path in sys.path:
50
+ path = str(path or "").strip()
51
+ if path and os.path.isdir(path):
52
+ base = os.path.abspath(path)
53
+ if (
54
+ os.path.isfile(os.path.join(base, "CFQUANT_TRADE_LOWLAT.py"))
55
+ or os.path.isfile(os.path.join(base, "cfquant_bridge_config.json"))
56
+ or os.path.isdir(os.path.join(base, "cfquant"))
57
+ ):
58
+ return base
59
+ try:
60
+ return os.path.abspath(os.getcwd())
61
+ except Exception:
62
+ return ""
63
+
64
+
65
+ def _runtime_config_paths():
66
+ try:
67
+ base_dir = _entry_base_dir()
68
+ parent_dir = os.path.dirname(base_dir)
69
+ candidates = []
70
+ env_path = os.environ.get("CFQUANT_BRIDGE_CONFIG_FILE")
71
+ if env_path:
72
+ candidates.append(env_path)
73
+ market = str(os.environ.get("CFQUANT_MARKET") or QMT_MARKET or "").strip().upper()
74
+ market_filenames = []
75
+ if market in ("SH", "SZ"):
76
+ market_filenames.append("cfquant_bridge_config_%s.json" % market)
77
+ if os.path.basename(base_dir).lower() == "python":
78
+ for filename in market_filenames:
79
+ candidates.append(os.path.join(parent_dir, "bin.x64", filename))
80
+ candidates.append(os.path.join(base_dir, filename))
81
+ candidates.append(os.path.join(parent_dir, "bin.x64", "cfquant_bridge_config.json"))
82
+ candidates.append(os.path.join(base_dir, "cfquant_bridge_config.json"))
83
+ else:
84
+ for filename in market_filenames:
85
+ candidates.append(os.path.join(base_dir, filename))
86
+ candidates.append(os.path.join(base_dir, "bin.x64", filename))
87
+ candidates.append(os.path.join(base_dir, "cfquant_bridge_config.json"))
88
+ candidates.append(os.path.join(base_dir, "bin.x64", "cfquant_bridge_config.json"))
89
+ for filename in market_filenames:
90
+ candidates.append(os.path.join(parent_dir, filename))
91
+ candidates.append(os.path.join(parent_dir, "cfquant_bridge_config.json"))
92
+ result = []
93
+ seen = set()
94
+ for path in candidates:
95
+ if not path:
96
+ continue
97
+ path = os.path.abspath(os.path.expandvars(os.path.expanduser(path)))
98
+ key = os.path.normcase(path)
99
+ if key in seen:
100
+ continue
101
+ seen.add(key)
102
+ result.append(path)
103
+ return result
104
+ except Exception:
105
+ return []
106
+
107
+
108
+ def _load_runtime_config():
109
+ for path in _runtime_config_paths():
110
+ if not os.path.isfile(path):
111
+ continue
112
+ for opener in (
113
+ lambda: io.open(path, "r", encoding="utf-8"),
114
+ lambda: open(path, "r"),
115
+ ):
116
+ try:
117
+ with opener() as f:
118
+ data = json.loads(f.read())
119
+ if isinstance(data, dict):
120
+ return data
121
+ except Exception:
122
+ pass
123
+ return {}
124
+
125
+
126
+ def _config_bool(value, default=True):
127
+ if isinstance(value, bool):
128
+ return value
129
+ if value is None:
130
+ return default
131
+ text = str(value).strip().lower()
132
+ if text in ("0", "false", "no", "off", "disable", "disabled", "closed", "close"):
133
+ return False
134
+ if text in ("1", "true", "yes", "on", "enable", "enabled", "open"):
135
+ return True
136
+ return default
137
+
138
+
139
+ def _env_allows_runtime_override(name, default_value=""):
140
+ value = str(os.environ.get(name) or "").strip()
141
+ if not value:
142
+ return True
143
+ if str(os.environ.get("%s_SOURCE" % name) or "").strip() == "cfquant_entry":
144
+ return True
145
+ return bool(default_value and value == default_value)
146
+
147
+
148
+ def _apply_runtime_config():
149
+ global BRIDGE_ID, RUNTIME_CONFIG, RUNTIME_CHANNELS, QMT_MARKET
150
+
151
+ data = _load_runtime_config()
152
+ RUNTIME_CONFIG = data
153
+ if not data:
154
+ return
155
+ if data.get("bridge_id") and _env_allows_runtime_override("CFQUANT_BRIDGE_ID", USER_BRIDGE_ID):
156
+ BRIDGE_ID = data.get("bridge_id")
157
+ if data.get("market"):
158
+ market = str(data.get("market") or "").strip().upper()
159
+ if market in ("SH", "SZ"):
160
+ QMT_MARKET = market
161
+ if not os.environ.get("CFQUANT_MARKET"):
162
+ os.environ["CFQUANT_MARKET"] = market
163
+ os.environ["CFQUANT_MARKET_SOURCE"] = "cfquant_entry"
164
+ channels = data.get("channels") or {}
165
+ if isinstance(channels, dict):
166
+ RUNTIME_CHANNELS = channels
167
+ if not os.environ.get("CFQUANT_QMT_LOG_LANGUAGE") and data.get("qmt_log_language"):
168
+ os.environ["CFQUANT_QMT_LOG_LANGUAGE"] = str(data.get("qmt_log_language") or "zh")
169
+ if not os.environ.get("CFQUANT_QMT_LOG_ENABLED") and "qmt_log_enabled" in data:
170
+ os.environ["CFQUANT_QMT_LOG_ENABLED"] = "1" if _config_bool(data.get("qmt_log_enabled"), True) else "0"
171
+
172
+
173
+ def _ensure_path():
174
+ try:
175
+ base_dir = _entry_base_dir()
176
+ parent_dir = os.path.dirname(base_dir)
177
+ env_paths = [p for p in os.environ.get("CFQUANT_PYTHONPATH", "").split(os.pathsep) if p]
178
+ if os.path.basename(base_dir).lower() == "python":
179
+ candidates = env_paths + [os.path.join(parent_dir, "bin.x64"), base_dir, parent_dir]
180
+ else:
181
+ candidates = env_paths + [
182
+ base_dir,
183
+ os.path.join(base_dir, "bin.x64"),
184
+ parent_dir,
185
+ os.path.join(parent_dir, "bin.x64"),
186
+ os.path.join(parent_dir, "python"),
187
+ ]
188
+ ordered = []
189
+ seen = set()
190
+ for path in candidates:
191
+ if not path or not os.path.isdir(path):
192
+ continue
193
+ path = os.path.abspath(path)
194
+ key = os.path.normcase(path)
195
+ if key in seen:
196
+ continue
197
+ seen.add(key)
198
+ ordered.append(path)
199
+ if ordered:
200
+ sys.path[:] = ordered + [
201
+ path for path in sys.path
202
+ if os.path.normcase(os.path.abspath(path or os.curdir)) not in seen
203
+ ]
204
+ except Exception:
205
+ pass
206
+
207
+
208
+ def _install_logging_compat():
209
+ """Keep this entry compatible with older cfquant packages in QMT."""
210
+ logging_module = importlib.import_module("cfquant.logging_i18n")
211
+
212
+ if not hasattr(logging_module, "normalize_log_language"):
213
+ def _normalize_log_language(value=None):
214
+ value = str(value or "").strip().lower()
215
+ return "en" if value in ("en", "english") else "zh"
216
+
217
+ logging_module.normalize_log_language = _normalize_log_language
218
+
219
+ if not hasattr(logging_module, "normalize_log_enabled"):
220
+ def _normalize_log_enabled(value=None):
221
+ if isinstance(value, bool):
222
+ return value
223
+ if value is None:
224
+ return True
225
+ text = str(value).strip().lower()
226
+ return text not in ("0", "false", "no", "off", "disable", "disabled", "closed", "close")
227
+
228
+ logging_module.normalize_log_enabled = _normalize_log_enabled
229
+
230
+ if not hasattr(logging_module, "_CFQUANT_COMPAT_LOG_LANGUAGE"):
231
+ logging_module._CFQUANT_COMPAT_LOG_LANGUAGE = ""
232
+ if not hasattr(logging_module, "_CFQUANT_COMPAT_LOG_ENABLED"):
233
+ logging_module._CFQUANT_COMPAT_LOG_ENABLED = None
234
+
235
+ if not hasattr(logging_module, "get_log_language"):
236
+ def _get_log_language():
237
+ if logging_module._CFQUANT_COMPAT_LOG_LANGUAGE:
238
+ return logging_module._CFQUANT_COMPAT_LOG_LANGUAGE
239
+ return logging_module.normalize_log_language(
240
+ os.environ.get("CFQUANT_QMT_LOG_LANGUAGE")
241
+ or os.environ.get("CFQUANT_LOG_LANGUAGE")
242
+ or "zh"
243
+ )
244
+
245
+ logging_module.get_log_language = _get_log_language
246
+
247
+ if not hasattr(logging_module, "set_log_language"):
248
+ def _set_log_language(value):
249
+ language = logging_module.normalize_log_language(value)
250
+ logging_module._CFQUANT_COMPAT_LOG_LANGUAGE = language
251
+ return language
252
+
253
+ logging_module.set_log_language = _set_log_language
254
+
255
+ if not hasattr(logging_module, "get_log_enabled"):
256
+ def _get_log_enabled():
257
+ if logging_module._CFQUANT_COMPAT_LOG_ENABLED is not None:
258
+ return bool(logging_module._CFQUANT_COMPAT_LOG_ENABLED)
259
+ return logging_module.normalize_log_enabled(
260
+ os.environ.get("CFQUANT_QMT_LOG_ENABLED")
261
+ or os.environ.get("CFQUANT_LOG_ENABLED")
262
+ or "1"
263
+ )
264
+
265
+ logging_module.get_log_enabled = _get_log_enabled
266
+
267
+ if not hasattr(logging_module, "set_log_enabled"):
268
+ def _set_log_enabled(value):
269
+ enabled = logging_module.normalize_log_enabled(value)
270
+ logging_module._CFQUANT_COMPAT_LOG_ENABLED = enabled
271
+ return enabled
272
+
273
+ logging_module.set_log_enabled = _set_log_enabled
274
+
275
+ if not hasattr(logging_module, "translate_log"):
276
+ def _translate_log(message, language=None):
277
+ return str(message)
278
+
279
+ logging_module.translate_log = _translate_log
280
+
281
+ return logging_module
282
+
283
+
284
+ _ensure_path()
285
+ _apply_runtime_config()
286
+
287
+ _logging_i18n = _install_logging_compat()
288
+ get_log_enabled = _logging_i18n.get_log_enabled
289
+ translate_log = _logging_i18n.translate_log
290
+
291
+ from cfquant import __version__ as _ENTRY_VERSION
292
+
293
+
294
+ def _print_log(message):
295
+ if get_log_enabled():
296
+ print(translate_log(message))
297
+
298
+
299
+ def _load_bridge_starter():
300
+ import cfquant.tx_trade_bridge as tx_trade_bridge
301
+
302
+ try:
303
+ tx_trade_bridge = importlib.reload(tx_trade_bridge)
304
+ except Exception as e:
305
+ _print_log("tx trade bridge reload failed:%s" % e)
306
+ return tx_trade_bridge.start_tx_trade_bridge
307
+
308
+
309
+ start_tx_trade_bridge = _load_bridge_starter()
310
+
311
+ from cfquant.channels import channels_for_bridge, normalize_bridge_id
312
+
313
+ BRIDGE_ID = normalize_bridge_id(BRIDGE_ID)
314
+ QMT_MARKET = str(QMT_MARKET or os.environ.get("CFQUANT_MARKET") or RUNTIME_CONFIG.get("market") or "").strip().upper()
315
+ if QMT_MARKET not in ("SH", "SZ"):
316
+ QMT_MARKET = ""
317
+ if not os.environ.get("CFQUANT_BRIDGE_ID"):
318
+ os.environ["CFQUANT_BRIDGE_ID"] = BRIDGE_ID
319
+ os.environ["CFQUANT_BRIDGE_ID_SOURCE"] = "cfquant_entry"
320
+ if QMT_MARKET and not os.environ.get("CFQUANT_MARKET"):
321
+ os.environ["CFQUANT_MARKET"] = QMT_MARKET
322
+ os.environ["CFQUANT_MARKET_SOURCE"] = "cfquant_entry"
323
+ BRIDGE_CHANNELS = channels_for_bridge(BRIDGE_ID)
324
+ _trade_channel_value = RUNTIME_CHANNELS.get("trade") or RUNTIME_CONFIG.get("trade_channel")
325
+ if _trade_channel_value:
326
+ BRIDGE_CHANNELS["trade"] = str(_trade_channel_value).strip()
327
+
328
+ _trade_bridge = start_tx_trade_bridge(
329
+ None,
330
+ ip="127.0.0.1",
331
+ port=2049,
332
+ token="LTtx",
333
+ request_channel=BRIDGE_CHANNELS["trade"],
334
+ bridge_id=BRIDGE_ID,
335
+ account_id=DEFAULT_ACCOUNT_ID,
336
+ show=True,
337
+ )
338
+ _print_log("cfquant lowlat trade bridge module loaded")
339
+ _print_log("cfquant lowlat entry version:%s" % _ENTRY_VERSION)
340
+ _print_log("cfquant bridge id:%s trade_channel:%s" % (BRIDGE_ID, BRIDGE_CHANNELS["trade"]))
341
+ if QMT_MARKET:
342
+ _print_log("cfquant lowlat market route market:%s bridge_id:%s" % (QMT_MARKET, BRIDGE_ID))
343
+
344
+
345
+ def _attach_trade_status_extra():
346
+ if not _trade_bridge:
347
+ return
348
+ original_status_extra = _trade_bridge._status_extra
349
+
350
+ def status_extra_with_market():
351
+ data = original_status_extra()
352
+ data.update({
353
+ "qmt_runtime_market": QMT_MARKET,
354
+ "qmt_runtime_market_role": RUNTIME_CONFIG.get("market_role") or ("trade" if QMT_MARKET else ""),
355
+ "qmt_runtime_market_parent_bridge_id": RUNTIME_CONFIG.get("market_route_parent_bridge_id") or "",
356
+ })
357
+ return data
358
+
359
+ _trade_bridge._status_extra = status_extra_with_market
360
+
361
+
362
+ _attach_trade_status_extra()
363
+
364
+
365
+ def init(ContextInfo):
366
+ if _trade_bridge:
367
+ _trade_bridge.set_context(ContextInfo)
368
+ _print_log("cfquant lowlat trade context ready version:%s" % _ENTRY_VERSION)
369
+ _trade_bridge.run_forever(sleep_seconds=0.001)
370
+
371
+
372
+ def handlebar(ContextInfo):
373
+ pass
374
+
375
+
376
+ def stop(ContextInfo):
377
+ global _trade_bridge
378
+
379
+ if _trade_bridge:
380
+ _trade_bridge.close()
381
+ _trade_bridge = None
382
+ _print_log("cfquant lowlat trade bridge stopped")
@@ -0,0 +1 @@
1
+ """QMT-side entry scripts distributed with cfquant."""