"""Slipstream Space config — everything from env (HF Space secrets) + local data. No cross-project paths: the signal bundle and the risk-screen cache ship inside the Space.""" import os import re from pathlib import Path APP_DIR = Path(__file__).resolve().parent DATA_DIR = APP_DIR / "data" # --- secrets (set these in the HF Space settings) --- ALPACA_API_KEY = os.getenv("ALPACA_API_KEY", "") ALPACA_SECRET_KEY = os.getenv("ALPACA_SECRET_KEY", "") ALPACA_ENDPOINT = re.sub( r"/v2/?$", "", os.getenv("ALPACA_PAPER_ENDPOINT", "https://paper-api.alpaca.markets").rstrip("/") ) ALPACA_ALLOW_LIVE = os.getenv("ALPACA_ALLOW_LIVE", "0") == "1" # Gemini runs the AI event-risk overlay (risk_screen.py). Flash-Lite is optimal here: a # well-specified batched classification (not heavy reasoning), so Lite is fast (~1s), cheap, # quota-generous (the thinking-tier Flash models 429 on free keys), and "-latest" never deprecates. GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") or os.getenv("GOOGLE_API_KEY", "") GEMINI_MODEL = os.getenv("GEMINI_MODEL", "gemini-flash-lite-latest") # rebalance execution guard: the Space only trades when this is set (belt-and-braces # on top of paper-only). Set REBALANCE_TOKEN as a secret to enable the trigger. REBALANCE_TOKEN = os.getenv("REBALANCE_TOKEN", "") # executor: size the book off (1 - CASH_BUFFER) x equity, never 100%. A fully-invested target plus # the min-trade deadband (small overweights are never sold) left the paper account on a standing # margin balance; ~1% cash absorbs fill slippage and drift. See alpaca_client.plan_rebalance. CASH_BUFFER = float(os.getenv("SLIPSTREAM_CASH_BUFFER", "0.01")) HTTP_TIMEOUT = 25 # The informational "Top AI Picks of the Month" panels live on the Signalflow Space. SIGNALFLOW_URL = os.getenv("SIGNALFLOW_URL", "https://s-ttp-signalflow.hf.space") def alpaca_is_paper() -> bool: return "paper-api" in ALPACA_ENDPOINT