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.
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/PKG-INFO +1 -1
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/__init__.py +1 -1
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/__main__.py +6 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/runner.py +30 -2
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/PKG-INFO +1 -1
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/pyproject.toml +1 -1
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/MANIFEST.in +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/README.md +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/README.md +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_market_fallback.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_metrics_15.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/_test_akquant_parity.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_data_adapter.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_runner.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_schema_adapter.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/base_strategy.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/cross_sectional_helpers.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/__init__.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/loader.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/qmt_broker.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/live/qmt_market.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/prebuilt_downloader.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/prebuilt_resolver.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/qmt_translator.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/__init__.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/backtest.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/cache.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/discipline.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/http_client.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/s3client.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/runtime/server_client.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/scripts/server.json +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/SOURCES.txt +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/dependency_links.txt +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/entry_points.txt +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/requires.txt +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/top_level.txt +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/setup.cfg +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/tests/test_live_safety.py +0 -0
- {hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/tests/test_skeleton.py +0 -0
|
@@ -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
|
-
|
|
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"]
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hamuna-quant-cli"
|
|
7
|
-
version = "0.1.
|
|
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"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/akquant_schema_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli/cross_sectional_helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{hamuna_quant_cli-0.1.0 → hamuna_quant_cli-0.1.1}/hamuna_quant_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|