hamuna-quant-cli 0.1.20__tar.gz → 0.1.22__tar.gz

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 (40) hide show
  1. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/PKG-INFO +1 -1
  2. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/__init__.py +1 -1
  3. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/qmt_market.py +8 -25
  4. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/runner.py +30 -2
  5. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/PKG-INFO +1 -1
  6. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/pyproject.toml +1 -1
  7. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/MANIFEST.in +0 -0
  8. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/README.md +0 -0
  9. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/README.md +0 -0
  10. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/__main__.py +0 -0
  11. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/_market_fallback.py +0 -0
  12. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/_metrics_15.py +0 -0
  13. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/_test_akquant_parity.py +0 -0
  14. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/akquant_data_adapter.py +0 -0
  15. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/akquant_runner.py +0 -0
  16. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/akquant_schema_adapter.py +0 -0
  17. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/base_strategy.py +0 -0
  18. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/cross_sectional_helpers.py +0 -0
  19. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/__init__.py +0 -0
  20. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/loader.py +0 -0
  21. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/qmt_broker.py +0 -0
  22. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/live/server_market_client.py +0 -0
  23. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/prebuilt_downloader.py +0 -0
  24. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/prebuilt_resolver.py +0 -0
  25. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/qmt_translator.py +0 -0
  26. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/__init__.py +0 -0
  27. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/backtest.py +0 -0
  28. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/cache.py +0 -0
  29. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/discipline.py +0 -0
  30. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/http_client.py +0 -0
  31. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/s3client.py +0 -0
  32. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/runtime/server_client.py +0 -0
  33. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli/scripts/server.json +0 -0
  34. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/SOURCES.txt +0 -0
  35. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/dependency_links.txt +0 -0
  36. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/entry_points.txt +0 -0
  37. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/requires.txt +0 -0
  38. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/hamuna_quant_cli.egg-info/top_level.txt +0 -0
  39. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/setup.cfg +0 -0
  40. {hamuna_quant_cli-0.1.20 → hamuna_quant_cli-0.1.22}/tests/test_live_safety.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamuna-quant-cli
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: Hamuna A 股回测 + 实盘统一 CLI (akquant 0.3.x). 替代 v1 自建 driver + QMT-style 策略规范.
5
5
  Author-email: Hamuna Team <team@hamuna.example>
6
6
  License: MIT
@@ -12,4 +12,4 @@ server (13-key metrics schema). 全部走 akquant 0.3.x 引擎.
12
12
  """
13
13
  from __future__ import annotations
14
14
 
15
- __version__ = "0.1.20"
15
+ __version__ = "0.1.22"
@@ -177,16 +177,16 @@ def _make_market_gateway() -> Any:
177
177
  self._tick_callback(raw)
178
178
 
179
179
  def _emit_bar(self, raw: dict[str, Any]) -> None:
180
- # Round 18.63.3: bar 时间戳按 period 真实递增 — wall-clock time_ns()
181
- # 在批量推送 (SSE batch / warmup 20 根) 时几乎相同, live feed 按
182
- # 时间戳去重/聚合 (同刻 bar 只保留一根) → 交付给策略的 bar 数远少于
183
- # 推送数 → warmup_period (30) 永远攒不满 → on_bar 永不触发.
184
- # 修: 每根 bar ts = max(prev + period_ns, wall-clock), 保证唯一递增且
185
- # 晚于 session 启动 (第一个 bar 用墙钟, 天然 > active_start).
186
- period_ns = _period_ns(self._period)
180
+ # Round 18.63.15: ts 用真实墙钟 (max(now, last+1ns)) — 之前 Round
181
+ # 18.63.3 用 max(now, last+period_ns) 造"假递增日期", SSE 每秒推同一根
182
+ # 当日 bar (time=00:00, volume 变) 时每根 +1 天 → 策略日期跳到未来
183
+ # (2026-10/11 月), %H:%M 恒为启动时刻 — 用户实测报告 (11:02 恒不变).
184
+ # 修: ts = max(now_ns, last_ns + 1) — 唯一递增 (流式每秒 1 根时墙钟
185
+ # 天然不同; 批量推送时 +1ns 防碰撞), 日期 = 当天, %H:%M 随墙钟走.
186
+ # QMT 真实 bar 时间 (epoch ms) 仍在 bar.extra['qmt_time_ms'] 可取.
187
187
  now_ns = time.time_ns()
188
188
  last_ns = getattr(self, "_last_bar_ts_ns", 0)
189
- ts_ns = max(now_ns, last_ns + period_ns) if last_ns else now_ns
189
+ ts_ns = max(now_ns, last_ns + 1) if last_ns else now_ns
190
190
  self._last_bar_ts_ns = ts_ns
191
191
  bar_obj = _to_bar_obj(raw, ts_ns=ts_ns)
192
192
  if self._feed is not None:
@@ -606,23 +606,6 @@ def _unwrap_envelope(resp: dict[str, Any]) -> Any:
606
606
  return resp.get("value", resp)
607
607
 
608
608
 
609
- def _period_ns(period: str) -> int:
610
- """QMT period 字符串 → 单根 bar 的名义时长 (ns). 用于 _emit_bar 时间戳递增.
611
-
612
- Round 18.63.3: live feed 按时间戳去重/聚合, 同刻多根 bar 只保留一根 →
613
- 批量推送攒不满 warmup_period → on_bar 永不触发. 修: bar ts 按 period 真实
614
- 递增, 保证每根唯一. 无法识别时退回 1 分钟 (保守, 避免未来戳).
615
- """
616
- p = str(period or "").strip().lower()
617
- table = {
618
- "1m": 60, "5m": 300, "15m": 900, "30m": 1800, "60m": 3600,
619
- "1h": 3600, "4h": 14400, "1d": 86400, "day": 86400, "1w": 604800,
620
- "week": 604800, "1mo": 2592000, "month": 2592000,
621
- }
622
- seconds = table.get(p, 60)
623
- return int(seconds * 1_000_000_000)
624
-
625
-
626
609
  def _bar_signature(bar: dict[str, Any]) -> tuple:
627
610
  """bar 摘要 — 推 on_bar 去重用.
628
611
 
@@ -93,6 +93,29 @@ def _resolve_market_period(
93
93
  f"(params.market_period={mp}, 策略 inline 默认)",
94
94
  flush=True,
95
95
  )
96
+ # 优先级 3 (Round 18.63.14): params.json strategy_params.market_period
97
+ # 运行时覆盖 — 之前 docstring 声明了优先级 3 但代码从未实现, desktop
98
+ # 传 params(market_period=2=5m) 永远不生效, 策略按 inline 默认 1d 跑.
99
+ # params 传入形态: cmd_live_run 已 unwrap strategy_params 段 (扁平 dict),
100
+ # 兼容直接带 market_period 的扁平形态与残留嵌套形态.
101
+ sp = (params or {}).get("strategy_params") if isinstance(params, dict) else None
102
+ mp_override = None
103
+ if isinstance(sp, dict) and "market_period" in sp:
104
+ mp_override = sp.get("market_period")
105
+ elif isinstance(params, dict) and "market_period" in params:
106
+ mp_override = params.get("market_period")
107
+ if mp_override is not None:
108
+ try:
109
+ pmp = int(mp_override)
110
+ if pmp in _MARKET_PERIOD_MAP:
111
+ mapped = _MARKET_PERIOD_MAP[pmp]
112
+ print(
113
+ f"[info] market_period 覆盖: {mapped} "
114
+ f"(params.json market_period={pmp}, 运行时覆盖)",
115
+ flush=True,
116
+ )
117
+ except (TypeError, ValueError):
118
+ pass # 非法值忽略, 用 inline 推断结果
96
119
  return mapped
97
120
  except Exception as e: # noqa: BLE001
98
121
  print(
@@ -612,9 +635,14 @@ def _live_safety_defaults(
612
635
  "要去掉 qmt_paper=1 或改用 --mode paper."
613
636
  )
614
637
 
615
- if duration == "1h": # CLI 默认值 — 替换为永久
638
+ if duration in ("1h", "0", "0s", "0m", "0h", ""):
639
+ # Round 18.63.14: "0"/"1h" = 永久运行. 之前返回 "0" 会被 akquant
640
+ # `if duration:` 当真值 → _apply_time_limit("0") → 0 秒 deadline →
641
+ # 立即停止 (desktop 传 --duration 0 意图永久, 实测 3 秒后 TRADING
642
+ # SUMMARY 停止). 返回 "" (空串) → akquant if duration: 为假 → 不设
643
+ # deadline → 永久运行.
616
644
  print("[info] broker_live 默认 duration=0 (永久运行); 如需限时显式传 --duration", flush=True)
617
- return "0"
645
+ return ""
618
646
  print(f"[warn] broker_live 使用显式 duration={duration} — 到期自动停止", flush=True)
619
647
 
620
648
  # Round 33: broker_live 默认开 dual_source=verify (QMT + server 端双源验证).
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamuna-quant-cli
3
- Version: 0.1.20
3
+ Version: 0.1.22
4
4
  Summary: Hamuna A 股回测 + 实盘统一 CLI (akquant 0.3.x). 替代 v1 自建 driver + QMT-style 策略规范.
5
5
  Author-email: Hamuna Team <team@hamuna.example>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "hamuna-quant-cli"
7
- version = "0.1.20"
7
+ version = "0.1.22"
8
8
  description = "Hamuna A 股回测 + 实盘统一 CLI (akquant 0.3.x). 替代 v1 自建 driver + QMT-style 策略规范."
9
9
  readme = "hamuna_quant_cli/README.md"
10
10
  requires-python = ">=3.10"