Get the full strategy library: This article uses one strategy from the Mega Backtrader Strategy Pack, a package of 500+ Backtrader-ready Python trading strategies with batch backtesting, dashboards, metrics, charts, and documentation.
Download the package here: Mega Backtrader Strategy Pack
If you want to move from one-off trading ideas to a repeatable strategy research workflow, the package gives you strategy code, batch runners, metrics, charts, and publishable reports in one place.
Markets do not behave the same way all the time. Some periods reward trend following. Other periods punish breakouts and reward mean reversion. That is the idea behind a dual-regime strategy: detect the current market condition first, then choose the trading logic that fits that condition.
This article walks through DualRegimeWeeklyStrategy, one
of the strategies included in the Mega Backtrader Strategy Pack. The
strategy was tested on UNH daily candles over a 1-year
period, with SPY used as the benchmark.
The result:
| Result | Value |
|---|---|
| Strategy return | 40.81% |
| UNH buy-and-hold return | 32.76% |
| SPY benchmark return | 25.65% |
| Excess return vs SPY | 15.15% |
| Sharpe ratio | 2.50 |
| Max drawdown | 4.15% |
| Closed trades | 13 |
| Open trades | 1 |
| Win rate | 76.92% |
This is a strong example because the strategy beat both the asset buy-and-hold return and the SPY benchmark while keeping maximum drawdown low. The run ended with one open position, so the final equity includes the marked value of that open trade. The win rate is based on the 13 closed trades.
DualRegimeWeeklyStrategy uses a weekly decision
schedule. It does not react to every daily candle. Instead, it checks
conditions once per week, closes the previous position, determines the
current market regime, and then decides whether to enter a new
trade.
The strategy uses two different playbooks:
That structure makes the strategy easy to understand. It first asks whether the market is trending or ranging. Only after that does it choose which signal type matters.
The strategy exposes its behavior through Backtrader params:
params = (
('adx_period', 14),
('adx_threshold', 25),
('rebal_day', 0),
('ema_period', 50),
('bb_period', 20),
('bb_devfactor', 2.0),
('rsi_period', 14),
('rsi_oversold', 30),
('rsi_overbought', 70),
('atr_period', 14),
('atr_mult', 3.0),
)These settings control:
The strategy starts by creating the indicators it needs for both regimes:
self.adx = bt.indicators.ADX(self.data, period=self.p.adx_period)
self.ema = bt.indicators.ExponentialMovingAverage(
self.data.close,
period=self.p.ema_period,
)
self.bb = bt.indicators.BollingerBands(
self.data.close,
period=self.p.bb_period,
devfactor=self.p.bb_devfactor,
)
self.rsi = bt.indicators.RSI(self.data.close, period=self.p.rsi_period)
self.atr = bt.indicators.ATR(self.data, period=self.p.atr_period)ADX is the regime filter. EMA is used when the market is trending. Bollinger Bands and RSI are used when the market is ranging.
The strategy then limits decision-making to one chosen weekday:
dt = self.data.datetime.date(0)
current_week = dt.isocalendar()[1]
if dt.weekday() != self.p.rebal_day:
return
if self.last_week == current_week:
return
self.last_week = current_weekWith rebal_day set to 0, the strategy
evaluates on Monday. This avoids constant churn from daily signal noise
and gives the system a cleaner weekly rhythm.
Before opening a new trade, the strategy closes any existing position:
if self.position:
self.close()That makes each weekly decision explicit. The strategy does not keep stacking unrelated entries. It exits the old position first, then evaluates the new setup.
The regime switch is controlled by ADX:
regime = 'trending' if self.adx[0] > self.p.adx_threshold else 'ranging'When the market is trending, the strategy uses the EMA as the directional filter:
if regime == 'trending':
if self.data.close[0] > self.ema[0]:
self.order = self.buy()
else:
self.order = self.sell()In the original strategy code, that bearish branch can issue a sell order. In the package batch run used for this article, the runner was in its default long-only mode, so sell orders are treated as exits rather than new short entries. That means the reported result is a long-only interpretation of the strategy logic.
When the market is ranging, the strategy waits for oversold or overbought extremes:
else:
if self.data.close[0] <= self.bb.bot[0] and self.rsi[0] < self.p.rsi_oversold:
self.order = self.buy()
elif self.data.close[0] >= self.bb.top[0] and self.rsi[0] > self.p.rsi_overbought:
self.order = self.sell()The long entry needs price near the lower Bollinger Band and RSI below the oversold threshold. The sell branch captures the opposite condition, and in the long-only batch run it functions as an exit signal rather than a fresh short.
Many simple strategies use only one market assumption. A moving-average strategy assumes trend continuation. A Bollinger Band reversion strategy assumes mean reversion. Both ideas can work, but neither describes every market.
DualRegimeWeeklyStrategy is useful because it combines
both ideas without making the code hard to follow:
That weekly schedule is important. It reduces overtrading and makes the strategy easier to inspect in the results dashboard.
The run used the package batch backtester with these settings:
| Setting | Value |
|---|---|
| Asset | UNH |
| Benchmark | SPY |
| Period | 1y |
| Interval | 1d |
| Starting cash | $10,000 |
| Strategy file | DualRegimeWeeklyStrategy.py |
| Strategy class | DualRegimeWeeklyStrategy |
| Execution mode | Long-only batch run |
The package generated the metrics table, equity curve, benchmark comparison, drawdown chart, rolling return chart, and daily return distribution automatically.
| Metric | Value |
|---|---|
| Starting portfolio value | $10,000.00 |
| Final portfolio value | $14,080.92 |
| Strategy return | 40.81% |
| UNH buy-and-hold return | 32.76% |
| SPY benchmark return | 25.65% |
| Excess return vs SPY | 15.15% |
| Excess return vs UNH buy-hold | 8.05% |
| Sharpe ratio | 2.50 |
| Max drawdown | 4.15% |
| Total trades | 14 |
| Closed trades | 13 |
| Open trades | 1 |
| Winning closed trades | 10 |
| Losing closed trades | 3 |
| Win rate | 76.92% |
| Runtime | 3.36 seconds |
The key number is not only the 40.81% return. The drawdown stayed at 4.15%, which is low for a strategy that outperformed both UNH buy-and-hold and SPY over the test window.
The single open trade at the end matters. Closed-trade statistics describe the 13 completed trades, while the final portfolio value includes the open position's mark-to-market value at the final bar.
The equity curve shows the strategy growing from $10,000 to $14,080.92. UNH buy-and-hold also performed well, but the strategy finished higher with a smoother path.
The drawdown chart is the strongest part of this case study. The strategy's maximum drawdown was only 4.15%, while both the asset and benchmark had deeper pullbacks during the same period.
The rolling return chart shows how performance developed through the test window. The strategy did not rely on a single lucky spike. It built the final result across multiple weekly decisions.
The daily return histogram gives a compact view of day-to-day movement in the strategy equity curve. It is useful for quickly checking whether the result came from frequent smaller moves or a handful of extreme days.
This backtest is a good example of why a large strategy library is useful. The idea is not only to find one strategy and stop. The value is in being able to test many different structures quickly:
DualRegimeWeeklyStrategy shows how a compact Backtrader
class can combine multiple market assumptions in one readable strategy.
It is still simple enough to modify, but it already has enough structure
to behave differently across market regimes.
DualRegimeWeeklyStrategy is one of 500+
Backtrader-ready strategies included in the Mega
Backtrader Strategy Pack.
Get the full package here: Mega Backtrader Strategy Pack
The package includes:
strategies/
package.If you want to test more strategy ideas faster, this package gives you the code and the research workflow.
Get the Mega Backtrader Strategy Pack
This article is for research and educational use only. Backtest results are not financial advice, investment advice, or a guarantee of future performance. Always validate strategy logic, data quality, execution assumptions, costs, slippage, and risk before using any trading system.