Swing_Quant_Engine / config.py
SiddharthVenba's picture
Initial commit for HF Space
75d9b3c
Raw
History Blame Contribute Delete
4.74 kB
"""
Swing Quant Engine β€” Central Configuration
All tunable parameters, universe definitions, and thresholds.
"""
import os
from pathlib import Path
from dotenv import load_dotenv
# ── Paths ──
BASE_DIR = Path(__file__).parent
DATA_DIR = BASE_DIR / "data"
PARQUET_DIR = DATA_DIR / "parquet"
DB_PATH = DATA_DIR / "quant.db"
# Ensure dirs exist
DATA_DIR.mkdir(exist_ok=True)
PARQUET_DIR.mkdir(exist_ok=True)
# Load env from portfolio_website if local .env doesn't exist
_local_env = BASE_DIR / ".env"
_portfolio_env = BASE_DIR.parent / "portfolio_website" / ".env"
if _local_env.exists():
load_dotenv(_local_env)
elif _portfolio_env.exists():
load_dotenv(_portfolio_env)
# ── API Keys ──
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY", "")
OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini")
PERPLEXITY_API_KEY = os.getenv("PERPLEXITY_API_KEY", "")
FINNHUB_API_KEY = os.getenv("FINNHUB_API_KEY", "")
# ── Stock Universe ──
# Indian blue-chips (NSE) β€” top Nifty 50 + select mid-caps
INDIA_UNIVERSE = [
"RELIANCE.NS", "TCS.NS", "HDFCBANK.NS", "INFY.NS", "ICICIBANK.NS",
"HINDUNILVR.NS", "BHARTIARTL.NS", "SBIN.NS", "ITC.NS", "KOTAKBANK.NS",
"LT.NS", "AXISBANK.NS", "BAJFINANCE.NS", "ASIANPAINT.NS", "MARUTI.NS",
"HCLTECH.NS", "WIPRO.NS", "SUNPHARMA.NS", "TITAN.NS", "ULTRACEMCO.NS",
"ONGC.NS", "NTPC.NS", "POWERGRID.NS", "TATAMOTORS.NS", "TATASTEEL.NS",
"ADANIENT.NS", "ADANIPORTS.NS", "COALINDIA.NS", "JSWSTEEL.NS", "M&M.NS",
"BAJAJ-AUTO.NS", "TECHM.NS", "HEROMOTOCO.NS", "DRREDDY.NS", "CIPLA.NS",
"DIVISLAB.NS", "APOLLOHOSP.NS", "EICHERMOT.NS", "BPCL.NS", "GRASIM.NS",
"TATACONSUM.NS", "NESTLEIND.NS", "BRITANNIA.NS", "INDUSINDBK.NS",
"HINDALCO.NS", "SBILIFE.NS", "HDFCLIFE.NS", "BAJAJFINSV.NS",
"SHREECEM.NS", "PIDILITIND.NS",
]
# US blue-chips β€” S&P 100 subset
US_UNIVERSE = [
"AAPL", "MSFT", "GOOGL", "AMZN", "NVDA", "META", "TSLA", "BRK-B",
"UNH", "JNJ", "V", "XOM", "JPM", "PG", "MA", "HD", "CVX", "MRK",
"ABBV", "LLY", "PEP", "KO", "COST", "AVGO", "WMT", "MCD", "CSCO",
"ACN", "TMO", "ABT", "DHR", "NEE", "LIN", "PM", "TXN", "UNP",
"RTX", "HON", "LOW", "AMGN", "COP", "QCOM", "ORCL", "GS", "BAC",
"CAT", "SBUX", "AXP", "PFE", "AMD",
]
# Combined default universe
DEFAULT_UNIVERSE = INDIA_UNIVERSE + US_UNIVERSE
# ── Technical Signal Thresholds ──
SIGNAL_PARAMS = {
# RSI
"rsi_oversold": 30,
"rsi_overbought": 75,
"rsi_bullish_zone": (45, 76), # Tightened momentum sweet spot
# MACD
"macd_fast": 12,
"macd_slow": 26,
"macd_signal": 9,
# Bollinger Bands
"bb_period": 20,
"bb_std": 2.0,
# Moving Averages
"sma_short": 20,
"sma_medium": 50,
"sma_long": 200,
"ema_fast": 9,
"ema_slow": 21,
# Volume
"volume_spike_threshold": 2.0, # Increased to 2.0x avg volume for higher conviction
"volume_sma_period": 20,
# ADX (trend strength)
"adx_trending": 25, # ADX > 25 = trending market
# ATR
"atr_period": 14,
# Breakout
"breakout_lookback": 20, # days to look for resistance
"breakout_volume_confirm": 1.3, # min volume multiplier for confirmation
}
# ── Risk Parameters ──
RISK_PARAMS = {
"max_position_pct": 5.0, # Max 5% of portfolio in one position
"max_sector_pct": 15.0, # Reduced to 15% for better diversification
"max_drawdown_pct": 15.0, # Kill switch at 15% portfolio drawdown
"min_liquidity_inr": 5_00_00_000, # β‚Ή5Cr daily volume for India
"min_liquidity_usd": 10_000_000, # $10M daily volume for US
"max_atr_pct": 5.0, # Skip stocks with ATR% > 5%
"max_correlation": 0.85, # Reject if corr > 0.85 with existing
"kelly_fraction": 0.25, # Use 25% of Kelly optimal (conservative)
}
# ── Alpha Scoring Weights ──
ALPHA_WEIGHTS = {
"momentum": 0.35,
"volume_breakout": 0.20,
"sentiment": 0.20,
"regime_fit": 0.15,
"fundamental": 0.10,
}
# ── Scan Schedule ──
SCAN_INTERVAL_HOURS = 4 # Re-scan every 4 hours during market hours
# ── Market Hours (for scheduling) ──
MARKET_HOURS = {
"india": {"open": "09:15", "close": "15:30", "tz": "Asia/Kolkata"},
"us": {"open": "09:30", "close": "16:00", "tz": "America/New_York"},
}
# ── Backtest Defaults ──
BACKTEST_PARAMS = {
"in_sample_months": 12,#6
"out_sample_months": 3,#1
"commission_india_pct": 0.1,
"commission_us_pct": 0.05,
"slippage_pct": 0.05,
"initial_capital": 10_00_000, # β‚Ή10L or $10K equivalent
}
# ── Logging ──
import logging
LOG_FORMAT = "%(asctime)s [%(levelname)s] %(name)s: %(message)s"
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)