# Walk-Forward Analysis

Walk-forward analysis is a method used in strategy backtesting to determine the robustness of a trading strategy. It involves optimizing strategy parameters over a specific time period (the "in-sample" period) and then testing those parameters on a subsequent, following period (the "out-of-sample" period).

The `walk_forward` function in `fastbt.simulation` automates this process by shifting the best-performing parameters from one period into the next.

## How it Works

1. **Partitioning**: The data is grouped into periods (e.g., Years, Months, Quarters) based on the `period` argument.
2. **In-Sample Optimization**: Within each period, the function calculates a performance metric (e.g., total profit, Sharpe ratio) for every combination of parameters provided.
3. **Selection**: It identifies the top `num` performing parameter combinations for that period.
4. **Out-of-Sample Application**: These "best" parameters are then "walked forward" (shifted) to the *next* period. The resulting DataFrame contains only the rows where the strategy would have been active using those previously optimized parameters.

---

## Basic Usage

The most common use case is picking the best-performing parameter from last year to trade this year.

```python
import pandas as pd
import numpy as np
from fastbt.simulation import walk_forward

# Assuming 'results_df' contains columns: ['Date', 'sma_fast', 'sma_slow', 'net_profit']
# And 'Date' is the index.

optimized_results = walk_forward(
    data=results_df,
    period='Y',               # Group by Year
    parameters=['sma_fast', 'sma_slow'],
    column='net_profit',      # Performance metric to rank by
    function='sum',           # How to aggregate the metric (total profit)
    num=1                     # Pick the single best combination
)

# 'optimized_results' now contains only the rows for each year 
# where the parameters match the winners from the PREVIOUS year.
```

---

## Configuration Options

### 1. Ranking Metric (`column` & `function`)
You can rank by any column in your DataFrame. The `function` argument determines how that column is aggregated over the period.
- **Total Profit**: `column='profit', function='sum'`
- **Average Return**: `column='return', function='mean'`
- **Custom**: You can pass any callable that accepts a Series.

### 2. Periodicity (`period`)
Use standard Pandas frequency aliases:
- `'Y'` or `'A'`: Annual
- `'Q'`: Quarterly
- `'M'`: Monthly
- `'W'`: Weekly

### 3. Selecting Bottom Performers
If you are analyzing failures or mean-reverting strategies, set `ascending=True` to pick the worst performers from the previous period.

```python
# Select the worst performing parameters to see if they mean-revert
results = walk_forward(data, period='M', parameters=['rsi_period'], 
                       column='returns', function='mean', ascending=True)
```

---

## Advanced: Portfolio Walk-Forward
If you want to pick the top 5 versions of a strategy (a "mini-ensemble") instead of just one, use the `num` parameter.

```python
# Pick the top 5 parameter sets from last quarter for the current quarter
ensemble_results = walk_forward(
    data=df,
    period='Q',
    parameters=['ma_period', 'std_dev'],
    column='sharpe_ratio',
    function='mean',
    num=5
)
```

---

## Why use Walk-Forward?

- **Prevents Overfitting**: Since the parameters are tested on data they haven't "seen" (the next period), it helps identify if a strategy has true predictive power or was just curve-fitted to a specific historical window.
- **Accounts for Market Regime Changes**: It acknowledges that "best" parameters might change over time as market volatility and trends shift.
- **Dynamic Optimization**: It simulates how a trader would actually operate—periodically re-optimizing their system based on recent history.
