Optimization of trading strategy hyperparameters with combinatorial cross validation and stress tesing
To get a local copy up and running, follow these simple steps:
Ensure you have the following software installed on your system:
- Python: You can download it from python.org.
- Git: You can download it from git-scm.com.
pip install git+https://github.com/alex33d/backtest_optimizer.git
To start using the Optimizer, you need to import the ParameterOptimizer
class from backtest_optimizer/main.py
. The main functions are:
-
Initialize the Optimizer:
from backtest_optimizer.main import ParameterOptimizer optimizer = ParameterOptimizer(calc_pl)
calc_pl
: A function for calculating strategy profit and loss. It must accept a dictionary with data in the form{ticker: DataFrame}
, and returns pandas Series with returns for each period.
-
Train/Test Split:
optimizer.split_data(data_dict, train_end)
data_dict
: Dictionary containing data in the form{ticker: DataFrame}
.train_end
: The train end date in the form of a pandas DateTime.
-
Create Combinatorial Cross Validation Groups:
optimizer.create_combcv_dict(n_splits, n_test_splits)
n_splits
: Total number of groups.n_test_splits
: Number of test groups.
-
Run the Optimization Algorithm:
optimizer.optimize(params=params_dict, n_jobs=3, n_runs=10, best_trials_pct=0.25)
params
: The parameter dictionary with hyperparameter space for Optuna optimization.n_jobs
: Number of parallel workers.n_runs
: Number of Optuna trials.best_trials_pct
: Percentage of trials that go to the validation set.
-
Reconstruct Equity Curves:
optimizer.reconstruct_equity_curves()
- Reconstructs the equity curves based on validation sets.
-
Run Stress Tests:
optimizer.run_stress_tests()
- Runs backtest stress tests.
-
Select Best Parameters:
best_params = optimizer.cluster_and_aggregate()
- Selects the best parameters via clustering.
-
Calculate Out-of-Sample Sharpe Ratio:
optimizer.calc_oos_sharpe(best_params)
- Tests the best parameters on the test set.
Here’s a complete example of how you might use the Optimizer class:
from backtest_optimizer.main import ParameterOptimizer
# Define your profit and loss calculation function
def calc_pl(data):
# Calculate P&L logic here
pass
# Initialize the optimizer
optimizer = ParameterOptimizer(calc_pl)
# Split data into train and test sets
data_dict = {'AAPL': data_frame_aapl, 'GOOG': data_frame_goog}
train_end = pd.to_datetime('2023-01-01')
optimizer.split_data(data_dict, train_end)
# Create combinatorial cross-validation groups
optimizer.create_combcv_dict(n_splits=5, n_test_splits=1)
# Define parameter dictionary for optimization
params_dict = {
'param1': [0, 1, 2],
'param2': [0, 10, 20]
}
# Run optimization
optimizer.optimize(params=params_dict, n_jobs=3, n_runs=10, best_trials_pct=0.25)
# Reconstruct equity curves
optimizer.reconstruct_equity_curves()
# Run stress tests
optimizer.run_stress_tests()
# Select best parameters
best_params = optimizer.cluster_and_aggregate()
# Calculate out-of-sample Sharpe ratio
oos_sharpe = optimizer.calc_oos_sharpe(best_params)
I welcome contributions to the project! Here’s how you can help:
If you find a bug or have a feature request, please create an issue on GitHub.
- Go to the Issues page.
- Click on the "New issue" button.
- Provide a clear and descriptive title.
- Describe the issue or feature request in detail, including steps to reproduce the issue if applicable.
If you want to contribute code, follow these steps to submit a pull request:
-
Fork the Repository
Click the "Fork" button at the top right of the repository page to create a copy of the repository on your GitHub account.
-
Clone Your Fork
Clone your forked repository to your local machine:
git clone https://github.com/alex33d/backtest_optimizer.git cd backtest_optimizer
-
Create a Branch
Create a new branch for your feature or bug fix:
git checkout -b my-feature-branch
-
Make Your Changes
Make your changes to the codebase. Ensure your code follows the project's coding standards.
-
Commit Your Changes
Commit your changes with a descriptive commit message:
git add . git commit -m "Description of your changes"
-
Push to Your Fork
Push your changes to your forked repository:
git push origin my-feature-branch
-
Create a Pull Request
Go to the original repository on GitHub and click the "New pull request" button.
- Select your branch from the "compare" dropdown.
- Provide a clear and descriptive title for your pull request.
- Describe your changes in detail in the description field.
- Submit the pull request.
To maintain consistency in the codebase, please adhere to the following guidelines:
- Follow the PEP 8 style guide for Python code.
- Write descriptive commit messages.
- Include docstrings for all functions and classes.
- Write unit tests for new features and bug fixes.
This project is licensed under the MIT License - see the LICENSE file for details.
For any questions, suggestions, or feedback, feel free to contact me: