Quant BuffetRelax, Not Over Thinking

Quant Buffet API

Data API

load_daily_prices and price panel conventions.

Market data lives in `backtest.data`. The lab uses adjusted daily closes from Yahoo Finance, cached under backtest/data_cache/ for repeat runs.

load_daily_prices

prices = load_daily_prices(
    ["SPY", "TLT", "GLD"],
    start="2010-01-01",
    end=None,          # optional end date "YYYY-MM-DD"
    use_cache=True,    # default: read/write backtest/data_cache/
    strict=False,      # if True, raise on first symbol failure
)
# prices: pd.DataFrame — DatetimeIndex rows, one column per ticker (adjusted close)
ParameterDefaultDescription
symbolsList of ticker strings, e.g. ["SPY", "TLT"].
start"2000-01-01"Inclusive start date (ISO string).
endNoneOptional exclusive end; None means latest available.
use_cacheTrueRead/write CSV cache files keyed by symbol and date range.
strictFalseIf True, raise on first symbol failure instead of skipping.

Return value

  • `pd.DataFrame` indexed by `DatetimeIndex` (timezone-naive).
  • One float column per symbol that loaded successfully.
  • Missing days within a series are forward-filled; pre-IPO history stays NaN until first print.
  • Failed symbols are omitted unless strict=True. Partial failures attach prices.attrs["load_errors"] when some symbols fail.

load_price_panel (optional)

from backtest.data import load_price_panel

prices, missing = load_price_panel(["SPY", "XYZ"], start="2010-01-01")
# missing: list of symbols with no data

Working with the panel

  • Filter columns: cols = [c for c in ASSETS if c in prices.columns].
  • Rolling windows: prices[cols].rolling(20, min_periods=20).mean().
  • Cross-sectional ranks: rets.rank(axis=1, ascending=False).
  • Align to engine dates: series.reindex(engine_index).ffill().