Files
signal-platform/app/config.py
T
dennisthiessen 099846513b
Deploy / lint (push) Successful in 7s
Deploy / test (push) Successful in 39s
Deploy / deploy (push) Successful in 25s
deepen OHLCV history + make the factor-IC pass honest about overlap/regime
Two changes so the cross-sectional signal results can actually be trusted.

(a) History depth — the binding constraint. Ingestion defaulted to 365 days, so
long-lookback factors (12-month momentum, 52-week high) were only computable on a
handful of weeks at the tail, and every IC reflected a single market regime.
- New `settings.ohlcv_history_days` (default 1825 ≈ 5y); new tickers backfill this
  far instead of 1 year.
- New manual "data_backfill" job (Admin → Jobs) re-fetches the full window for
  every ticker, ignoring incremental resume — run once to deepen existing
  1-year histories. Idempotent (upsert); resumes after rate limits.

(b) Factor-IC honesty. The IC was averaged over weekly rebalances whose 30-day
forward windows overlap, inflating the t-stat ~sqrt(6)x.
- IC now measured on NON-OVERLAPPING windows (weeks thinned to ~HORIZON apart).
- Each signal carries a `reliable` flag (>= 12 independent windows); BacktestPanel
  greys out and de-stars thin signals so a lucky 9-week IC of 0.3 can't masquerade
  as an edge.

332 backend tests pass; frontend build clean. No migration (config + job + an
added JSON field on the cached backtest report).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 18:20:59 +02:00

85 lines
3.0 KiB
Python

from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(env_file=".env", env_file_encoding="utf-8")
# Database
database_url: str = "postgresql+asyncpg://stock_backend:changeme@localhost:5432/stock_data_backend"
# Auth
jwt_secret: str = "change-this-to-a-random-secret"
jwt_expiry_minutes: int = 60
# OHLCV Provider — Alpaca Markets
alpaca_api_key: str = ""
alpaca_api_secret: str = ""
# Sentiment Provider — Gemini with Search Grounding (legacy)
gemini_api_key: str = ""
gemini_model: str = "gemini-2.0-flash"
# Sentiment Provider — OpenAI
openai_api_key: str = ""
openai_model: str = "gpt-4o-mini"
openai_sentiment_batch_size: int = 5
# Sentiment Provider — DeepSeek / xAI (OpenAI-compatible; optional env fallback)
deepseek_api_key: str = ""
xai_api_key: str = ""
# Fundamentals Provider — Financial Modeling Prep
fmp_api_key: str = ""
# Fundamentals Provider — Finnhub (optional fallback)
finnhub_api_key: str = ""
# Fundamentals Provider — Alpha Vantage (optional fallback)
alpha_vantage_api_key: str = ""
# Alerts — Telegram (optional env fallback; can also be set in Admin)
telegram_bot_token: str = ""
telegram_chat_id: str = ""
# Scheduled Jobs
data_collector_frequency: str = "daily"
sentiment_poll_interval_minutes: int = 30
# Sentiment search-budget controls (Gemini grounding free tier = 5000/month).
# Only fetch sentiment for relevant tickers (watchlist + open trades + top-N by
# composite), skip ones refreshed within fresh_hours, and cap per run.
sentiment_fresh_hours: int = 72
sentiment_max_per_run: int = 25
sentiment_top_composite: int = 30
fundamental_fetch_frequency: str = "weekly" # quarterly-ish data; weekly conserves API quota
rr_scan_frequency: str = "daily"
alerts_frequency: str = "hourly"
fundamental_rate_limit_retries: int = 3
fundamental_rate_limit_backoff_seconds: int = 15
# Pause between tickers in the bulk fundamentals job. Free tiers throttle
# hard (Finnhub ~60 calls/min, ~3 calls/ticker → ~3s/ticker); without
# spacing the job bursts straight into 429s. 0 disables.
fundamental_request_spacing_seconds: float = 3.0
# Scoring Defaults
default_watchlist_auto_size: int = 10
default_rr_threshold: float = 1.5
# Outcome evaluation: trading days before an undecided setup expires
outcome_evaluation_max_bars: int = 30
# OHLCV history depth to fetch. New tickers backfill this far; the manual
# "data_backfill" job re-fetches the full window for everyone. ~5 years so
# long-lookback factors (12-month momentum, 52-week high) and multi-regime
# backtests become computable. ~252 trading days/year.
ohlcv_history_days: int = 1825
# Database Pool
db_pool_size: int = 5
db_pool_timeout: int = 30
# Logging
log_level: str = "INFO"
settings = Settings()