"""Central configuration: paths, universe, and backtest parameters.

Keeping every tunable in one place makes ``python run.py`` fully reproducible
and makes the in-sample / out-of-sample split explicit.
"""
from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path

# ----------------------------------------------------------------------------
# Paths
# ----------------------------------------------------------------------------
ROOT = Path(__file__).resolve().parent.parent
DATA_DIR = ROOT / "data"
RESULTS_DIR = ROOT / "results"
PRICE_CACHE = DATA_DIR / "prices.csv.gz"
FACTOR_CACHE = DATA_DIR / "ff_factors.csv.gz"

# Global seed for every RNG used in the project.
SEED = 42

# ----------------------------------------------------------------------------
# Sample window
# ----------------------------------------------------------------------------
START = "2010-01-01"
END = "2024-12-31"

# In-sample window is used to *select* the MAX(N) parameter; the out-of-sample
# window is used only to *evaluate* the chosen strategy.  The split is by date
# so there is no overlap and no peeking.
IS_END = "2017-12-31"   # in-sample:  START .. IS_END
OOS_START = "2018-01-01"  # out-of-sample: OOS_START .. END

# ----------------------------------------------------------------------------
# Strategy parameters
# ----------------------------------------------------------------------------
N_QUINTILES = 5
# Candidate MAX(N) definitions evaluated in-sample.  N is the number of the
# highest daily returns within the formation month that get averaged.
MAX_N_GRID = (1, 3, 5)
DEFAULT_MAX_N = 5
# Minimum number of valid daily returns within a formation month for a stock to
# receive a signal that month (guards against thinly-traded / halted names).
MIN_DAYS_IN_MONTH = 15
# One-way proportional transaction cost in basis points, charged on the dollar
# value traded (|Δweight|) at every monthly rebalance, on both the long and the
# short leg.  10 bps one-way is a conservative estimate for liquid large caps.
COST_BPS = 10.0
# Trading days used to estimate idiosyncratic volatility (rolling, daily FF3).
IVOL_WINDOW = 21

# ----------------------------------------------------------------------------
# Universe: a broad, liquid large-cap set (S&P 100-style names across sectors).
# Survivorship is acknowledged in the README; delisted/missing names are handled
# gracefully by the data layer rather than crashing the run.
# ----------------------------------------------------------------------------
UNIVERSE: tuple[str, ...] = (
    # Technology / communication
    "AAPL", "MSFT", "NVDA", "AVGO", "ORCL", "CSCO", "ADBE", "CRM", "ACN", "IBM",
    "INTC", "QCOM", "TXN", "AMD", "MU", "AMAT", "INTU", "NOW",
    "GOOGL", "META", "NFLX", "DIS", "CMCSA", "T", "VZ", "TMUS",
    # Consumer
    "AMZN", "TSLA", "HD", "MCD", "NKE", "SBUX", "LOW", "TGT", "BKNG",
    "PG", "KO", "PEP", "COST", "WMT", "MDLZ", "CL", "MO", "PM",
    # Health care
    "UNH", "JNJ", "LLY", "PFE", "MRK", "ABBV", "TMO", "ABT", "DHR", "BMY",
    "AMGN", "GILD", "CVS", "MDT", "ISRG",
    # Financials
    "BRK-B", "JPM", "BAC", "WFC", "C", "GS", "MS", "AXP", "BLK", "SPGI",
    "SCHW", "USB", "PNC", "CB", "MMC",
    # Industrials / energy / materials / utilities
    "BA", "CAT", "GE", "HON", "UPS", "RTX", "LMT", "DE", "MMM", "UNP",
    "XOM", "CVX", "COP", "SLB", "EOG",
    "LIN", "APD", "NEE", "DUK", "SO",
)

# Number of bootstrap resamples for confidence intervals on headline metrics.
N_BOOTSTRAP = 1000


@dataclass(frozen=True)
class BacktestParams:
    """Bundle of parameters consumed by the backtest engine."""

    max_n: int = DEFAULT_MAX_N
    n_quintiles: int = N_QUINTILES
    cost_bps: float = COST_BPS
    min_days_in_month: int = MIN_DAYS_IN_MONTH
    seed: int = SEED


def ensure_dirs() -> None:
    """Create output directories if they do not already exist."""
    DATA_DIR.mkdir(parents=True, exist_ok=True)
    RESULTS_DIR.mkdir(parents=True, exist_ok=True)
