hamuna-quant-cli 0.1.6__tar.gz → 0.1.7__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.6 → hamuna_quant_cli-0.1.7}/PKG-INFO +1 -1
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/__init__.py +1 -1
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/__main__.py +46 -12
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/PKG-INFO +1 -1
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/pyproject.toml +1 -1
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/MANIFEST.in +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/README.md +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/README.md +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/_market_fallback.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/_metrics_15.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/_test_akquant_parity.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/akquant_data_adapter.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/akquant_runner.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/akquant_schema_adapter.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/base_strategy.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/cross_sectional_helpers.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/live/__init__.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/live/loader.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/live/qmt_broker.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/live/qmt_market.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/live/runner.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/prebuilt_downloader.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/prebuilt_resolver.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/qmt_translator.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/__init__.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/backtest.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/cache.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/discipline.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/http_client.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/s3client.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/runtime/server_client.py +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/scripts/server.json +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/SOURCES.txt +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/dependency_links.txt +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/entry_points.txt +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/requires.txt +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/top_level.txt +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/setup.cfg +0 -0
- {hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/tests/test_live_safety.py +0 -0
|
@@ -30,6 +30,37 @@ def _load_config(path: str) -> dict:
|
|
|
30
30
|
return json.loads(Path(path).read_text(encoding="utf-8"))
|
|
31
31
|
|
|
32
32
|
|
|
33
|
+
def _load_params_arg(arg: str) -> dict | None:
|
|
34
|
+
"""Round 18.48+: --params 既支持 inline JSON (以 '{' 开头) 又支持文件路径.
|
|
35
|
+
|
|
36
|
+
历史 CLI / 回测脚本传文件路径 (`hamuna_quant_cli run --params ./params.json`).
|
|
37
|
+
desktop Rust 调 live run 时通过 `read_to_string` 把 `<name>.params.json` 读成
|
|
38
|
+
String 后 inline 传过来 (`--params '<json>'`), 旧 cli 把 inline 当文件路径
|
|
39
|
+
直接 `Path.read_text()` → FileNotFoundError (本轮 bug 报告).
|
|
40
|
+
|
|
41
|
+
协议: 以 '{' (允许前导空白) 开头 → inline JSON parse; 否则 → 文件路径 read.
|
|
42
|
+
Caller 决定 None vs raise: cmd_commit 容忍 None + 走 schema warning,
|
|
43
|
+
cmd_live_run 期望非空否则 raise FileNotFoundError.
|
|
44
|
+
"""
|
|
45
|
+
if not arg:
|
|
46
|
+
return None
|
|
47
|
+
stripped = arg.lstrip()
|
|
48
|
+
if stripped.startswith("{"):
|
|
49
|
+
import json as _json
|
|
50
|
+
try:
|
|
51
|
+
return _json.loads(arg)
|
|
52
|
+
except _json.JSONDecodeError as e:
|
|
53
|
+
raise ValueError(f"--params inline JSON 解析失败: {e}") from e
|
|
54
|
+
p = Path(arg)
|
|
55
|
+
if not p.exists():
|
|
56
|
+
raise FileNotFoundError(f"--params 不存在: {arg}")
|
|
57
|
+
import json as _json
|
|
58
|
+
try:
|
|
59
|
+
return _json.loads(p.read_text(encoding="utf-8"))
|
|
60
|
+
except _json.JSONDecodeError as e:
|
|
61
|
+
raise ValueError(f"--params 解析失败: {arg} ({e})") from e
|
|
62
|
+
|
|
63
|
+
|
|
33
64
|
def _parse_symbols(s: str) -> list[str]:
|
|
34
65
|
"""CSV symbols → 裸码 list (A 股 dataset stockCode 不带 .SH/.SZ/.BJ 后缀)."""
|
|
35
66
|
out: list[str] = []
|
|
@@ -72,18 +103,17 @@ def cmd_run(args) -> int:
|
|
|
72
103
|
# --params (params.json 固定 schema) → strategy_params 段注入 cfg,
|
|
73
104
|
# akquant_runner 展开注入 engine kwargs. 与 `live run --params` 同源:
|
|
74
105
|
# 同一份 params.json 驱动回测 + 实盘, 参数约定不再分裂 (Round 18.13).
|
|
106
|
+
# Round 18.48+: 既支持文件路径也支持 inline JSON (见 _load_params_arg).
|
|
75
107
|
if getattr(args, "params", None):
|
|
76
|
-
params_path = Path(args.params)
|
|
77
|
-
if not params_path.exists():
|
|
78
|
-
print(f"--params 不存在: {args.params}", file=sys.stderr)
|
|
79
|
-
return 2
|
|
80
|
-
import json as _json
|
|
81
108
|
try:
|
|
82
|
-
params_doc =
|
|
83
|
-
except
|
|
84
|
-
print(f"--params
|
|
109
|
+
params_doc = _load_params_arg(args.params) or {}
|
|
110
|
+
except FileNotFoundError as e:
|
|
111
|
+
print(f"--params 不存在: {e}", file=sys.stderr)
|
|
85
112
|
return 2
|
|
86
|
-
|
|
113
|
+
except ValueError as e:
|
|
114
|
+
print(f"--params 解析失败: {e}", file=sys.stderr)
|
|
115
|
+
return 2
|
|
116
|
+
sp = params_doc.get("strategy_params")
|
|
87
117
|
if isinstance(sp, dict):
|
|
88
118
|
cfg["strategy_params"] = sp
|
|
89
119
|
else:
|
|
@@ -91,7 +121,7 @@ def cmd_run(args) -> int:
|
|
|
91
121
|
# Round 18.14: risk_config 段 → cfg['risk_config'] → runner 透传
|
|
92
122
|
# run_backtest(risk_config={"max_position_pct": 0.1}) 原生消费 (账户级风控,
|
|
93
123
|
# 引擎 hasattr 校验 + 未知字段仅 warning). skill 桌面编辑的实盘风控真正生效.
|
|
94
|
-
rc =
|
|
124
|
+
rc = params_doc.get("risk_config")
|
|
95
125
|
if isinstance(rc, dict):
|
|
96
126
|
# 与既有 cfg['risk_config'] 合并 (显式 cfg 优先)
|
|
97
127
|
merged = dict(cfg.get("risk_config") or {})
|
|
@@ -814,9 +844,13 @@ def cmd_live_run(args) -> int:
|
|
|
814
844
|
print(f"[error] strategy.py 加载失败: {e}", file=sys.stderr)
|
|
815
845
|
return 3
|
|
816
846
|
try:
|
|
817
|
-
import json as _json
|
|
818
847
|
symbols = [s.strip() for s in args.symbols.split(",")] if args.symbols else None
|
|
819
|
-
|
|
848
|
+
# Round 18.48+: --params 既支持 inline JSON 也支持文件路径 (desktop rust read_to_string 传 inline)
|
|
849
|
+
try:
|
|
850
|
+
params = _load_params_arg(args.params) if args.params else None
|
|
851
|
+
except (FileNotFoundError, ValueError) as e:
|
|
852
|
+
print(f"[error] --params: {e}", file=sys.stderr)
|
|
853
|
+
return 2
|
|
820
854
|
# 只取 strategy_params 段 (schema 顶层: backtest / strategy_params / risk_config / meta)
|
|
821
855
|
sp = (params or {}).get("strategy_params")
|
|
822
856
|
run_live(
|
|
@@ -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.7"
|
|
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.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli/akquant_schema_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
{hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/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
|
|
File without changes
|
{hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{hamuna_quant_cli-0.1.6 → hamuna_quant_cli-0.1.7}/hamuna_quant_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|