Spaces:
Runtime error
Runtime error
| """Configuration management β stores settings in ~/.config/trading-cli/config.toml.""" | |
| from __future__ import annotations | |
| import toml | |
| from pathlib import Path | |
| CONFIG_DIR = Path("~/.config/trading-cli").expanduser() | |
| CONFIG_PATH = CONFIG_DIR / "config.toml" | |
| DB_PATH = CONFIG_DIR / "trades.db" | |
| DEFAULT_CONFIG: dict = { | |
| "alpaca_api_key": "", | |
| "alpaca_api_secret": "", | |
| "alpaca_paper": True, | |
| "adapter_id": "alpaca", | |
| "auto_trading": True, | |
| "sentiment_model": "finbert", | |
| "strategy_id": "trend_following", | |
| "risk_pct": 0.02, | |
| "max_drawdown": 0.15, | |
| "stop_loss_pct": 0.05, | |
| "max_positions": 10, | |
| "default_symbols": ["AAPL", "TSLA", "NVDA"], | |
| "poll_interval_prices": 30, | |
| "poll_interval_news": 900, | |
| "poll_interval_signals": 60, | |
| "poll_interval_positions": 60, | |
| "initial_cash": 100000.0, | |
| "finbert_batch_size": 50, | |
| "debug_fast_cycle": True, | |
| "sma_short": 20, | |
| "sma_long": 50, | |
| "rsi_period": 14, | |
| "signal_buy_threshold": 0.15, | |
| "signal_sell_threshold": -0.15, | |
| "position_size_warning": 1000.0, | |
| # ββ Strategy weights ββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "tech_weight": 0.6, | |
| "sent_weight": 0.4, | |
| # ββ Technical indicator weights βββββββββββββββββββββββββββββββββββββββββββ | |
| "weight_sma": 0.25, | |
| "weight_rsi": 0.25, | |
| "weight_bb": 0.20, | |
| "weight_ema": 0.15, | |
| "weight_volume": 0.15, | |
| # ββ Bollinger Bands βββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "bb_window": 20, | |
| "bb_std": 2.0, | |
| # ββ EMA periods βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "ema_fast": 12, | |
| "ema_slow": 26, | |
| # ββ Volume SMA window βββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| "volume_window": 20, | |
| # ββ Sentiment event weights βββββββββββββββββββββββββββββββββββββββββββββββ | |
| "event_weight_earnings": 1.5, | |
| "event_weight_executive": 1.3, | |
| "event_weight_product": 1.2, | |
| "event_weight_macro": 1.4, | |
| "event_weight_generic": 0.8, | |
| "sentiment_half_life_hours": 24.0, | |
| } | |
| def load_config() -> dict: | |
| """Load config from disk, creating defaults if absent.""" | |
| CONFIG_DIR.mkdir(parents=True, exist_ok=True) | |
| if not CONFIG_PATH.exists(): | |
| save_config(DEFAULT_CONFIG) | |
| return dict(DEFAULT_CONFIG) | |
| with open(CONFIG_PATH) as f: | |
| on_disk = toml.load(f) | |
| merged = dict(DEFAULT_CONFIG) | |
| merged.update(on_disk) | |
| return merged | |
| def save_config(config: dict) -> None: | |
| """Persist config to disk.""" | |
| CONFIG_DIR.mkdir(parents=True, exist_ok=True) | |
| with open(CONFIG_PATH, "w") as f: | |
| toml.dump(config, f) | |
| def get_db_path() -> Path: | |
| CONFIG_DIR.mkdir(parents=True, exist_ok=True) | |
| return DB_PATH | |
| def is_demo_mode(config: dict) -> bool: | |
| """True if Alpaca keys are not configured.""" | |
| return not (config.get("alpaca_api_key") and config.get("alpaca_api_secret")) | |