79 lines
3.0 KiB
Python
79 lines
3.0 KiB
Python
"""Tests for sanguo_api.strategy_registry (Task S1.3)."""
|
|
from sanguo_api.strategy_registry import (
|
|
list_strategies, strategy_params, STRATEGY_NAMES,
|
|
list_strategy_files, read_strategy_file, get_strategy_class,
|
|
)
|
|
|
|
|
|
def test_list_strategies_shape():
|
|
items = list_strategies()
|
|
assert isinstance(items, list)
|
|
assert len(items) > 0
|
|
for item in items:
|
|
assert "name" in item and "class_name" in item
|
|
|
|
|
|
def test_list_strategies_fallback_when_unimportable():
|
|
"""Locally vnpy_ctastrategy is absent → falls back to STRATEGY_NAMES."""
|
|
names = {item["name"] for item in list_strategies()}
|
|
# At minimum the fallback names appear (DoubleMaStrategy must be listed)
|
|
assert "DoubleMaStrategy" in names or len(names) > 0
|
|
|
|
|
|
def test_strategy_params_keys():
|
|
p = strategy_params("DoubleMaStrategy")
|
|
assert "parameters" in p
|
|
assert isinstance(p["parameters"], list)
|
|
assert "defaults" in p and isinstance(p["defaults"], dict)
|
|
|
|
|
|
def test_strategy_params_unknown_returns_empty():
|
|
p = strategy_params("NoSuchStrategy_xyz")
|
|
assert p == {"parameters": [], "defaults": {}}
|
|
|
|
|
|
def test_list_strategy_files_returns_dirs():
|
|
data = list_strategy_files()
|
|
assert "files" in data and isinstance(data["files"], list)
|
|
dirs = {f["dir"] for f in data["files"]}
|
|
# 自研目录至少出现一个(sanguo_portfolio/strategies 有真实策略文件)
|
|
assert any("sanguo_trader/strategy" in d or "sanguo_portfolio/strategies" in d for d in dirs)
|
|
|
|
|
|
def test_list_strategy_files_item_shape():
|
|
data = list_strategy_files()
|
|
if not data["files"]:
|
|
return
|
|
f = data["files"][0]
|
|
for k in ("name", "dir", "class_name", "type"):
|
|
assert k in f
|
|
|
|
|
|
def test_read_strategy_file_returns_code():
|
|
data = list_strategy_files()
|
|
if not data["files"]:
|
|
return
|
|
f = data["files"][0]
|
|
content = read_strategy_file(f["name"])
|
|
assert "code" in content and isinstance(content["code"], str)
|
|
assert content["class_name"] == f["class_name"]
|
|
|
|
|
|
def test_vnpy_builtin_copies_classified_cta():
|
|
"""灌入的 vnpy 内置模板(from vnpy_ctastrategy import ...)必须判成 cta。"""
|
|
data = list_strategy_files()
|
|
cta_files = {f["name"]: f for f in data["files"] if f["dir"] == "sanguo_trader/strategy/"}
|
|
assert "double_ma_strategy.py" in cta_files, "内置策略模板未灌入 sanguo_trader/strategy"
|
|
assert cta_files["double_ma_strategy.py"]["type"] == "cta"
|
|
assert cta_files["double_ma_strategy.py"]["class_name"] == "DoubleMaStrategy"
|
|
|
|
|
|
def test_get_strategy_class_self_owned_priority_or_fallback():
|
|
"""有 vnpy_ctastrategy 环境:自研目录类可加载;无:优雅返 None/降级不崩。"""
|
|
cls = get_strategy_class("DoubleMaStrategy")
|
|
# 本机 dev 无 vnpy_ctastrategy 时 pip 侧也拿不到 → None 不崩即可;
|
|
# 容器内应返回 sanguo_trader.strategy.double_ma_strategy 的类(自研优先)
|
|
if cls is not None:
|
|
assert cls.__name__ == "DoubleMaStrategy"
|
|
assert cls.__module__.startswith("sanguo_trader.strategy")
|