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
cfquant/xttype.py ADDED
@@ -0,0 +1,586 @@
1
+ # -*- coding: utf-8 -*-
2
+ from . import xtconstant
3
+
4
+
5
+ class DictObject(object):
6
+ def __init__(self, **kwargs):
7
+ self.__dict__.update(kwargs)
8
+
9
+ @classmethod
10
+ def from_any(cls, value):
11
+ if value is None:
12
+ return None
13
+ if isinstance(value, cls):
14
+ return value
15
+ if hasattr(value, "__dict__"):
16
+ return cls(**vars(value))
17
+ if isinstance(value, dict):
18
+ return cls(**value)
19
+ return value
20
+
21
+ def __repr__(self):
22
+ return "%s(%s)" % (
23
+ type(self).__name__,
24
+ ", ".join("%s=%r" % item for item in sorted(self.__dict__.items())),
25
+ )
26
+
27
+
28
+ _MISSING = object()
29
+
30
+
31
+ def _dict_from_any(value):
32
+ if value is None:
33
+ return None
34
+ if hasattr(value, "__dict__"):
35
+ return dict(vars(value))
36
+ if isinstance(value, dict):
37
+ return dict(value)
38
+ return None
39
+
40
+
41
+ def _is_empty(value):
42
+ if value is None:
43
+ return True
44
+ if isinstance(value, str):
45
+ return value.strip() == ""
46
+ return False
47
+
48
+
49
+ def _first_value(data, names, default=_MISSING):
50
+ for name in names:
51
+ if name not in data:
52
+ continue
53
+ value = data.get(name)
54
+ if not _is_empty(value):
55
+ return value
56
+ return default
57
+
58
+
59
+ def _set_first(data, target, names, default=_MISSING):
60
+ if target in data and not _is_empty(data.get(target)):
61
+ return
62
+ value = _first_value(data, names, default)
63
+ if value is not _MISSING:
64
+ data[target] = value
65
+
66
+
67
+ _CANCELABLE_ORDER_STATUS_VALUES = frozenset((
68
+ getattr(xtconstant, "ORDER_UNREPORTED", 48),
69
+ getattr(xtconstant, "ORDER_WAIT_REPORTING", 49),
70
+ getattr(xtconstant, "ORDER_REPORTED", 50),
71
+ getattr(xtconstant, "ORDER_PART_SUCC", 55),
72
+ ))
73
+
74
+ _ORDER_STATUS_FIELD_NAMES = (
75
+ "order_status",
76
+ "m_nOrderStatus",
77
+ "m_nOrderState",
78
+ "m_strOrderStatus",
79
+ "m_strStatus",
80
+ )
81
+
82
+
83
+ def _normalize_order_status(value):
84
+ if value is None or isinstance(value, bool):
85
+ return None
86
+ if isinstance(value, int):
87
+ return value
88
+ if isinstance(value, float):
89
+ return int(value) if value.is_integer() else None
90
+ if isinstance(value, bytes):
91
+ try:
92
+ value = value.decode("utf-8")
93
+ except Exception:
94
+ return None
95
+ text = str(value).strip()
96
+ if not text:
97
+ return None
98
+ if text.isdigit():
99
+ return int(text)
100
+ try:
101
+ number = float(text)
102
+ if number.is_integer():
103
+ return int(number)
104
+ except Exception:
105
+ pass
106
+ aliases = {
107
+ "ORDER_UNREPORTED": getattr(xtconstant, "ORDER_UNREPORTED", 48),
108
+ "ORDER_WAIT_REPORTING": getattr(xtconstant, "ORDER_WAIT_REPORTING", 49),
109
+ "ORDER_REPORTED": getattr(xtconstant, "ORDER_REPORTED", 50),
110
+ "ORDER_PART_SUCC": getattr(xtconstant, "ORDER_PART_SUCC", 55),
111
+ }
112
+ return aliases.get(text.upper())
113
+
114
+
115
+ def order_status_from_any(value):
116
+ data = _dict_from_any(value)
117
+ if data is None:
118
+ return None
119
+ status = _first_value(data, _ORDER_STATUS_FIELD_NAMES, default=None)
120
+ return _normalize_order_status(status)
121
+
122
+
123
+ def is_cancelable_order_status(value):
124
+ return _normalize_order_status(value) in _CANCELABLE_ORDER_STATUS_VALUES
125
+
126
+
127
+ def is_cancelable_order(value):
128
+ return order_status_from_any(value) in _CANCELABLE_ORDER_STATUS_VALUES
129
+
130
+
131
+ def filter_cancelable_orders(values):
132
+ if values is None:
133
+ return None
134
+ if isinstance(values, list):
135
+ return [value for value in values if is_cancelable_order(value)]
136
+ return values if is_cancelable_order(values) else None
137
+
138
+
139
+ def _normalize_account_type(value):
140
+ if _is_empty(value):
141
+ return xtconstant.SECURITY_ACCOUNT
142
+ if isinstance(value, str):
143
+ text = value.strip().upper()
144
+ if text.isdigit():
145
+ return int(text)
146
+ aliases = {
147
+ "SECURITY": xtconstant.SECURITY_ACCOUNT,
148
+ "SECURITY_ACCOUNT": xtconstant.SECURITY_ACCOUNT,
149
+ "STOCK_ACCOUNT": xtconstant.SECURITY_ACCOUNT,
150
+ "MARGIN": xtconstant.CREDIT_ACCOUNT,
151
+ "CREDIT_ACCOUNT": xtconstant.CREDIT_ACCOUNT,
152
+ }
153
+ if text in aliases:
154
+ return aliases[text]
155
+ for int_type, str_type in xtconstant.ACCOUNT_TYPE_DICT.items():
156
+ if text == str(str_type).upper():
157
+ return int_type
158
+ return value
159
+
160
+
161
+ def _apply_common_account_fields(data):
162
+ _set_first(data, "account_id", (
163
+ "m_strAccountID",
164
+ "m_strAccountId",
165
+ "m_strAccount",
166
+ "m_accountID",
167
+ "fund_account",
168
+ ), default="")
169
+ account_type = _first_value(data, (
170
+ "account_type",
171
+ "m_nAccountType",
172
+ "m_strAccountType",
173
+ ), default=xtconstant.SECURITY_ACCOUNT)
174
+ data["account_type"] = _normalize_account_type(account_type)
175
+
176
+
177
+ def _exchange_suffix(value):
178
+ if _is_empty(value):
179
+ return ""
180
+ if isinstance(value, int):
181
+ return {0: "SH", 1: "SZ", 70: "BJ"}.get(value, str(value))
182
+ text = str(value).strip().upper()
183
+ aliases = {
184
+ "0": "SH",
185
+ "SH": "SH",
186
+ "SSE": "SH",
187
+ "SHSE": "SH",
188
+ "1": "SZ",
189
+ "SZ": "SZ",
190
+ "SZSE": "SZ",
191
+ "70": "BJ",
192
+ "BJ": "BJ",
193
+ "BSE": "BJ",
194
+ }
195
+ return aliases.get(text, text)
196
+
197
+
198
+ def _stock_code(data):
199
+ code = _first_value(data, ("stock_code", "code", "ticker"), default="")
200
+ if not _is_empty(code):
201
+ return str(code)
202
+ instrument_id = _first_value(data, (
203
+ "m_strInstrumentID",
204
+ "instrument_id",
205
+ "m_strStockCode",
206
+ "stock_id",
207
+ ), default="")
208
+ if _is_empty(instrument_id):
209
+ return ""
210
+ instrument_id = str(instrument_id)
211
+ if "." in instrument_id:
212
+ return instrument_id
213
+ exchange_id = _exchange_suffix(_first_value(data, (
214
+ "m_strExchangeID",
215
+ "exchange_id",
216
+ "market",
217
+ "m_strMarket",
218
+ ), default=""))
219
+ if exchange_id:
220
+ return "%s.%s" % (instrument_id, exchange_id)
221
+ return instrument_id
222
+
223
+
224
+ def _apply_stock_code_field(data):
225
+ if _is_empty(data.get("stock_code")):
226
+ data["stock_code"] = _stock_code(data)
227
+
228
+
229
+ class StockAccount(object):
230
+ def __new__(cls, account_id, account_type="STOCK", bridge_id=None):
231
+ if not isinstance(account_id, str):
232
+ return "资金账号必须为字符串类型"
233
+ return super(StockAccount, cls).__new__(cls)
234
+
235
+ def __init__(self, account_id, account_type="STOCK", bridge_id=None):
236
+ account_type = account_type.upper()
237
+ for int_type, str_type in xtconstant.ACCOUNT_TYPE_DICT.items():
238
+ if account_type == str_type:
239
+ self.account_type = int_type
240
+ self.account_id = account_id
241
+ self.bridge_id = str(bridge_id or "").strip()
242
+ return
243
+ raise Exception("不支持的账号类型:{}!".format(account_type))
244
+
245
+
246
+ class XtAsset(DictObject):
247
+ @classmethod
248
+ def from_any(cls, value):
249
+ data = _dict_from_any(value)
250
+ if data is None:
251
+ return value
252
+ _apply_common_account_fields(data)
253
+ _set_first(data, "cash", (
254
+ "available",
255
+ "m_dAvailable",
256
+ "m_dEnableBalance",
257
+ ), default=0.0)
258
+ _set_first(data, "frozen_cash", (
259
+ "frozen",
260
+ "frozen_balance",
261
+ "m_dFrozenCash",
262
+ "m_dFrozenBalance",
263
+ ), default=0.0)
264
+ _set_first(data, "market_value", (
265
+ "m_dInstrumentValue",
266
+ "m_dMarketValue",
267
+ "m_dStockValue",
268
+ ), default=0.0)
269
+ _set_first(data, "total_asset", (
270
+ "balance",
271
+ "m_dBalance",
272
+ "assure_asset",
273
+ "m_dAssureAsset",
274
+ ), default=0.0)
275
+ _set_first(data, "fetch_balance", (
276
+ "m_dFetchBalance",
277
+ "fetch_balance",
278
+ "available",
279
+ "m_dAvailable",
280
+ "cash",
281
+ ), default=0.0)
282
+ return cls(**data)
283
+
284
+
285
+ class XtOrder(DictObject):
286
+ @classmethod
287
+ def from_any(cls, value):
288
+ data = _dict_from_any(value)
289
+ if data is None:
290
+ return value
291
+ _apply_common_account_fields(data)
292
+ _apply_stock_code_field(data)
293
+ _set_first(data, "order_id", (
294
+ "m_nOrderID",
295
+ "m_strOrderID",
296
+ ), default=-1)
297
+ _set_first(data, "order_sysid", (
298
+ "m_strOrderSysID",
299
+ "sysid",
300
+ "m_strOrderID",
301
+ ), default="")
302
+ _set_first(data, "order_time", (
303
+ "entrust_time",
304
+ "insert_time",
305
+ "m_strOrderTime",
306
+ "m_strEntrustTime",
307
+ "m_strInsertTime",
308
+ "m_nOrderTime",
309
+ "m_nEntrustTime",
310
+ "m_nInsertTime",
311
+ ), default="")
312
+ _set_first(data, "order_type", (
313
+ "m_nOrderType",
314
+ "m_nBusinessType",
315
+ ), default=0)
316
+ _set_first(data, "order_volume", (
317
+ "m_nVolumeTotalOriginal",
318
+ "m_nOrderVolume",
319
+ "m_nVolume",
320
+ ), default=0)
321
+ _set_first(data, "price_type", (
322
+ "m_nPriceType",
323
+ "m_nOrderPriceType",
324
+ ), default=0)
325
+ _set_first(data, "price", (
326
+ "m_dLimitPrice",
327
+ "m_dOrderPrice",
328
+ "m_dPrice",
329
+ ), default=0.0)
330
+ _set_first(data, "traded_volume", (
331
+ "m_nVolumeTraded",
332
+ "m_nTradedVolume",
333
+ ), default=0)
334
+ _set_first(data, "traded_price", (
335
+ "m_dTradedPrice",
336
+ "m_dAveragePrice",
337
+ ), default=0.0)
338
+ _set_first(data, "order_status", (
339
+ "m_nOrderStatus",
340
+ "m_nOrderState",
341
+ ), default=getattr(xtconstant, "ORDER_UNKNOWN", 255))
342
+ _set_first(data, "status_msg", (
343
+ "m_strStatusMsg",
344
+ "m_strStatus",
345
+ "m_strOrderStatus",
346
+ ), default="")
347
+ _set_first(data, "strategy_name", (
348
+ "m_strStrategyName",
349
+ ), default="")
350
+ _set_first(data, "order_remark", (
351
+ "m_strRemark",
352
+ "m_strOrderRemark",
353
+ ), default="")
354
+ _set_first(data, "direction", (
355
+ "m_nDirection",
356
+ ), default=0)
357
+ _set_first(data, "offset_flag", (
358
+ "m_nOffsetFlag",
359
+ ), default=0)
360
+ _set_first(data, "secu_account", (
361
+ "m_strSecuAccount",
362
+ "m_strSecurityAccount",
363
+ ), default="")
364
+ _set_first(data, "instrument_name", (
365
+ "m_strInstrumentName",
366
+ "name",
367
+ ), default="")
368
+ return cls(**data)
369
+
370
+
371
+ class XtTrade(DictObject):
372
+ @classmethod
373
+ def from_any(cls, value):
374
+ data = _dict_from_any(value)
375
+ if data is None:
376
+ return value
377
+ _apply_common_account_fields(data)
378
+ _apply_stock_code_field(data)
379
+ _set_first(data, "order_type", (
380
+ "m_nOrderType",
381
+ "m_nBusinessType",
382
+ ), default=0)
383
+ _set_first(data, "traded_id", (
384
+ "trade_id",
385
+ "deal_id",
386
+ "m_strTradeID",
387
+ "m_strDealID",
388
+ "m_nTradeID",
389
+ ), default="")
390
+ _set_first(data, "traded_time", (
391
+ "trade_time",
392
+ "deal_time",
393
+ "m_strTradeTime",
394
+ "m_strDealTime",
395
+ "m_nTradeTime",
396
+ "m_nDealTime",
397
+ ), default="")
398
+ _set_first(data, "traded_price", (
399
+ "price",
400
+ "m_dPrice",
401
+ "m_dTradedPrice",
402
+ ), default=0.0)
403
+ _set_first(data, "traded_volume", (
404
+ "volume",
405
+ "m_nVolume",
406
+ "m_nVolumeTraded",
407
+ ), default=0)
408
+ _set_first(data, "traded_amount", (
409
+ "trade_amount",
410
+ "m_dTradeAmount",
411
+ "m_dTradedAmount",
412
+ ), default=0.0)
413
+ _set_first(data, "order_id", (
414
+ "m_nOrderID",
415
+ "m_strOrderID",
416
+ ), default=-1)
417
+ _set_first(data, "order_sysid", (
418
+ "m_strOrderSysID",
419
+ "sysid",
420
+ "m_strOrderID",
421
+ ), default="")
422
+ _set_first(data, "strategy_name", (
423
+ "m_strStrategyName",
424
+ ), default="")
425
+ _set_first(data, "order_remark", (
426
+ "m_strRemark",
427
+ "m_strOrderRemark",
428
+ ), default="")
429
+ _set_first(data, "direction", (
430
+ "m_nDirection",
431
+ ), default=0)
432
+ _set_first(data, "offset_flag", (
433
+ "m_nOffsetFlag",
434
+ ), default=0)
435
+ _set_first(data, "commission", (
436
+ "m_dCommission",
437
+ ), default=0.0)
438
+ _set_first(data, "secu_account", (
439
+ "m_strSecuAccount",
440
+ "m_strSecurityAccount",
441
+ ), default="")
442
+ _set_first(data, "instrument_name", (
443
+ "m_strInstrumentName",
444
+ "name",
445
+ ), default="")
446
+ return cls(**data)
447
+
448
+
449
+ class XtPosition(DictObject):
450
+ @classmethod
451
+ def from_any(cls, value):
452
+ data = _dict_from_any(value)
453
+ if data is None:
454
+ return value
455
+ _apply_common_account_fields(data)
456
+ _apply_stock_code_field(data)
457
+ _set_first(data, "volume", (
458
+ "m_nVolume",
459
+ "m_nPosition",
460
+ ), default=0)
461
+ _set_first(data, "can_use_volume", (
462
+ "m_nCanUseVolume",
463
+ "m_nAvailableVolume",
464
+ ), default=0)
465
+ _set_first(data, "open_price", (
466
+ "m_dOpenPrice",
467
+ ), default=0.0)
468
+ _set_first(data, "market_value", (
469
+ "m_dInstrumentValue",
470
+ "m_dMarketValue",
471
+ ), default=0.0)
472
+ _set_first(data, "frozen_volume", (
473
+ "m_nFrozenVolume",
474
+ "m_nFreezeVolume",
475
+ ), default=0)
476
+ _set_first(data, "on_road_volume", (
477
+ "m_nOnRoadVolume",
478
+ "m_nUncomeVolume",
479
+ ), default=0)
480
+ _set_first(data, "yesterday_volume", (
481
+ "m_nYesterdayVolume",
482
+ "m_nYdPosition",
483
+ ), default=0)
484
+ _set_first(data, "avg_price", (
485
+ "position_cost",
486
+ "m_dPositionCost",
487
+ "m_dAvgPrice",
488
+ ), default=0.0)
489
+ _set_first(data, "direction", (
490
+ "m_nDirection",
491
+ ), default=0)
492
+ _set_first(data, "last_price", (
493
+ "m_dLastPrice",
494
+ ), default=0.0)
495
+ _set_first(data, "profit_rate", (
496
+ "m_dProfitRate",
497
+ ), default=0.0)
498
+ _set_first(data, "secu_account", (
499
+ "m_strSecuAccount",
500
+ "m_strSecurityAccount",
501
+ ), default="")
502
+ _set_first(data, "instrument_name", (
503
+ "m_strInstrumentName",
504
+ "name",
505
+ ), default="")
506
+ return cls(**data)
507
+
508
+
509
+ class XtOrderError(DictObject):
510
+ @classmethod
511
+ def from_any(cls, value):
512
+ data = _dict_from_any(value)
513
+ if data is None:
514
+ return value
515
+ _apply_common_account_fields(data)
516
+ _set_first(data, "order_id", ("m_nOrderID", "m_strOrderID"), default=-1)
517
+ _set_first(data, "error_id", ("m_nErrorID", "error_code"), default=None)
518
+ _set_first(data, "error_msg", ("m_strErrorMsg", "message", "msg"), default="")
519
+ _set_first(data, "strategy_name", ("m_strStrategyName",), default="")
520
+ _set_first(data, "order_remark", ("m_strRemark", "m_strOrderRemark"), default="")
521
+ return cls(**data)
522
+
523
+
524
+ class XtCancelError(DictObject):
525
+ @classmethod
526
+ def from_any(cls, value):
527
+ data = _dict_from_any(value)
528
+ if data is None:
529
+ return value
530
+ _apply_common_account_fields(data)
531
+ _set_first(data, "order_id", ("m_nOrderID", "m_strOrderID"), default=-1)
532
+ _set_first(data, "market", ("m_nMarket", "m_strExchangeID"), default="")
533
+ _set_first(data, "order_sysid", ("m_strOrderSysID", "sysid", "m_strOrderID"), default="")
534
+ _set_first(data, "error_id", ("m_nErrorID", "error_code"), default=None)
535
+ _set_first(data, "error_msg", ("m_strErrorMsg", "message", "msg"), default="")
536
+ return cls(**data)
537
+
538
+
539
+ class XtOrderResponse(DictObject):
540
+ @classmethod
541
+ def from_any(cls, value):
542
+ data = _dict_from_any(value)
543
+ if data is None:
544
+ return value
545
+ _apply_common_account_fields(data)
546
+ _set_first(data, "order_id", ("m_nOrderID", "m_strOrderID"), default=-1)
547
+ _set_first(data, "strategy_name", ("m_strStrategyName",), default="")
548
+ _set_first(data, "order_remark", ("m_strRemark", "m_strOrderRemark"), default="")
549
+ _set_first(data, "error_msg", ("m_strErrorMsg", "message", "msg"), default="")
550
+ _set_first(data, "seq", ("m_nSeq", "request_id"), default=None)
551
+ return cls(**data)
552
+
553
+
554
+ class XtCancelOrderResponse(DictObject):
555
+ @classmethod
556
+ def from_any(cls, value):
557
+ data = _dict_from_any(value)
558
+ if data is None:
559
+ return value
560
+ _apply_common_account_fields(data)
561
+ _set_first(data, "cancel_result", ("result", "m_nCancelResult"), default=-1)
562
+ _set_first(data, "order_id", ("m_nOrderID", "m_strOrderID"), default=-1)
563
+ _set_first(data, "order_sysid", ("m_strOrderSysID", "sysid", "m_strOrderID"), default="")
564
+ _set_first(data, "seq", ("m_nSeq", "request_id"), default=None)
565
+ _set_first(data, "error_msg", ("m_strErrorMsg", "message", "msg"), default="")
566
+ return cls(**data)
567
+
568
+
569
+ class XtAccountStatus(DictObject):
570
+ pass
571
+
572
+
573
+ class XtBankTransferResponse(DictObject):
574
+ pass
575
+
576
+
577
+ class XtSmtAppointmentResponse(DictObject):
578
+ pass
579
+
580
+
581
+ def to_objects(values, cls=DictObject):
582
+ if values is None:
583
+ return None
584
+ if isinstance(values, list):
585
+ return [cls.from_any(v) for v in values]
586
+ return cls.from_any(values)
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 tao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.