Skip to content

Latest commit

 

History

History
196 lines (134 loc) · 7.05 KB

File metadata and controls

196 lines (134 loc) · 7.05 KB
  1. Installation

Clone the repository and install the required dependencies.

git clone https://github.com/strakehyr/Trading-Strategy-Optimizer.git

pip install -r requirements.txt

System Requirements: Python 3.8+ Operating System: Linux, macOS, or Windows

Dependencies:

pandas
numpy
optuna
plotly
scipy
  1. Data Integration

The framework supports two methods for ingesting market data: a custom API fetcher or local CSV files.

Option A: Custom Data Fetcher (API/Database)

To connect to an external source (Yahoo Finance, Alpaca, Binance, SQL, etc.), you must implement a data_fetcher.py module in the root directory. This acts as the primary interface. Required Interface: The data_fetcher.py file must contain the following function signatures:

import pandas as pd

def get_market_data(symbol: str, timeframe: str, min_data_days: int) -> pd.DataFrame:
    """
    Retrieves historical market data.

    Args:
        symbol (str): Ticker symbol (e.g., "BTCUSD", "AAPL").
        timeframe (str): Resolution (e.g., "1 hour", "1 day").
        min_data_days (int): Minimum required history in days.

    Returns:
        pd.DataFrame: A DataFrame containing OHLCV data.
                      Index must be DatetimeIndex.
                      Columns must include: 'open', 'high', 'low', 'close', 'volume'.
    """
    # Implementation logic here (e.g., read_csv or API call)
    pass

def initialize_data_service():
    """
    Performs any necessary setup (e.g., API authentication).
    Returns True if successful, False otherwise.
    """
    pass

def shutdown_data_service():
    """
    Performs cleanup tasks (e.g., closing connections).
    """
    pass

Option B: Offline Mode (Local CSV)

If initialize_data_service() fails or returns False, the system defaults to Offline Mode. It will look for CSV files in a data/ directory within the project root. File Naming Convention: Files must be named using the format: {SYMBOL}_{TIMEFRAME}.csv. Note that spaces in timeframes should be removed in the filename. Example: QQQ_1hour.csv Example: BTCUSD_1day.csv CSV Format Requirements: The CSV must contain standard OHLCV headers. The date column must be parseable by pandas.

CSV

datetime,open,high,low,close,volume
2020-01-01 09:30:00,100.50,101.20,100.00,100.80,5000
2020-01-01 10:30:00,100.80,102.00,100.50,101.50,6200

Note: Ensure your CSV data covers the requested --days lookback period, otherwise the backtest for that symbol will be skipped.

  1. Adding Entry Strategies

Strategies are defined as standalone Python modules within the strategies/ directory. The framework dynamically loads any .py file found in this folder. Strategy Module Structure: Each strategy file must define: compatible_timeframes: A list of supported timeframes. param_space: A dictionary defining the hyperparameter search space for Optuna. strategy_function: The core logic that accepts a DataFrame and parameters, returning the DataFrame with a position column.

Example:

import pandas as pd
import numpy as np

compatible_timeframes = ['1 hour', '4 hours', '1 day']

param_space = {
    'short_window': {'type': 'int', 'low': 5, 'high': 20},
    'long_window': {'type': 'int', 'low': 21, 'high': 50}
}

def strategy_function(df: pd.DataFrame, short_window: int, long_window: int) -> pd.DataFrame:
    strategy_df = df.copy()
    
    # Calculate indicators
    strategy_df['short_mavg'] = strategy_df['close'].rolling(window=short_window).mean()
    strategy_df['long_mavg'] = strategy_df['close'].rolling(window=long_window).mean()
    
    # Generate signals
    # 1 = Long, -1 = Short, 0 = Neutral/Flat
    condition_long = strategy_df['short_mavg'] > strategy_df['long_mavg']
    condition_short = strategy_df['short_mavg'] < strategy_df['long_mavg']
    
    raw_signal = np.where(condition_long, 1, np.where(condition_short, -1, 0))
    
    # Apply signal to position column
    strategy_df['position'] = raw_signal
    
    return strategy_df
  1. Adding Exit Strategies

Exit logic is handled separately in the exit_strategies/ directory. Exit Module Structure: param_space: Hyperparameters for the exit logic (e.g., TP/SL percentages). uses_native_exit: Boolean flag. True: The backtester relies solely on the entry strategy's position column changes to close trades (e.g., Stop and Reverse). False: The backtester runs exit_logic_function at every step to check for exit conditions. exit_logic_function: Logic to determine if an active trade should be closed. Example: exit_strategies/fixed_tp_sl.py

import pandas as pd

param_space = {
    'tp_pct': {'type': 'float', 'low': 0.01, 'high': 0.05},
    'sl_pct': {'type': 'float', 'low': 0.01, 'high': 0.03}
}

uses_native_exit = False

def exit_logic_function(df: pd.DataFrame, entry_price: float, position_direction: int, params: dict) -> pd.Series:
    tp = params['tp_pct']
    sl = params['sl_pct']
    
    if position_direction == 1:
        # Long Exit: High hits TP or Low hits SL
        tp_price = entry_price * (1 + tp)
        sl_price = entry_price * (1 - sl)
        return (df['high'] >= tp_price) | (df['low'] <= sl_price)
        
    elif position_direction == -1:
        # Short Exit: Low hits TP or High hits SL
        tp_price = entry_price * (1 - tp)
        sl_price = entry_price * (1 + sl)
        return (df['low'] <= tp_price) | (df['high'] >= sl_price)
        
    return pd.Series(False, index=df.index)
  1. Usage

Run the workflow using main.py. The system accepts command-line arguments to control the scope of the backtest. Command Line Arguments:

Argument	Description	Default

--symbols	List of ticker symbols to process.
--strategies	Specific entry strategy files to run (or 'all').
--exit_strategies	Specific exit strategy files to run (or 'all').
--timeframes	Timeframes to test.	1 hour, 4 hours, 1 day
--days	Total lookback period in days (IS + OOS).
--is_years	Number of years allocated to In-Sample training.
--trials	Number of Optuna trials per combination.
--objective	Metric to optimize (Sharpe Ratio, Calmar Ratio, Total Return).

Example Execution:

python main.py --symbols BTCUSD ETHUSD --strategies momentum_dual_consistency --exit_strategies fixed_tp_sl --timeframes "1 hour" "4 hours" --trials 200 --objective "Sharpe Ratio"
  1. Output

Results are saved in the results/run_/ directory. Each symbol-strategy-timeframe combination produces a subdirectory containing: HTML Reports: Visualization of backtests, robustness, and optimization landscapes. CSV Data: Raw data for trials and robustness analysis.

Logs: Execution details and error tracking.