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 a practical research workflow for testing hundreds of trading systems across crypto, stocks, ETFs, and other markets, the package gives you strategy code, batch runners, metrics, charts, and publishable reports in one place.
Volume Spread Analysis is built around a simple idea: price movement is more meaningful when it is read together with volume and bar structure. A wide range candle on heavy volume does not say the same thing as a narrow range candle on light volume. A close near the high of the bar does not say the same thing as a close near the low.
This article walks through VSAStrategy, one of the
strategies included in the Mega Backtrader Strategy Pack. The strategy
was tested on ETH-USD daily candles from July 23, 2025 to July
23, 2026.
The result:
| Result | Value |
|---|---|
| Strategy return | 43.25% |
| ETH buy-and-hold return | -48.06% |
| Excess return | 91.31% |
| Sharpe ratio | 1.39 |
| Max drawdown | 11.98% |
| Closed trades | 12 |
| Open trades | 0 |
| Win rate | 66.67% |
This is a clean case study: the strategy made 12 closed trades, had no open trade left at the end of the run, and beat ETH buy-and-hold by 91.31 percentage points over the same period.
VSAStrategy trades Volume Spread Analysis patterns.
The strategy looks at four pieces of information on each bar:
high - low, compared with recent
average spread.From those inputs, the strategy classifies market behavior into VSA-style patterns such as stopping volume, strength, weakness, climax, tests of support, and tests of resistance.
The goal is not to buy every uptick or sell every downtick. The goal is to find bars where volume, range, close location, and trend context agree strongly enough to justify a trade.
The strategy exposes its behavior through Backtrader params:
params = (
('volume_period', 7),
('volume_threshold', 1.2),
('spread_period', 7),
('spread_threshold', 1.2),
('trend_period', 30),
('climax_volume_mult', 2.0),
('test_volume_mult', 0.5),
('trail_stop_pct', 0.05),
)These settings define:
The strategy starts by storing OHLCV data and calculating the core VSA components:
self.high = self.data.high
self.low = self.data.low
self.close = self.data.close
self.open = self.data.open
self.volume = self.data.volume
self.spread = self.high - self.low
self.close_position = (
self.close - self.low
) / (self.high - self.low)It then builds moving averages for volume, spread, and trend:
self.volume_ma = bt.indicators.SMA(
self.volume,
period=self.params.volume_period,
)
self.spread_ma = bt.indicators.SMA(
self.spread,
period=self.params.spread_period,
)
self.trend_ma = bt.indicators.SMA(
self.close,
period=self.params.trend_period,
)Volume is classified as climactic, high, low, or normal:
volume_ratio = self.volume[0] / self.volume_ma[0]
if volume_ratio >= self.params.climax_volume_mult:
return 'climax'
elif volume_ratio >= self.params.volume_threshold:
return 'high'
elif volume_ratio <= self.params.test_volume_mult:
return 'low'
else:
return 'normal'The candle range is classified separately:
spread_ratio = self.spread[0] / self.spread_ma[0]
if spread_ratio >= self.params.spread_threshold:
return 'wide'
elif spread_ratio <= (2 - self.params.spread_threshold):
return 'narrow'
else:
return 'normal'The strategy also checks where the candle closes inside the bar:
close_pos = self.close_position[0]
if close_pos >= 0.7:
return 'high'
elif close_pos <= 0.3:
return 'low'
else:
return 'middle'The trend filter is simple and direct:
if self.close[0] > self.trend_ma[0]:
return 'up'
elif self.close[0] < self.trend_ma[0]:
return 'down'
else:
return 'sideways'These classifications feed the pattern engine. For example, a stopping-volume pattern is detected when volume is climactic after a decline and the candle does not close weakly:
if (
volume_class == 'climax' and
trend == 'down' and
is_down_bar and
close_class in ['middle', 'high']
):
return 'stopping_volume', 4A bearish climax pattern is detected when climactic volume appears on a wide up bar during an uptrend:
if (
volume_class == 'climax' and
spread_class == 'wide' and
close_class == 'high' and
is_up_bar and
trend == 'up'
):
return 'climax', 4The strategy also uses recent bars as background context:
context_score = 0
for i in range(1, 4):
if len(self.data) <= i:
continue
prev_volume = self.volume[-i]
if prev_volume > self.volume_ma[-i]:
context_score += 1The pattern strength and background context are combined before a trade is allowed:
pattern, strength = self.detect_vsa_patterns()
if pattern is None or strength < 2:
return
context = self.check_background_context()
total_strength = strength + context
if total_strength < 3:
returnBullish patterns can open long positions or close short positions:
if pattern in [
'no_demand',
'no_supply',
'stopping_volume',
'strength',
'test_support',
'effort_down',
]:
if self.position.size < 0:
self.order = self.close()
elif not self.position:
if total_strength >= 4 or pattern in [
'stopping_volume',
'no_supply',
]:
self.order = self.buy()Bearish patterns can open short positions or close long positions:
elif pattern in [
'climax',
'weakness',
'test_resistance',
'effort_up',
]:
if self.position.size > 0:
self.order = self.close()
elif not self.position:
if total_strength >= 4 or pattern in [
'climax',
'weakness',
]:
self.order = self.sell()Risk is managed with a trailing stop after entry:
if order.isbuy() and self.position.size > 0:
self.entry_price = order.executed.price
self.trail_stop_price = (
order.executed.price *
(1 - self.params.trail_stop_pct)
)
self.stop_order = self.sell(
exectype=bt.Order.Stop,
price=self.trail_stop_price,
)That gives the strategy a complete trading loop: classify the bar, detect the VSA pattern, score the context, enter only when strength is high enough, and manage the trade with a stop.
The article result was generated with:
python run_backtest.py --fast --fast-plots --fast-equity \
--workers 1 \
--symbol ETH-USD \
--period 1y \
--interval 1d \
--benchmark ETH-USD \
--stake-percent 99 \
--strategies strategies \
--out results \
--strategy-filter VSAStrategyBacktest setup:
| Setting | Value |
|---|---|
| Asset | ETH-USD |
| Benchmark | ETH-USD buy-and-hold |
| Period | 1y |
| Data window | July 23, 2025 to July 23, 2026 |
| Interval | 1d |
| Starting cash | $10,000 |
| Final value | $14,324.86 |
| Strategy file | strategies/VSAStrategy.py |
| Metric | Value |
|---|---|
| Strategy return | 43.25% |
| ETH buy-and-hold return | -48.06% |
| Excess return vs benchmark | 91.31% |
| Sharpe ratio | 1.39 |
| Max drawdown | 11.98% |
| Total trades | 12 |
| Closed trades | 12 |
| Open trades | 0 |
| Winning trades | 8 |
| Losing trades | 4 |
| Win rate | 66.67% |
| Runtime | 2.26 seconds |
The strategy did not rely on one open position to create the result. It finished with 12 closed trades, no open trades, and a two-thirds win rate.
The equity curve shows the strategy growing from $10,000 to $14,324.86 while ETH buy-and-hold declined sharply over the same period.
The drawdown chart shows the strategy's largest pullback at 11.98%, with the strategy avoiding the full downside profile of buy-and-hold.
The rolling return chart shows how the strategy's edge developed across the test window.
The daily return distribution summarizes how the strategy's day-to-day returns were distributed during the run.
This VSA example is useful because it is not a simple moving-average crossover. It combines volume expansion, spread behavior, close location, trend context, pattern labels, signal strength, background context, and trailing stops.
That is exactly where a large strategy library becomes valuable. You can move beyond one generic template and test many different market ideas:
For this ETH-USD run, the VSA approach worked because it treated volume and bar structure as trade context instead of relying only on price direction.
VSAStrategy 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, compare, document, and publish Backtrader strategies faster, this package gives you the full 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.