WalkForwardGridOptimizer#
-
class sigtech.framework.analytics.optimization.walk_forward_optimizer.WalkForwardGridOptimizer
Helper class enabling the repeated grid optimisation of a strategy and subsequent use of the optimised parameters until the next optimisation. Walk-forward optimisation can help to reduce overfitting since each optimisation uses the same lookback. Additionally, the method avoids in-sample fitting since each optimisation at time \(t\) only uses data available up to \(t\).
Parameters:
strategy_generator
: Method called to return the strategy. Must return aStrategy
object. Must take at least as many arguments as is contained inparameter_space
.parameter_space
: Dictionary keyed by parameter names (must match argument names instrategy_generator
method) containing lists of possible values that will be iterated over at each optimisation step, e.g.:'trend_lookback': [20, 60, 120]
.fitting_metric
: Metric method (chosen from methods inmetrics
or designed with an identical signature) used to evaluate each parameter combination.fitting_lookback
: Lookback of ‘training’ data used at each optimisation step. Can be expressed as either a tenor string ('1M'
,'2W-MON'
, etc.; seeSchedulePeriodic
for a complete list of possible inputs), or apd.DateOffset
, e.g.pd.DateOffset(months=3)
.fitting_frequency
: Time elapsed between each optimisation step. Can be expressed as either a tenor string ('1M'
,'2W-MON'
, etc.; seeSchedulePeriodic
for a complete list of possible inputs), or a list of dates (in which case the dates themselves will be used).extra_strategy_kwargs
: Any additional kwargs to pass to the strategy being optimised.
Note
The arguments in
parameter_space
andextra_strategy_kwargs
together must match the arguments of thestrategy_generator
method.Example usage:
import datetime as dtm import pandas as pd import numpy as np import sigtech.framework as sig from sigtech.framework.analytics.performance.metrics import sharpe_ratio from sigtech.framework.analytics.optimization.walk_forward_optimizer import WalkForwardGridOptimizer def generate_trend_strategy( trend_short_lookback, trend_long_lookback, contract_offset, equity_index_code ): asset = sig.RollingFutureStrategy( currency='USD', ticker=f'{trend_short_lookback}-{trend_long_lookback}-{contract_offset}-{equity_index_code} Trend', contract_code=equity_index_code, contract_sector='INDEX', start_date=dtm.date(2020, 9, 1), rolling_rule='front', contract_offset=contract_offset, ) signal = sig.signal_library.technical_indicators.macd( close=asset.history(), short_window=trend_short_lookback, long_window=trend_long_lookback ).dropna() signal = pd.DataFrame(signal['MACD'].apply(np.sign)) signal.columns = [asset.name] return sig.SignalStrategy( currency='USD', start_date=signal.first_valid_index(), signal_name=sig.signal_library.from_ts(signal).name, rebalance_frequency='1W', ) o = WalkForwardGridOptimizer( strategy_generator=generate_trend_strategy, parameter_space={ 'trend_short_lookback': [10, 12, 14, ], 'trend_long_lookback': [24, 26, 30, ], 'contract_offset': [0, 3, ], }, fitting_metric=sharpe_ratio, fitting_lookback=pd.DateOffset(months=12), fitting_frequency='2W', equity_index_code='ES', ) o.optimize(dtm.date(2022, 1, 1)) o.report()
-
generate_strategy_piecewise(ticker: str = 'PIECEWISE', delay: int = 1, **extra_args) PiecewiseStrategy
Take the results from the optimisation and generate a
PiecewiseStrategy
from the best parameters.Note
PiecewiseStrategy
would return incorrect results in the case that the strategies used in the grid optimiser are path-dependent.- Parameters:
ticker – Ticker identifier for the strategy (optional).
delay – Delay applied to the start date of the strategies, in number of days (default is 1).
extra_args – Extra arguments to pass to the
PiecewiseStrategy
being created.
- Returns:
PiecewiseStrategy
strategy.
-
optimize(start: Optional[date] = None, end: Optional[date] = None)
Run the walk-forward optimisation between a given date range.
- Parameters:
start – Date of first optimisation (optional, if not provided will be set as maximum between the strategy start dates).
end – Date of last optimisation (optional).
-
params_from_strategy(strategy_name) tuple
Return the parameters (as tuple) represented by the strategy name.
- Parameters:
strategy_name – Strategy name.
- Returns:
Tuple represented by the strategy name.
-
performance_df(include_strategy_piecewise=True, params_tuple_as_columns=True) DataFrame
Generate a DataFrame containing the performance of the strategy variations.
- Parameters:
include_strategy_piecewise – If True, include the optimal strategy defined by
generate_strategy_piecewise
(default is True).params_tuple_as_columns – If True, use the parameter space (as tuples) as columns instead of the strategy tickers (default is True).
- Returns:
pandas DaraFrame.
-
report() DataFrame
Generate a report of the results in DataFrame format.
-
strategy_piecewise_ts(delay: int = 1) Series
Return a timeseries of the strategies with their start dates used to generate a
PiecewiseStrategy
from the best parameters. Seegenerate_strategy_piecewise()
for details.- Parameters:
delay – Delay applied to the start date of the strategies, in number of days (default is 1).
- Returns:
pandas Series.
-
strategy_variations() dict
Return a dictionary containing the parameter space as keys and the individual strategies as values.