finagent / crew /config.py
emmanuelakbi's picture
feat(prefs): risk tolerance + trading style now shape the signal
1e840aa
"""LLM configuration, timeouts, and constants for the orchestration layer."""
from dataclasses import dataclass, field
from typing import Literal
RiskTolerance = Literal["Conservative", "Moderate", "Aggressive"]
TradingStyle = Literal["Day Trading", "Swing Trading", "Position Trading"]
@dataclass(frozen=True)
class TradePreferences:
"""User-selected risk / style / portfolio preferences.
These come from the Gradio UI dropdowns and are threaded end-to-end
into the Chief Strategist's task description so the final signal
reflects the user's stated profile. They also tune the re-ground
clamps in :class:`FinAgentCrew` — Conservative + Day Trading pushes
stop / target toward tight, short-horizon bands; Aggressive +
Position Trading opens them up.
Numbers here are percentages of entry (0.03 == 3 %).
"""
risk_tolerance: RiskTolerance = "Moderate"
trading_style: TradingStyle = "Swing Trading"
portfolio_value: float = 10000.0
@property
def stop_pct(self) -> float:
return {
"Conservative": 0.015,
"Moderate": 0.03,
"Aggressive": 0.05,
}[self.risk_tolerance]
@property
def target_pct(self) -> float:
return {
"Day Trading": 0.02,
"Swing Trading": 0.05,
"Position Trading": 0.10,
}[self.trading_style]
@property
def stop_clamp(self) -> float:
"""Upper bound used by _reground_if_drifted. Slightly looser than
``stop_pct`` so the LLM has headroom, but tight enough to catch
the wide ATR-style stops Qwen sometimes emits."""
return self.stop_pct * 2.5
@property
def target_clamp(self) -> float:
return self.target_pct * 3.0
@dataclass
class LLMConfig:
"""Configuration for the vLLM endpoint connection."""
base_url: str = "http://localhost:8000/v1"
model_name: str = "Qwen/Qwen3-14B"
temperature: float = 0.7
max_tokens: int = 1024
request_timeout: int = 120 # seconds
@dataclass
class CrewConfig:
"""Configuration for crew execution parameters."""
max_iterations: int = 5
task_timeout: int = 120 # seconds per task
verbose: bool = True
@dataclass
class OrchestratorConfig:
"""Top-level configuration combining all settings."""
llm: LLMConfig = field(default_factory=LLMConfig)
crew: CrewConfig = field(default_factory=CrewConfig)