fix(orchestrator): code quality fixes in config and signals
- config: remove hardcoded absolute path for quant_backtest_path (now empty string) - config: add llm_solo_penalty (0.7) and quant_solo_penalty (0.8) fields - signals: SignalMerger now accepts OrchestratorConfig in __init__ - signals: use config.llm_solo_penalty / quant_solo_penalty instead of magic numbers - signals: apply quant_weight_cap / llm_weight_cap as confidence upper bounds - signals: both-None branch raises ValueError instead of returning ticker="" - signals: replace assert with explicit ValueError for llm-None-when-quant-None - signals: replace datetime.utcnow() with datetime.now(timezone.utc)
This commit is contained in:
parent
56dc76d44a
commit
dacb3316fa
|
|
@ -3,9 +3,12 @@ from dataclasses import dataclass, field
|
|||
|
||||
@dataclass
|
||||
class OrchestratorConfig:
|
||||
quant_backtest_path: str = "/Users/chenshaojie/Downloads/quant_backtest"
|
||||
# Must be set to the local quant backtest output directory before use
|
||||
quant_backtest_path: str = ""
|
||||
trading_agents_config: dict = field(default_factory=dict)
|
||||
quant_weight_cap: float = 0.8 # quant 置信度上限
|
||||
llm_weight_cap: float = 0.9 # llm 置信度上限
|
||||
llm_batch_days: int = 7 # LLM 每隔几天运行一次(节省 API)
|
||||
cache_dir: str = "orchestrator/cache" # LLM 信号缓存目录
|
||||
llm_solo_penalty: float = 0.7 # LLM 单轨时的置信度折扣
|
||||
quant_solo_penalty: float = 0.8 # Quant 单轨时的置信度折扣
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
import logging
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from datetime import datetime, timezone
|
||||
from typing import Optional
|
||||
|
||||
from orchestrator.config import OrchestratorConfig
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
|
@ -36,30 +38,27 @@ def _sign(x: float) -> int:
|
|||
|
||||
|
||||
class SignalMerger:
|
||||
def __init__(self, config: OrchestratorConfig) -> None:
|
||||
self._config = config
|
||||
|
||||
def merge(self, quant: Optional[Signal], llm: Optional[Signal]) -> FinalSignal:
|
||||
now = datetime.utcnow()
|
||||
now = datetime.now(timezone.utc)
|
||||
|
||||
# 两者均失败
|
||||
if quant is None and llm is None:
|
||||
ticker = ""
|
||||
return FinalSignal(
|
||||
ticker=ticker,
|
||||
direction=0,
|
||||
confidence=0.0,
|
||||
quant_signal=None,
|
||||
llm_signal=None,
|
||||
timestamp=now,
|
||||
)
|
||||
raise ValueError("both quant and llm signals are None")
|
||||
|
||||
ticker = (quant or llm).ticker # type: ignore[union-attr]
|
||||
|
||||
# 只有 LLM(quant 失败)
|
||||
if quant is None:
|
||||
assert llm is not None
|
||||
if llm is None:
|
||||
raise ValueError("llm signal is None when quant is None")
|
||||
return FinalSignal(
|
||||
ticker=ticker,
|
||||
direction=llm.direction,
|
||||
confidence=llm.confidence * 0.7,
|
||||
confidence=min(llm.confidence * self._config.llm_solo_penalty,
|
||||
self._config.llm_weight_cap),
|
||||
quant_signal=None,
|
||||
llm_signal=llm,
|
||||
timestamp=now,
|
||||
|
|
@ -70,7 +69,8 @@ class SignalMerger:
|
|||
return FinalSignal(
|
||||
ticker=ticker,
|
||||
direction=quant.direction,
|
||||
confidence=quant.confidence * 0.8,
|
||||
confidence=min(quant.confidence * self._config.quant_solo_penalty,
|
||||
self._config.quant_weight_cap),
|
||||
quant_signal=quant,
|
||||
llm_signal=None,
|
||||
timestamp=now,
|
||||
|
|
@ -88,7 +88,9 @@ class SignalMerger:
|
|||
ticker,
|
||||
)
|
||||
total_conf = quant.confidence + llm.confidence
|
||||
final_confidence = abs(weighted_sum) / total_conf if total_conf > 0 else 0.0
|
||||
raw_confidence = abs(weighted_sum) / total_conf if total_conf > 0 else 0.0
|
||||
final_confidence = min(raw_confidence, self._config.quant_weight_cap,
|
||||
self._config.llm_weight_cap)
|
||||
|
||||
return FinalSignal(
|
||||
ticker=ticker,
|
||||
|
|
|
|||
Loading…
Reference in New Issue