.. _methodology: Backtest Methodology ==================== This page explains the assumptions and calculations the engine applies during a simulation. Price Roles ----------- The engine uses **three distinct prices** for different purposes. This separation reflects how institutional trading actually works — execution, commission calculation, and valuation each reference different price sources. .. list-table:: :widths: 25 30 45 :header-rows: 1 * - Role - Default recommendation - Rationale * - **Execution price** - Split/dividend-adjusted VWAP - The realistic average fill price throughout the trading day, adjusted for splits and dividends. * - **Commission price** - Unadjusted VWAP - Commissions are charged on the nominal share count at the market price, not on adjusted prices. * - **Mark-to-market price** - Split/dividend-adjusted close - The standard end-of-day reference price used universally for historical performance measurement. All three roles can be set to the same column if your data only has one price. Rebalancing Dates and Date Format --------------------------------- Dates in the portfolio file must use the **ISO 8601 format ``YYYY-MM-DD``** (e.g., ``2024-03-15``). All date columns are normalized to this format during ingestion. **Rebalancing occurs on the exact date specified in the portfolio file — not on the following trading day (t+1).** When the engine encounters a date in the weights file, it executes the rebalance that same day using that day's execution, commission, and mark-to-market prices. The date in the file is the effective rebalancing date taken into account for portfolio holdings and valuation. Execution Model --------------- On each rebalancing date defined in the portfolio file: 1. **Target exposure** is calculated as ``available_capital × weight`` per ticker. 2. **Share count** is computed as ``floor(dollar_exposure / execution_price)`` — fractional shares are not supported. 3. **Sell orders execute before buy orders** to free up capital. 4. **Liquidation**: when a ticker's target weight is zero, the entire position is sold at the exact share count held (no rounding). 5. **Commission** is calculated using the commission price: ``floor(dollar_exposure / commission_price) × commission_cents``. 6. **Slippage**: a pluggable model applied to the execution price after share calculation. The default applies no slippage. Cash Reserve ------------ A configurable percentage of total portfolio value is held as cash on every rebalancing date. This acts as a buffer for transaction costs and rebalancing friction. .. math:: \text{capital\_to\_invest} = \text{total\_portfolio\_value} \times (1 - \text{cash\_reserve\_percentage}) Daily Valuation --------------- Between rebalancing dates, portfolio value is computed using the mark-to-market price: .. math:: \text{portfolio\_value} = \sum_{\text{ticker}} \text{shares\_held} \times \text{mark\_to\_market\_price} .. math:: \text{total\_value} = \text{portfolio\_value} + \text{cash\_position} Daily returns are the percentage change of ``total_value``. Performance Metrics ------------------- All metrics are computed on the daily returns series. The full implementation is in: .. automodule:: kaxanuk.backtest_engine.modules.metrics :members: :undoc-members: :show-inheritance: :noindex: