Some checks failed
ci/woodpecker/push/woodpecker Pipeline was canceled
Composable: cursor/aggregator/strategy/publisher/audit_writer/broker all injected. Master kill-switch (kevin_enable_trading=false) routes to audit-only path. Cursor advances ONLY after XADD succeeds (race fix). Concrete collaborators wired in subsequent tasks. Also extends TradeSignal + SignalDirection.EXIT with the optional fields Kevin paths need (strategy_id, target_dollars, stop_loss_pct, take_profit_pct).
63 lines
1.7 KiB
Python
63 lines
1.7 KiB
Python
"""KevinBridgeConfig — env-var settings for the Kevin signal bridge service.
|
|
|
|
All env vars use the TRADING_ prefix consumed by shared.config.BaseConfig.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import json
|
|
from typing import Any
|
|
|
|
from pydantic import field_validator
|
|
|
|
from shared.config import BaseConfig
|
|
|
|
|
|
class KevinBridgeConfig(BaseConfig):
|
|
"""Env-var driven settings for the bridge service."""
|
|
|
|
# Signal translation
|
|
kevin_min_conviction: float = 0.60
|
|
kevin_max_mention_age_hours: int = 48
|
|
kevin_hold_days: dict[str, int] = {
|
|
"days": 3,
|
|
"weeks": 10,
|
|
"months": 45,
|
|
"long_term": 90,
|
|
"unspecified": 10,
|
|
}
|
|
|
|
# Sizing
|
|
kevin_base_position_pct: float = 0.04
|
|
kevin_min_trade_usd: float = 500.0
|
|
kevin_max_trade_usd: float = 5000.0
|
|
kevin_max_per_ticker_usd: float = 7500.0
|
|
|
|
# Exits
|
|
kevin_stop_loss_pct: float = 0.08
|
|
kevin_take_profit_pct: float = 0.20
|
|
kevin_avoid_closes_longs: bool = True
|
|
kevin_avoid_blocks_days: int = 7
|
|
|
|
# Aggregation
|
|
kevin_mention_boost_per_repeat: float = 0.05
|
|
kevin_max_mention_boost: float = 0.20
|
|
|
|
# Risk
|
|
kevin_max_position_pct: float = 0.075
|
|
kevin_daily_trade_cap: int = 5
|
|
kevin_daily_alloc_cap_usd: float = 15000.0
|
|
kevin_daily_loss_circuit_pct: float = 0.03
|
|
kevin_equity_drawdown_halt_pct: float = 0.80
|
|
|
|
# Plumbing
|
|
kevin_bridge_poll_interval_seconds: int = 60
|
|
kevin_bridge_exit_scan_cron: str = "35 9 * * 1-5"
|
|
kevin_enable_trading: bool = False # master kill-switch
|
|
|
|
@field_validator("kevin_hold_days", mode="before")
|
|
@classmethod
|
|
def _parse_hold_days(cls, v: Any) -> Any:
|
|
if isinstance(v, str):
|
|
return json.loads(v)
|
|
return v
|