hamuna-quant-cli 0.1.0__tar.gz → 0.1.1__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.0 → hamuna_quant_cli-0.1.1}/PKG-INFO +1 -1
  2. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/__init__.py +1 -1
  3. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/__main__.py +6 -0
  4. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/runner.py +30 -2
  5. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/PKG-INFO +1 -1
  6. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/pyproject.toml +1 -1
  7. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/MANIFEST.in +0 -0
  8. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/README.md +0 -0
  9. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/README.md +0 -0
  10. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_market_fallback.py +0 -0
  11. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_metrics_15.py +0 -0
  12. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_test_akquant_parity.py +0 -0
  13. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_data_adapter.py +0 -0
  14. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_runner.py +0 -0
  15. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_schema_adapter.py +0 -0
  16. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/base_strategy.py +0 -0
  17. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/cross_sectional_helpers.py +0 -0
  18. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/__init__.py +0 -0
  19. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/loader.py +0 -0
  20. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/qmt_broker.py +0 -0
  21. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/qmt_market.py +0 -0
  22. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/prebuilt_downloader.py +0 -0
  23. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/prebuilt_resolver.py +0 -0
  24. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/qmt_translator.py +0 -0
  25. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/__init__.py +0 -0
  26. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/backtest.py +0 -0
  27. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/cache.py +0 -0
  28. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/discipline.py +0 -0
  29. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/http_client.py +0 -0
  30. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/s3client.py +0 -0
  31. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/server_client.py +0 -0
  32. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/scripts/server.json +0 -0
  33. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/SOURCES.txt +0 -0
  34. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/dependency_links.txt +0 -0
  35. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/entry_points.txt +0 -0
  36. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/requires.txt +0 -0
  37. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/top_level.txt +0 -0
  38. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/setup.cfg +0 -0
  39. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/tests/test_live_safety.py +0 -0
  40. {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/tests/test_skeleton.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamuna-quant-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
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
@@ -14,4 +14,4 @@ from __future__ import annotations
14
14
 
15
15
  # 版本号由 scripts/bump_version.py 每次 build 自动更新 (基于 git 提交数).
16
16
  # 格式: 0.1.0.dev<git提交数> (PEP 440). 手动改这里会被下一次 build 覆盖.
17
- __version__ = "0.1.0"
17
+ __version__ = "0.1.1"
@@ -800,6 +800,9 @@ def cmd_live_run(args) -> int:
800
800
  return 3
801
801
  try:
802
802
  symbols = [s.strip() for s in args.symbols.split(",")] if args.symbols else None
803
+ params = json.loads(Path(args.params).read_text(encoding="utf-8")) if args.params else None
804
+ # 只取 strategy_params 段 (schema 顶层: backtest / strategy_params / risk_config / meta)
805
+ sp = (params or {}).get("strategy_params")
803
806
  run_live(
804
807
  spec,
805
808
  mode=args.mode,
@@ -812,6 +815,7 @@ def cmd_live_run(args) -> int:
812
815
  log_file=args.log_file,
813
816
  market_broker=args.market_broker,
814
817
  replay_days=args.replay_days,
818
+ params=sp if isinstance(sp, dict) else None,
815
819
  )
816
820
  except LiveRunError as e:
817
821
  print(f"[error] live run 失败: {e}", file=sys.stderr)
@@ -950,6 +954,8 @@ def build_parser() -> argparse.ArgumentParser:
950
954
  help="独立行情 broker (e.g. qmt_market)")
951
955
  run_p.add_argument("--symbols", default=None,
952
956
  help="标的列表, 逗号分隔")
957
+ run_p.add_argument("--params", default=None,
958
+ help="params.json 路径 (固定 schema, strategy_params 段作策略构造参数)")
953
959
  run_p.add_argument("--duration", default="1h",
954
960
  help="运行时长 (akquant 解析)")
955
961
  run_p.add_argument("--class-name", default="Strategy",
@@ -279,17 +279,30 @@ def configure_logging(level: str, log_file: Path | None) -> None:
279
279
  akquant.configure_logging(LogConfig(**cfg_kwargs))
280
280
 
281
281
 
282
- def _with_live_history_depth(cls: type) -> type:
282
+ def _with_live_history_depth(cls: type, params: dict | None = None) -> type:
283
283
  """class mode 注入 set_history_depth — live 引擎不像回测 (engine.py:4637) 那样
284
284
  自动开 history tracking, 策略 on_bar 里 get_history 直接抛
285
285
  "History tracking is not enabled" (2026-08-19 实测). depth 取策略 on_start 设的
286
286
  warmup_period, 未设默认 120.
287
287
 
288
+ params: 用户实盘参数 (params.json strategy_params) — 作构造 kwargs 注入.
289
+ live 端 _build_strategy_instance 是 `cls()` 无参实例化, 不传的话 Strategy.__new__
290
+ 走 `model_cls()` 空模型, 用户配置的参数不生效 (2026-08-25 实测缺口).
291
+ 注入必须盖 `__new__`: Strategy 的参数入口在 __new__ 末尾 `model_cls(**kwargs)`,
292
+ 盖 __init__ 传 kwargs 不回灌给已结束的 __new__ (无参构造时 params 丢失).
293
+
288
294
  ponytail: 只包 class mode; functional mode 用户自己管 get_history (ctx 侧).
289
295
  """
290
296
  from typing import Any as _Any
291
297
 
292
298
  class _Wrapped(cls):
299
+ _user_params: dict = params or {}
300
+
301
+ def __new__(cls, *a: _Any, **kw: _Any) -> _Any:
302
+ merged = dict(cls._user_params)
303
+ merged.update(kw)
304
+ return super().__new__(cls, *a, **merged)
305
+
293
306
  def on_start(self) -> _Any:
294
307
  ret = super().on_start()
295
308
  depth = getattr(self, "warmup_period", None) or 120
@@ -345,6 +358,7 @@ def run_live(
345
358
  log_file: Path | None,
346
359
  market_broker: str | None,
347
360
  replay_days: int = 30,
361
+ params: dict | None = None,
348
362
  ) -> None:
349
363
  """翻译 + 转发到 akquant.run_live.
350
364
 
@@ -358,6 +372,8 @@ def run_live(
358
372
  duration: 字符串 ("30s" / "1h" / "2d"), akquant 自己解析
359
373
  gateway_options_raw: CLI 字符串, parse 成 dict 后透传
360
374
  initial_cash: 回传给 run_live (None = akquant 默认)
375
+ params: params.json 的 strategy_params (用户实盘配置) — 校验后作构造
376
+ kwargs 注入策略. None = 用策略代码内默认值.
361
377
  """
362
378
  gateway_options = parse_kv_pairs(gateway_options_raw)
363
379
  duration = _live_safety_defaults(mode, broker, gateway_options, duration)
@@ -555,7 +571,19 @@ def run_live(
555
571
 
556
572
  # class mode vs functional mode — run_live 入参不同
557
573
  if spec.mode == "class":
558
- kwargs["strategy_cls"] = _with_live_history_depth(spec.strategy_cls)
574
+ # params.json 用户配置 → 校验 (未知字段/越界抛 LiveRunError) + 注入构造 kwargs.
575
+ # live 端 _build_strategy_instance 是 `cls()` 无参实例化, 必须在包装类里把
576
+ # params 传进 __new__ → ParamModel(**kwargs) 才生效 (2026-08-25 实测缺口).
577
+ sp = None
578
+ if params:
579
+ try:
580
+ from akquant import validate_strategy_params
581
+ sp = validate_strategy_params(spec.strategy_cls, params)
582
+ except Exception as e:
583
+ raise LiveRunError(
584
+ f"params.json 校验失败 (strategy_params 与 IntParam/ListParam 字段不符): {e}"
585
+ ) from e
586
+ kwargs["strategy_cls"] = _with_live_history_depth(spec.strategy_cls, sp)
559
587
  else:
560
588
  cbs = spec.callbacks or {}
561
589
  kwargs["strategy_cls"] = cbs["on_bar"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hamuna-quant-cli
3
- Version: 0.1.0
3
+ Version: 0.1.1
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.0"
7
+ version = "0.1.1"
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"