Active Optimization ExampleΒΆ

set the example MACD strategy to periodically run a parameter scan on the most recent data, and update the parameters acccordingly.

Python source code: ../../examples/active_optimization.py

from boatwright.Data import CSVdatabase
from boatwright import Backtest
from boatwright.Brokers import BacktestBroker
from boatwright.Visualization import plot_backtest
from boatwright.Optimizations.ParameterScan import ParameterScan
from boatwright.Optimizations.Optimization import generate_parameter_combinations
from boatwright import ActiveOptimization
from boatwright.BacktestExecutors import ParallelExecutor
from boatwright.PerformanceMetrics import PercentProfit
from MACD import MACD
from datetime import datetime
import matplotlib.pyplot as plt

# 1. set the boker model
br = BacktestBroker(taker_fee=0, maker_fee=0, slippage=0.1, quote_symbol="USD")

# 2. set the strategy, and optimization (in this example a parameter scan)
macd = MACD(symbol="BTC", fast_period=1, slow_period=2)

scan = {
    "fast_period": [10,20,30,40,50],
    "slow_period": [25,50,75,100,125]
}
parameters_sets = generate_parameter_combinations(scan)
parameters_sets = [p for p in parameters_sets if (p["fast_period"] < p["slow_period"])]

loss_function = lambda b: -PercentProfit().calculate(b) # by minimizing 'negative' percent profit, profit is maximized
executor = ParallelExecutor(n_procs=3) # for faster optimization, run backtests in parallel across multiple processes (defaults to 1 process, i.e. no parallelization)
ps = ParameterScan(strategy_class=MACD, symbol="BTC", broker=br, loss_function=loss_function, scan=parameters_sets, data=None, executor=executor)
ps.make_backtests()

# 3. declare the ActiveOptimzation
# In this example: optimize every week, using the most recent 7 days of data
strategy = ActiveOptimization(strategy=macd, optimization=ps, opt_period=7*24, opt_length=7*24, debug=False, verbose=True)

# 4. load data for the backtest 
DB = CSVdatabase(source="ALPACA", dir="quickstart_data/")
start = datetime(year=2025, month=2, day=1, hour=1, minute=0)
end = datetime(year=2025, month=5, day=1, hour=0, minute=0)
data = DB.load(symbol=strategy.symbol, start=start, end=end, prerequisite_data_length=ps.calc_prerequisite_data_length(), granularity=1, granularity_unit="HOUR")

# 5. run the backtest
backtest = Backtest(strategy=strategy, data=data, broker=br, debug=False)
backtest.run(verbose=True)

# analyze results
figs, axs = plot_backtest(backtest)

# saving figures for documentation
figs["aum"].savefig("../docs/examples/images/active_optimization/aum.png")
figs["assets"].savefig("../docs/examples/images/active_optimization/assets.png")
figs["price"].savefig("../docs/examples/images/active_optimization/price.png")
figs["fast_period"].savefig("../docs/examples/images/active_optimization/fast_period.png")
figs["slow_period"].savefig("../docs/examples/images/active_optimization/slow_period.png")
figs["reoptimize"].savefig("../docs/examples/images/active_optimization/reoptimize.png")

plt.show()

../_images/price.png ../_images/reoptimize.png ../_images/fast_period.png ../_images/slow_period.png ../_images/aum.png