# Python Backtesting & Optimization Workflow

This repository contains a Python-based framework for validating, optimizing, and stress-testing trading strategies. This framework is designed to replicate and extend the functionality of Pine Script strategies.

## Core Components

### 1. Strategy Logic (`strategies/`)
*   **Strategy Files** (e.g., `strategy_activation_scores.py`): These contain the core trading logic, which in the case of this strategy is just importing indicator values from TradingView from the 'TV_Export.csv' then multiplying them by weights and and if those products cross the entry or activation thresholds then a trade is executed.
*   **Parameter Configs** (e.g., `params_strategy_activation_scores.json`): JSON files defining the search space (start, stop, step) for strategy parameters during optimization.

### 2. Tools

#### A. Validation (`strategies/validate_strategy.py`)
Runs a single backtest using specific parameters.
*   **Goal:** Verify that the Python logic matches Pine Script results or check the performance of a specific parameter set.
*   **Output:** Prints Total P&L, Drawdown, Sharpe Ratio, Sortino ratio and optionally a list of trades.
*   **Usage:**
    ```bash
    python strategies/validate_strategy.py --data results/TV_Export.csv --strategy_file strategy_activation_scores.py --show-trades
    ```

#### B. Optimization (`strategies/optimize_strategy.py`)
Performs a Grid Search over the parameter ranges defined in the JSON config.
*   **Goal:** Find the parameter combination that yields the highest Sharpe Ratio.
*   **Output:** Saves a CSV of all results (`results/optimization_sweep_*.csv`) and the winning parameters (`results/optimization_winner_*.csv`).
*   **Usage:**
    ```bash
    python strategies/optimize_strategy.py --data data/MY_DATA.csv --strategy_file strategy_activation_scores.py
    ```

#### C. Walk-Forward Analysis (`backtester/walk_forward_runner.py`)
Performs a rolling window analysis (Train on past data -> Test on future data).
*   **Goal:** Test the robustness of the strategy and the optimization process itself. Prevents overfitting by ensuring parameters work on unseen data.
*   **Output:** Prints a step-by-step log of In-Sample vs Out-of-Sample performance and saves a detailed CSV to `results/`.
*   **Usage:**
    ```bash
    python backtester/walk_forward_runner.py --data data/MY_DATA.csv --strategy_file strategy_activation_scores.py --train_months 12 --test_months 1
    ```

## Porting & Adding New Strategies

When converting a strategy from Pine Script (`.pine`) to Python (`.py`), follow these standards to ensure consistency and compatibility.

### 1. File Naming & Structure
*   **Strategies:** Convert the Pine Script filename to **snake_case** and prefix with `strategy_`.
    *   *Pine:* `strategies/strategy_activation_scores.pine` Gets run on TradingView.com and has a recently updated set of weights, which should match the optimized weights saved in `results/optimization_winner_activation_scores.csv` as the default input weight values. This strategy calls the relevant libraries with the OHLCV values from TradingView and multiplies the result from each of these libraries by the appropriate weight, then sums all of the products into `activation_score_poc` and compares this to the entry and exit thresholds to decide if a trade should be entered if not already in a trade, exited if already in a trade or do nothing. Note: There are also optional entry and exitconfirmation booleans and values which, if enabled, require that the confirmation threshold be met on the subsequent bar to allow the trade to occur. Export of many of the relevant component variable values and activation_score_poc are saved to `data/Export-TV.csv`
    *   *Pine:* `strategies/strategy_activation_scores_debug.pine` Same as above, but plots all of the component values and in the exported CSV, prepends all fields with "DB_" and included in the same `data/Export-TV.csv`. Having both enabled and contributing to the same CSV might be confusing and unnecessary, I can turn off either one if needed.
    *   *Python:* `strategies/strategy_activation_scores.py`. This version of the strategy SHOULD be very stripped down. It should just read in the component values provided in `data/Export-TV.csv` and multiply each of those by the relevant weights being tested, to then determine if a long entry, long exit or neither should occur in this local calculation. The reason for running this locally is to take advantage of the local GPU for testing vast quantities of combinations of weight values quickly in order to find weights that maximize the Sortino Ratio. Notice: SHOULD was in all caps as it needs to be confirmed that this python version of the strategy is not trying to calculate its own component values as these could differ and be a source of divergence in the calculation of the sum of the products

### 2. Strategy Logic Parameter Configuration
*   Create a JSON file for optimization parameters matching the strategy filename.
    *   *Naming:* `strategies/params_<strategy_name>.json` (e.g., `strategies/params_strategy_activation_scores.json`).
    *   *Content:* Define `start`, `stop`, and `step` for numerical ranges, or `values` for specific lists.

### 3. Run
*   Once created, you can use `validate`, `optimize`, and `walk_forward` with your new strategy file immediately.

### 4. Common Pitfalls & Guardrails
*   **Parity Verification:** The most critical step is verifying that the Python output score matches the output of the Pine Script implementation saved to `data/Export-TV.csv` in column labelled `activation_score_poc`, if it does not match then compare each component value and each respective weight to identify the source of the discrepancy. Run `validate_strategy.py --show-trades` and compare the trade list line-by-line with TradingView trading results here in `results/2025.10.25_ActivationScores_COINBASE_BTCUSD_2026-03-09.xlsx - List of trades.csv` . 
*   **Handling `NaN` and History:** Pine Script is forgiving with `NaN` values and out-of-bounds indexing (returning `NaN`). Python/Numpy will throw errors or return garbage. Explicitly handle `np.nan` and array bounds (e.g., `if i < length: continue`).
*   **State Persistence:** Pine Script's `var` variables persist values across bars. In Python, you can just read the value from the exported trading view data found in 'TV_Export.csv'.

## Data Format
Input CSVs should contain standard OHLCV data with columns: `time`, `open`, `high`, `low`, `close`, `volume`.