Files
sanguo_vnpy_v2/sanguo_data/config.py
T
claude_dev ff84b3d4b0 feat(live): D-3 sanguo实盘分支(影子下单)+D期设计文档
D-3 模式A影子下单(spec §5):
- bridge_client.py: QMT bridge HTTP客户端(urllib, X-Bridge-Token, 失败不抛返回None)
- live_orchestrator: _shadow_trades_to_bridge 当日成交POST bridge(默认enabled=false)
- persistence: paper_shadow_orders幂等表+save_shadow_order/is_trade_shadowed
- config: data_platform.yaml加live段, token走env(BRIDGE_TOKEN)
- to_bridge_code symbol转换与guess_exchange一致(2位前缀)
安全: enabled=false默认关+token走env+幂等防重复+影子失败不阻断live_step

docs: phase3d-live-trading-design.md(D期完整设计)
2026-07-11 00:03:46 +08:00

48 lines
1.5 KiB
Python

# sanguo_data/config.py
from dataclasses import dataclass
import os
import yaml
@dataclass(frozen=True)
class DataConfig:
data_paths: dict
data_sources: dict
validation: dict
performance: dict
risk_free_rate: float = 0.02 # 年化无风险利率(spec §195 资金占用成本归因)
live: dict | None = None # 实盘集成(D期 spec §5),None/缺省=disabled
def load_config(path: str) -> DataConfig:
try:
with open(path, "r", encoding="utf-8") as f:
raw = yaml.safe_load(f)
except FileNotFoundError:
raise FileNotFoundError(f"配置文件不存在: {path}")
except yaml.YAMLError as e:
raise ValueError(f"YAML解析失败: {e}")
if not raw:
raise ValueError(f"配置文件为空: {path}")
return DataConfig(
data_paths=raw.get("data_paths", {}),
data_sources=raw.get("data_sources", {}),
validation=raw.get("validation", {}),
performance=raw.get("performance", {}),
risk_free_rate=float(raw.get("risk_free_rate", 0.02)),
live=raw.get("live"),
)
def find_config_path() -> str:
"""Locate data_platform.yaml: container /app/config first, then repo config/."""
candidates = [
"/app/config/data_platform.yaml",
os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "config", "data_platform.yaml"),
"config/data_platform.yaml",
]
for p in candidates:
if os.path.exists(p):
return p
return candidates[0]