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,436 @@
1
+ #coding:gbk
2
+ #! /usr/bin/python
3
+ # Embedded same-account market entry. Do not load parent entry files at runtime.
4
+
5
+ import os as _cfquant_market_os
6
+
7
+ _CFQUANT_MARKET = "SH"
8
+ _CFQUANT_CONFIG_FILENAME = "cfquant_bridge_config_SH.json"
9
+
10
+
11
+ def _cfquant_market_base_dir():
12
+ path = globals().get("__file__") or ""
13
+ if path and not str(path).startswith("<"):
14
+ try:
15
+ return _cfquant_market_os.path.dirname(_cfquant_market_os.path.abspath(path))
16
+ except Exception:
17
+ return ""
18
+ try:
19
+ return _cfquant_market_os.path.abspath(_cfquant_market_os.getcwd())
20
+ except Exception:
21
+ return ""
22
+
23
+
24
+ def _cfquant_market_config_path():
25
+ base = _cfquant_market_base_dir()
26
+ parent = _cfquant_market_os.path.dirname(base) if base else ""
27
+ if base and _cfquant_market_os.path.basename(base).lower() == "python" and parent:
28
+ return _cfquant_market_os.path.join(parent, "bin.x64", _CFQUANT_CONFIG_FILENAME)
29
+ if base:
30
+ return _cfquant_market_os.path.join(base, _CFQUANT_CONFIG_FILENAME)
31
+ return _CFQUANT_CONFIG_FILENAME
32
+
33
+
34
+ _cfquant_market_os.environ["CFQUANT_MARKET"] = _CFQUANT_MARKET
35
+ _cfquant_market_os.environ["CFQUANT_MARKET_SOURCE"] = "cfquant_market_entry"
36
+
37
+
38
+ def _cfquant_market_should_set_config_path():
39
+ current = str(_cfquant_market_os.environ.get("CFQUANT_BRIDGE_CONFIG_FILE") or "").strip()
40
+ if not current:
41
+ return True
42
+ source = str(_cfquant_market_os.environ.get("CFQUANT_BRIDGE_CONFIG_FILE_SOURCE") or "").strip()
43
+ if source in ("cfquant_market_entry", "cfquant_entry"):
44
+ return True
45
+ current_name = _cfquant_market_os.path.basename(current).lower()
46
+ market_names = ("cfquant_bridge_config_sh.json", "cfquant_bridge_config_sz.json")
47
+ return current_name in market_names and current_name != _CFQUANT_CONFIG_FILENAME.lower()
48
+
49
+
50
+ if _cfquant_market_should_set_config_path():
51
+ _cfquant_market_os.environ["CFQUANT_BRIDGE_CONFIG_FILE"] = _cfquant_market_config_path()
52
+ _cfquant_market_os.environ["CFQUANT_BRIDGE_CONFIG_FILE_SOURCE"] = "cfquant_market_entry"
53
+
54
+ # Embedded market entry: CFQUANT_TRADE_LOWLAT_SH.py
55
+ #coding:gbk
56
+ #! /usr/bin/python
57
+
58
+ import os
59
+ import sys
60
+ import importlib
61
+ import io
62
+ import json
63
+
64
+
65
+ _trade_bridge = None
66
+ DEFAULT_ACCOUNT_ID = ""
67
+ USER_BRIDGE_ID = "default"
68
+ BRIDGE_ID = os.environ.get("CFQUANT_BRIDGE_ID", USER_BRIDGE_ID)
69
+ RUNTIME_CONFIG = {}
70
+ RUNTIME_CHANNELS = {}
71
+ QMT_MARKET = os.environ.get("CFQUANT_MARKET", "").strip().upper()
72
+
73
+
74
+ def _entry_file_path():
75
+ path = globals().get("__file__") or ""
76
+ path = str(path or "").strip()
77
+ if path and not path.startswith("<"):
78
+ try:
79
+ return os.path.abspath(path)
80
+ except Exception:
81
+ return path
82
+ return ""
83
+
84
+
85
+ def _entry_base_dir():
86
+ entry_file = _entry_file_path()
87
+ if entry_file:
88
+ return os.path.dirname(entry_file)
89
+ for name in ("CFQUANT_QMT_SCRIPT_DIR", "CFQUANT_SCRIPT_DIR", "CFQUANT_ENTRY_DIR"):
90
+ path = str(os.environ.get(name) or "").strip()
91
+ if path and os.path.isdir(path):
92
+ return os.path.abspath(path)
93
+ try:
94
+ cwd = os.path.abspath(os.getcwd())
95
+ if (
96
+ os.path.isfile(os.path.join(cwd, "CFQUANT_TRADE_LOWLAT_SH.py"))
97
+ or os.path.isfile(os.path.join(cwd, "cfquant_bridge_config.json"))
98
+ or os.path.isdir(os.path.join(cwd, "cfquant"))
99
+ ):
100
+ return cwd
101
+ except Exception:
102
+ pass
103
+ for path in sys.path:
104
+ path = str(path or "").strip()
105
+ if path and os.path.isdir(path):
106
+ base = os.path.abspath(path)
107
+ if (
108
+ os.path.isfile(os.path.join(base, "CFQUANT_TRADE_LOWLAT_SH.py"))
109
+ or os.path.isfile(os.path.join(base, "cfquant_bridge_config.json"))
110
+ or os.path.isdir(os.path.join(base, "cfquant"))
111
+ ):
112
+ return base
113
+ try:
114
+ return os.path.abspath(os.getcwd())
115
+ except Exception:
116
+ return ""
117
+
118
+
119
+ def _runtime_config_paths():
120
+ try:
121
+ base_dir = _entry_base_dir()
122
+ parent_dir = os.path.dirname(base_dir)
123
+ candidates = []
124
+ env_path = os.environ.get("CFQUANT_BRIDGE_CONFIG_FILE")
125
+ if env_path:
126
+ candidates.append(env_path)
127
+ market = str(os.environ.get("CFQUANT_MARKET") or QMT_MARKET or "").strip().upper()
128
+ market_filenames = []
129
+ if market in ("SH", "SZ"):
130
+ market_filenames.append("cfquant_bridge_config_%s.json" % market)
131
+ if os.path.basename(base_dir).lower() == "python":
132
+ for filename in market_filenames:
133
+ candidates.append(os.path.join(parent_dir, "bin.x64", filename))
134
+ candidates.append(os.path.join(base_dir, filename))
135
+ candidates.append(os.path.join(parent_dir, "bin.x64", "cfquant_bridge_config.json"))
136
+ candidates.append(os.path.join(base_dir, "cfquant_bridge_config.json"))
137
+ else:
138
+ for filename in market_filenames:
139
+ candidates.append(os.path.join(base_dir, filename))
140
+ candidates.append(os.path.join(base_dir, "bin.x64", filename))
141
+ candidates.append(os.path.join(base_dir, "cfquant_bridge_config.json"))
142
+ candidates.append(os.path.join(base_dir, "bin.x64", "cfquant_bridge_config.json"))
143
+ for filename in market_filenames:
144
+ candidates.append(os.path.join(parent_dir, filename))
145
+ candidates.append(os.path.join(parent_dir, "cfquant_bridge_config.json"))
146
+ result = []
147
+ seen = set()
148
+ for path in candidates:
149
+ if not path:
150
+ continue
151
+ path = os.path.abspath(os.path.expandvars(os.path.expanduser(path)))
152
+ key = os.path.normcase(path)
153
+ if key in seen:
154
+ continue
155
+ seen.add(key)
156
+ result.append(path)
157
+ return result
158
+ except Exception:
159
+ return []
160
+
161
+
162
+ def _load_runtime_config():
163
+ for path in _runtime_config_paths():
164
+ if not os.path.isfile(path):
165
+ continue
166
+ for opener in (
167
+ lambda: io.open(path, "r", encoding="utf-8"),
168
+ lambda: open(path, "r"),
169
+ ):
170
+ try:
171
+ with opener() as f:
172
+ data = json.loads(f.read())
173
+ if isinstance(data, dict):
174
+ return data
175
+ except Exception:
176
+ pass
177
+ return {}
178
+
179
+
180
+ def _config_bool(value, default=True):
181
+ if isinstance(value, bool):
182
+ return value
183
+ if value is None:
184
+ return default
185
+ text = str(value).strip().lower()
186
+ if text in ("0", "false", "no", "off", "disable", "disabled", "closed", "close"):
187
+ return False
188
+ if text in ("1", "true", "yes", "on", "enable", "enabled", "open"):
189
+ return True
190
+ return default
191
+
192
+
193
+ def _env_allows_runtime_override(name, default_value=""):
194
+ value = str(os.environ.get(name) or "").strip()
195
+ if not value:
196
+ return True
197
+ if str(os.environ.get("%s_SOURCE" % name) or "").strip() == "cfquant_entry":
198
+ return True
199
+ return bool(default_value and value == default_value)
200
+
201
+
202
+ def _apply_runtime_config():
203
+ global BRIDGE_ID, RUNTIME_CONFIG, RUNTIME_CHANNELS, QMT_MARKET
204
+
205
+ data = _load_runtime_config()
206
+ RUNTIME_CONFIG = data
207
+ if not data:
208
+ return
209
+ if data.get("bridge_id") and _env_allows_runtime_override("CFQUANT_BRIDGE_ID", USER_BRIDGE_ID):
210
+ BRIDGE_ID = data.get("bridge_id")
211
+ if data.get("market"):
212
+ market = str(data.get("market") or "").strip().upper()
213
+ if market in ("SH", "SZ"):
214
+ QMT_MARKET = market
215
+ if not os.environ.get("CFQUANT_MARKET"):
216
+ os.environ["CFQUANT_MARKET"] = market
217
+ os.environ["CFQUANT_MARKET_SOURCE"] = "cfquant_entry"
218
+ channels = data.get("channels") or {}
219
+ if isinstance(channels, dict):
220
+ RUNTIME_CHANNELS = channels
221
+ if not os.environ.get("CFQUANT_QMT_LOG_LANGUAGE") and data.get("qmt_log_language"):
222
+ os.environ["CFQUANT_QMT_LOG_LANGUAGE"] = str(data.get("qmt_log_language") or "zh")
223
+ if not os.environ.get("CFQUANT_QMT_LOG_ENABLED") and "qmt_log_enabled" in data:
224
+ os.environ["CFQUANT_QMT_LOG_ENABLED"] = "1" if _config_bool(data.get("qmt_log_enabled"), True) else "0"
225
+
226
+
227
+ def _ensure_path():
228
+ try:
229
+ base_dir = _entry_base_dir()
230
+ parent_dir = os.path.dirname(base_dir)
231
+ env_paths = [p for p in os.environ.get("CFQUANT_PYTHONPATH", "").split(os.pathsep) if p]
232
+ if os.path.basename(base_dir).lower() == "python":
233
+ candidates = env_paths + [os.path.join(parent_dir, "bin.x64"), base_dir, parent_dir]
234
+ else:
235
+ candidates = env_paths + [
236
+ base_dir,
237
+ os.path.join(base_dir, "bin.x64"),
238
+ parent_dir,
239
+ os.path.join(parent_dir, "bin.x64"),
240
+ os.path.join(parent_dir, "python"),
241
+ ]
242
+ ordered = []
243
+ seen = set()
244
+ for path in candidates:
245
+ if not path or not os.path.isdir(path):
246
+ continue
247
+ path = os.path.abspath(path)
248
+ key = os.path.normcase(path)
249
+ if key in seen:
250
+ continue
251
+ seen.add(key)
252
+ ordered.append(path)
253
+ if ordered:
254
+ sys.path[:] = ordered + [
255
+ path for path in sys.path
256
+ if os.path.normcase(os.path.abspath(path or os.curdir)) not in seen
257
+ ]
258
+ except Exception:
259
+ pass
260
+
261
+
262
+ def _install_logging_compat():
263
+ """Keep this entry compatible with older cfquant packages in QMT."""
264
+ logging_module = importlib.import_module("cfquant.logging_i18n")
265
+
266
+ if not hasattr(logging_module, "normalize_log_language"):
267
+ def _normalize_log_language(value=None):
268
+ value = str(value or "").strip().lower()
269
+ return "en" if value in ("en", "english") else "zh"
270
+
271
+ logging_module.normalize_log_language = _normalize_log_language
272
+
273
+ if not hasattr(logging_module, "normalize_log_enabled"):
274
+ def _normalize_log_enabled(value=None):
275
+ if isinstance(value, bool):
276
+ return value
277
+ if value is None:
278
+ return True
279
+ text = str(value).strip().lower()
280
+ return text not in ("0", "false", "no", "off", "disable", "disabled", "closed", "close")
281
+
282
+ logging_module.normalize_log_enabled = _normalize_log_enabled
283
+
284
+ if not hasattr(logging_module, "_CFQUANT_COMPAT_LOG_LANGUAGE"):
285
+ logging_module._CFQUANT_COMPAT_LOG_LANGUAGE = ""
286
+ if not hasattr(logging_module, "_CFQUANT_COMPAT_LOG_ENABLED"):
287
+ logging_module._CFQUANT_COMPAT_LOG_ENABLED = None
288
+
289
+ if not hasattr(logging_module, "get_log_language"):
290
+ def _get_log_language():
291
+ if logging_module._CFQUANT_COMPAT_LOG_LANGUAGE:
292
+ return logging_module._CFQUANT_COMPAT_LOG_LANGUAGE
293
+ return logging_module.normalize_log_language(
294
+ os.environ.get("CFQUANT_QMT_LOG_LANGUAGE")
295
+ or os.environ.get("CFQUANT_LOG_LANGUAGE")
296
+ or "zh"
297
+ )
298
+
299
+ logging_module.get_log_language = _get_log_language
300
+
301
+ if not hasattr(logging_module, "set_log_language"):
302
+ def _set_log_language(value):
303
+ language = logging_module.normalize_log_language(value)
304
+ logging_module._CFQUANT_COMPAT_LOG_LANGUAGE = language
305
+ return language
306
+
307
+ logging_module.set_log_language = _set_log_language
308
+
309
+ if not hasattr(logging_module, "get_log_enabled"):
310
+ def _get_log_enabled():
311
+ if logging_module._CFQUANT_COMPAT_LOG_ENABLED is not None:
312
+ return bool(logging_module._CFQUANT_COMPAT_LOG_ENABLED)
313
+ return logging_module.normalize_log_enabled(
314
+ os.environ.get("CFQUANT_QMT_LOG_ENABLED")
315
+ or os.environ.get("CFQUANT_LOG_ENABLED")
316
+ or "1"
317
+ )
318
+
319
+ logging_module.get_log_enabled = _get_log_enabled
320
+
321
+ if not hasattr(logging_module, "set_log_enabled"):
322
+ def _set_log_enabled(value):
323
+ enabled = logging_module.normalize_log_enabled(value)
324
+ logging_module._CFQUANT_COMPAT_LOG_ENABLED = enabled
325
+ return enabled
326
+
327
+ logging_module.set_log_enabled = _set_log_enabled
328
+
329
+ if not hasattr(logging_module, "translate_log"):
330
+ def _translate_log(message, language=None):
331
+ return str(message)
332
+
333
+ logging_module.translate_log = _translate_log
334
+
335
+ return logging_module
336
+
337
+
338
+ _ensure_path()
339
+ _apply_runtime_config()
340
+
341
+ _logging_i18n = _install_logging_compat()
342
+ get_log_enabled = _logging_i18n.get_log_enabled
343
+ translate_log = _logging_i18n.translate_log
344
+
345
+ from cfquant import __version__ as _ENTRY_VERSION
346
+
347
+
348
+ def _print_log(message):
349
+ if get_log_enabled():
350
+ print(translate_log(message))
351
+
352
+
353
+ def _load_bridge_starter():
354
+ import cfquant.tx_trade_bridge as tx_trade_bridge
355
+
356
+ try:
357
+ tx_trade_bridge = importlib.reload(tx_trade_bridge)
358
+ except Exception as e:
359
+ _print_log("tx trade bridge reload failed:%s" % e)
360
+ return tx_trade_bridge.start_tx_trade_bridge
361
+
362
+
363
+ start_tx_trade_bridge = _load_bridge_starter()
364
+
365
+ from cfquant.channels import channels_for_bridge, normalize_bridge_id
366
+
367
+ BRIDGE_ID = normalize_bridge_id(BRIDGE_ID)
368
+ QMT_MARKET = str(QMT_MARKET or os.environ.get("CFQUANT_MARKET") or RUNTIME_CONFIG.get("market") or "").strip().upper()
369
+ if QMT_MARKET not in ("SH", "SZ"):
370
+ QMT_MARKET = ""
371
+ if not os.environ.get("CFQUANT_BRIDGE_ID"):
372
+ os.environ["CFQUANT_BRIDGE_ID"] = BRIDGE_ID
373
+ os.environ["CFQUANT_BRIDGE_ID_SOURCE"] = "cfquant_entry"
374
+ if QMT_MARKET and not os.environ.get("CFQUANT_MARKET"):
375
+ os.environ["CFQUANT_MARKET"] = QMT_MARKET
376
+ os.environ["CFQUANT_MARKET_SOURCE"] = "cfquant_entry"
377
+ BRIDGE_CHANNELS = channels_for_bridge(BRIDGE_ID)
378
+ _trade_channel_value = RUNTIME_CHANNELS.get("trade") or RUNTIME_CONFIG.get("trade_channel")
379
+ if _trade_channel_value:
380
+ BRIDGE_CHANNELS["trade"] = str(_trade_channel_value).strip()
381
+
382
+ _trade_bridge = start_tx_trade_bridge(
383
+ None,
384
+ ip="127.0.0.1",
385
+ port=2049,
386
+ token="LTtx",
387
+ request_channel=BRIDGE_CHANNELS["trade"],
388
+ bridge_id=BRIDGE_ID,
389
+ account_id=DEFAULT_ACCOUNT_ID,
390
+ show=True,
391
+ )
392
+ _print_log("cfquant lowlat trade bridge module loaded")
393
+ _print_log("cfquant lowlat entry version:%s" % _ENTRY_VERSION)
394
+ _print_log("cfquant bridge id:%s trade_channel:%s" % (BRIDGE_ID, BRIDGE_CHANNELS["trade"]))
395
+ if QMT_MARKET:
396
+ _print_log("cfquant lowlat market route market:%s bridge_id:%s" % (QMT_MARKET, BRIDGE_ID))
397
+
398
+
399
+ def _attach_trade_status_extra():
400
+ if not _trade_bridge:
401
+ return
402
+ original_status_extra = _trade_bridge._status_extra
403
+
404
+ def status_extra_with_market():
405
+ data = original_status_extra()
406
+ data.update({
407
+ "qmt_runtime_market": QMT_MARKET,
408
+ "qmt_runtime_market_role": RUNTIME_CONFIG.get("market_role") or ("trade" if QMT_MARKET else ""),
409
+ "qmt_runtime_market_parent_bridge_id": RUNTIME_CONFIG.get("market_route_parent_bridge_id") or "",
410
+ })
411
+ return data
412
+
413
+ _trade_bridge._status_extra = status_extra_with_market
414
+
415
+
416
+ _attach_trade_status_extra()
417
+
418
+
419
+ def init(ContextInfo):
420
+ if _trade_bridge:
421
+ _trade_bridge.set_context(ContextInfo)
422
+ _print_log("cfquant lowlat trade context ready version:%s" % _ENTRY_VERSION)
423
+ _trade_bridge.run_forever(sleep_seconds=0.001)
424
+
425
+
426
+ def handlebar(ContextInfo):
427
+ pass
428
+
429
+
430
+ def stop(ContextInfo):
431
+ global _trade_bridge
432
+
433
+ if _trade_bridge:
434
+ _trade_bridge.close()
435
+ _trade_bridge = None
436
+ _print_log("cfquant lowlat trade bridge stopped")