Dynamic Buying Selling Volume Breakout Strategy
This strategy determines long and short through customized timeframe buying and selling volume, combined with weekly VWAP and Bollinger Bands for filtering, to realize high probability trend tracking. It also…

Overview
This strategy determines long and short through customized timeframe buying and selling volume, combined with weekly VWAP and Bollinger Bands for filtering, to realize high probability trend tracking. It also introduces dynamic take profit and stop loss mechanism to effectively control one-sided risk.
Strategy Principle
- Calculate buying and selling volume indicators within customized timeframe
- BV: Buying volume, caused by buying at low point
- SV: Selling volume, caused by selling at high point
- Process buying and selling volume
- Smooth by 20-period EMA
- Separate processed buying and selling volume into positive and negative
- Judge indicator direction
- Greater than 0 is bullish, less than 0 is bearish
- Determine divergence combined with weekly VWAP and Bollinger Bands
- Price above VWAP and indicator bullish is long signal
- Price below VWAP and indicator bearish is short signal
- Dynamic take profit and stop loss
- Set percentage of take profit and stop loss based on daily ATR
Advantages
- Buying and selling volume reflects real market momentum, captures potential energy of trends
- Weekly VWAP judges longer timeframe trend direction, Bollinger Bands determine breakout signals
- Dynamic ATR sets take profit and stop loss, maximizes profit locking and avoids overtuning
Risks
- Buying and selling volume data has certain errors, may cause misjudgement
- Single indicator combined judgement tends to generate false signals
- Improper Bollinger Bands parameter settings narrow down valid breakouts
Optimization Directions
- Optimize with multiple timeframe buying and selling volume indicators
- Add trading volume and other auxiliary indicators for filtering
- Dynamically adjust Bollinger Bands parameters to improve breakout efficiency
Conclusion
This strategy makes full use of the predictability of buying and selling volume, generating high probability signals supplemented by VWAP and Bollinger Bands, while effectively controlling risk through dynamic take profit and stop loss. As parameters and rules continue to be optimized, performance is expected to become more significant.
Parameters
| Name | Default | What it controls |
|---|---|---|
| v_input_timeframe_1 | 60 | (?Entry Settings)customTimeframe |
| v_input_bool_1 | true | allow_long |
| v_input_bool_2 | false | allow_short |
| v_input_int_1 | 20 | (?Volatility Settings)length |
| v_input_float_1 | 2 | StdDev |
| v_input_float_2 | 100 | (?Dynamic Risk Management)TP Multiplier for Long entries |
| v_input_float_3 | true | SL Multiplier for Long entries |
| v_input_float_4 | 100 | TP Multiplier for Short entries |
| v_input_float_5 | 5 | SL Multiplier for Short entries |
Source Pine Script
/*backtest
start: 2022-12-19 00:00:00
end: 2023-12-25 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © original author ceyhun
//@ exlux99 update
//@version=5
strategy('Buying Selling Volume Strategy', format=format.volume, precision=0, overlay=false)
weekly_vwap = request.security(syminfo.tickerid, "W", ta.vwap(hlc3))
vi = false
customTimeframe = input.timeframe("60", group="Entry Settings")
allow_long = input.bool(true, group="Entry Settings")
allow_short = input.bool(false, group="Entry Settings")
xVolume = request.security(syminfo.tickerid, customTimeframe, volume)
xHigh = request.security(syminfo.tickerid, customTimeframe, high)
xLow = request.security(syminfo.tickerid, customTimeframe, low)
xClose = request.security(syminfo.tickerid, customTimeframe, close)
BV = xHigh == xLow ? 0 : xVolume * (xClose - xLow) / (xHigh - xLow)
SV = xHigh == xLow ? 0 : xVolume * (xHigh - xClose) / (xHigh - xLow)
vol = xVolume > 0 ? xVolume : 1
TP = BV + SV
BPV = BV / TP * vol
SPV = SV / TP * vol
TPV = BPV + SPV
tavol20 = request.security(syminfo.tickerid, customTimeframe, ta.ema(vol, 20))
tabv20= request.security(syminfo.tickerid, customTimeframe, ta.ema(BV, 20))
tasv20= request.security(syminfo.tickerid, customTimeframe, ta.ema(SV, 20))
VN = vol / tavol20
BPN = BV / tabv20 * VN * 100
SPN = SV / tasv20 * VN * 100
TPN = BPN + SPN
xbvp = request.security(syminfo.tickerid, customTimeframe,-math.abs(BPV))
xbpn = request.security(syminfo.tickerid, customTimeframe,-math.abs(BPN))
xspv = request.security(syminfo.tickerid, customTimeframe,-math.abs(SPV))
xspn = request.security(syminfo.tickerid, customTimeframe,-math.abs(SPN))
BPc1 = BPV > SPV ? BPV : xbvp
BPc2 = BPN > SPN ? BPN : xbpn
SPc1 = SPV > BPV ? SPV : xspv
SPc2 = SPN > BPN ? SPN : xspn
BPcon = vi ? BPc2 : BPc1
SPcon = vi ? SPc2 : SPc1
minus = BPcon + SPcon
plot(minus, color = BPcon > SPcon ? color.green : color.red , style=plot.style_columns)
length = input.int(20, minval=1, group="Volatility Settings")
src = minus//input(close, title="Source")
mult = input.float(2.0, minval=0.001, maxval=50, title="StdDev", group="Volatility Settings")
xtasma = request.security(syminfo.tickerid, customTimeframe, ta.sma(src, length))
xstdev = request.security(syminfo.tickerid, customTimeframe, ta.stdev(src, length))
basis = xtasma
dev = mult * xstdev
upper = basis + dev
lower = basis - dev
plot(basis, "Basis", color=#FF6D00, offset = 0)
p1 = plot(upper, "Upper", color=#2962FF, offset = 0)
p2 = plot(lower, "Lower", color=#2962FF, offset = 0)
fill(p1, p2, title = "Background", color=color.rgb(33, 150, 243, 95))
// Original a
longOriginal = minus > upper and BPcon > SPcon and close > weekly_vwap
shortOriginal = minus > upper and BPcon < SPcon and close< weekly_vwap
high_daily = request.security(syminfo.tickerid, "D", high)
low_daily = request.security(syminfo.tickerid, "D", low)
close_daily = request.security(syminfo.tickerid, "D", close)
true_range = math.max(high_daily - low_daily, math.abs(high_daily - close_daily[1]), math.abs(low_daily - close_daily[1]))
atr_range = ta.sma(true_range*100/request.security(syminfo.tickerid, "D", close), 14)
ProfitTarget_Percent_long = input.float(100.0, title='TP Multiplier for Long entries ', step=0.5, step=0.5, group='Dynamic Risk Management')
Profit_Ticks_long = close + (close * (atr_range * ProfitTarget_Percent_long))/100
LossTarget_Percent_long = input.float(1.0, title='SL Multiplier for Long entries', step=0.5, group='Dynamic Risk Management')
Loss_Ticks_long = close - (close * (atr_range * LossTarget_Percent_long ))/100
ProfitTarget_Percent_short = input.float(100.0, title='TP Multiplier for Short entries ', step=0.5, step=0.5, group='Dynamic Risk Management')
Profit_Ticks_short = close - (close * (atr_range*ProfitTarget_Percent_short))/100
LossTarget_Percent_short = input.float(5.0, title='SL Multiplier for Short entries', step=0.5, group='Dynamic Risk Management')
Loss_Ticks_short = close + (close * (atr_range*LossTarget_Percent_short))/100
var longOpened_original = false
var int timeOfBuyLong = na
var float tpLong_long_original = na
var float slLong_long_original = na
long_entryx = longOriginal
longEntry_original = long_entryx and not longOpened_original
if longEntry_original
longOpened_original := true
tpLong_long_original := Profit_Ticks_long
slLong_long_original := Loss_Ticks_long
timeOfBuyLong := time
//lowest_low_var_sl := lowest_low
tpLong_trigger = longOpened_original[1] and ((close > tpLong_long_original) or (high > tpLong_long_original)) //or high > lowest_low_var_tp
slLong_Trigger = longOpened_original[1] and ((close < slLong_long_original) or (low < slLong_long_original)) //or low < lowest_low_var_sl
longExitSignal_original = shortOriginal or tpLong_trigger or slLong_Trigger
if(longExitSignal_original)
longOpened_original := false
tpLong_long_original := na
slLong_long_original := na
if(allow_long)
strategy.entry("long", strategy.long, when=longOriginal)
strategy.close("long", when= longExitSignal_original) //or shortNew
if(allow_short)
strategy.entry("short", strategy.short, when=shortOriginal )
strategy.close("short", when= longOriginal) //or shortNew
Published by ChaoZhang on the FMZ strategy square · last modified 2023-12-26. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.
Build this with AgenKit
A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Dynamic-Buying-Selling-Volume-Breakout-Strategy.md- npx agenkit install engineering-kit in your project
- Paste the command into your agent and approve each phase
- Get tests, backtest, risk controls and a paper-trading switch
Understand it first
Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.
Related specs
- Cross Timeframe SuperTrend Breakout StrategyPine Script · Breakout · 1h
- BB Breakout StrategyPine Script · Breakout · 1d
- EMA and Bollinger Bands Breakout StrategyPine Script · Breakout · 1h
- Momentum Breakout Moving Average StrategyPine Script · Breakout · 1d
- Momentum Breakout Trading Strategy 440964Pine Script · Breakout · 5m
- Moving Average Crossover and Upper Rail Breakthrough Impulse StrategyPine Script · Breakout · 1m