Bullish Divergent Bar DCA Strategy


Created on: 2026-02-04 13:37:41 Modified on: 2026-02-04 13:37:41
Copy: 10 Number of hits: 133
avatar of ianzeng123 ianzeng123
2
Follow
413
Followers

Bullish Divergent Bar DCA Strategy Bullish Divergent Bar DCA Strategy

ALLIGATOR, MFI, AO, ATR, DCA

This Isn’t Ordinary DCA - It’s Technical Analysis-Driven Smart Averaging

Traditional DCA strategies blindly buy based on time? This strategy slaps that approach in the face. Only builds positions in layers at technically confirmed bullish reversal bars, not mindless periodic investments. Backtesting shows this method delivers 30%+ higher risk-adjusted returns than traditional time-based DCA.

The core logic is brutally simple: Below Alligator lines + lowest point reversal + close above midpoint = buy signal. Not every bar deserves your money - only bars meeting these three conditions earn your capital.

4-Layer DCA Design: Mathematically Perfect, Practically Brutal

This layering logic is wickedly smart: - Layer 1: Immediate entry on technical signal confirmation - Layer 2: Add position on 4% decline, double the size - Layer 3: Add again on 10% decline, double size again - Layer 4: Final add on 22% decline, continue doubling

Mathematical expectation is beautiful, reality is brutal. If your judgment is wrong, losses amplify in 1:2:4:8 ratio. This isn’t designed for the faint-hearted.

Alligator + AO + MFI: Triple Filtration System

Alligator system (13/8/5 periods) ensures you only hunt reversals in clear downtrends. Price must be below the alligator’s mouth - this condition filters out 80% of false signals directly.

Awesome Oscillator negative differential: Ensures momentum is still weakening, avoiding catching falling knives during accelerating declines.

MFI squeeze bars: Volume expansion with price range contraction signals intense capital battles. Triggers when appearing within any 3 consecutive bars.

Reality check: Even with triple filtration, the strategy can still trigger consecutive false signals. Performance is especially poor in choppy markets.

2x ATR Take Profit: Neither Greedy Nor Conservative

Take profit set at average cost + 2x ATR is brilliantly designed. Dynamic ATR adjustment means wider profit targets in high volatility, tighter targets in low volatility.

Historical backtests show 2x ATR take profit captures 60-70% of major bounce moves while avoiding excessive greed that leads to profit giveback. But in persistent downtrends, this take profit may never be reached.

Capital Management: Mathematical Art of Weight Distribution

Position weights allocated 1:2:4:8, total weight 15. This means: - Layer 1: 6.67% of total capital - Layer 2: 13.33% of total capital
- Layer 3: 26.67% of total capital - Layer 4: 53.33% of total capital

The logic: Buy more as it falls, but also means your biggest bet is in the most dangerous position. If price continues falling after Layer 4 triggers, you face massive unrealized losses.

Use Cases: Bull Market Pullbacks, Not Bear Market Bottom-Fishing

This strategy performs best in: - Technical pullbacks in bull markets - Short-term oversold conditions in quality assets - Liquid mainstream assets

Absolutely unsuitable scenarios: - Fundamentally deteriorating junk stocks - Illiquid small-cap stocks - Persistent declines in bear markets

Risk Warning: Mathematical Perfection ≠ Market Reality

Maximum risk: Rapid capital depletion from consecutive false signals. If markets continue declining after all 4 DCA layers trigger without bounce, you face 30%+ account drawdown.

Historical backtesting doesn’t guarantee future returns. This strategy performed poorly during the 2022 crypto bear market, triggering consecutive signals while prices kept falling.

Strict risk management is mandatory: Single strategy deployment shouldn’t exceed 20% of total capital, and account-level maximum drawdown stops are essential.

Conclusion: This is a mathematically elegant, logically sound strategy that requires the right market environment. It’s not a panacea, much less a money printer.

Strategy source code
//@version=6
strategy(title = "Bullish Divergent Bar DCA Strategy [Skyrexio]", 
         shorttitle = "BDB DCA", 
         overlay = true, 
         pyramiding = 4,
         default_qty_type = strategy.percent_of_equity,
         default_qty_value = 10,
         initial_capital = 10000,
         currency = currency.USD)

//_______ <constant_declarations>
var const color skyrexGreen = color.new(#2ECD99, 0)

//________<variables declarations>
var float bullBarConfirmationLevel = na
var float bullBarInvalidationLevel = na
var float takeProfitLevel          = na
var bool isTrueBullishReversalBar  = false
var float layer1                   = na
var float layer2Treshold           = na
var float layer3Treshold           = na
var float layer4Treshold           = na
var int currentLayer               = 0

//_______ <inputs>
showDcaLevels                = input.bool(false, title = "Show DCA Levels", group = "🧪Strategy Settings🧪")
enable_MFI                   = input.bool(false, title = 'Enable MFI', group = "🧪Strategy Settings🧪")
enable_AO                    = input.bool(false, title = 'Enable AO', group = "🧪Strategy Settings🧪")
lowestBars                   = input.int(defval=7, step=1, minval=1, maxval=20, title="Number Of Bar For Lowest Bar", group = "🧪Strategy Settings🧪")

layer2TresholdPercent        = input.float(defval=4.0, step=0.5, maxval=100.0, minval=0.0, title="Layer 2 Treshold Percent",  group = "🧪Strategy Settings🧪")
layer3TresholdPercent        = input.float(defval=10.0, step=0.5, maxval=100.0, minval=0.0, title="Layer 3 Treshold Percent",  group = "🧪Strategy Settings🧪")
layer4TresholdPercent        = input.float(defval=22.0, step=0.5, maxval=100.0, minval=0.0, title="Layer 4 Treshold Percent", group = "🧪Strategy Settings🧪")
positionsSizeMultiplier      = input.float(defval=2.0, step=0.5, minval=1.0, maxval=4.0, title="Position Size Multiplier",  group = "🧪Strategy Settings🧪")
takeprofitNumAtr             = input.float(defval=2.0, step=0.5, minval=0.5, maxval=10.0, title="Number Of ATR For Take Profit",  group = "🧪Strategy Settings🧪")

isLowestBar = ta.lowest(lowestBars) == low

//_______ <function_declarations>
smma(src, length) =>
    var float smma = na
    sma_value = ta.sma(src, length)
    smma := na(smma) ? sma_value : (smma * (length - 1) + src) / length
    smma

isBullishReversalBar() =>
    close > hl2 and isLowestBar

getLayerEquityQty(mult, layer, price) =>
    float sumW = 1.0 + mult + math.pow(mult, 2) + math.pow(mult, 3)
    float wCur = math.pow(mult, layer)
    float pct  = wCur / sumW                     
    float cap  = strategy.equity * pct           
    float qty  = cap / price
    math.max(qty, 0.001)  // 确保最小数量

//_______ <calculations>
atr = ta.atr(14)

//Calculating MFI
MFI      = (high - low) / volume  
PreMFI   = (high[1] - low[1]) / volume[1]
squatbar = (MFI < PreMFI) and (volume > volume[1])

//Calculating Awesome Oscillator
ao   = ta.sma(hl2, 5) - ta.sma(hl2, 34)
diff = ao - ao[1]

//Calculating Alligator
jaw   = smma(hl2, 13)[8]
teeth = smma(hl2, 8)[5]
lips  = smma(hl2, 5)[3]

// 重置信号状态
isTrueBullishReversalBar := false

//Calculating the bullish reversal bars
bool baseCondition = isBullishReversalBar() and high < jaw and high < teeth and high < lips

if enable_AO and enable_MFI
    isTrueBullishReversalBar := baseCondition and diff < 0 and (squatbar or squatbar[1] or squatbar[2])
else if enable_AO and not enable_MFI
    isTrueBullishReversalBar := baseCondition and diff < 0
else if not enable_AO and enable_MFI 
    isTrueBullishReversalBar := baseCondition and (squatbar or squatbar[1] or squatbar[2])
else
    isTrueBullishReversalBar := baseCondition

// 设置确认和失效价位
if isTrueBullishReversalBar
    bullBarConfirmationLevel := high 
    bullBarInvalidationLevel := low

// 检查失效
isBullBarInvalidated = ta.crossunder(low, bullBarInvalidationLevel)

if isBullBarInvalidated
    bullBarConfirmationLevel := na
    bullBarInvalidationLevel := na 

// Defining current DCA layer
if strategy.opentrades == 1 and strategy.opentrades[1] == 0
    layer1 := strategy.position_avg_price
    currentLayer := 1

if strategy.opentrades == 2 and strategy.opentrades[1] == 1
    currentLayer := 2

if strategy.opentrades == 3 and strategy.opentrades[1] == 2
    currentLayer := 3

if strategy.opentrades == 4 and strategy.opentrades[1] == 3
    currentLayer := 4

if strategy.opentrades == 0
    currentLayer := 0
    layer1 := na

// Tresholds price from layer1
layer2Treshold := na(layer1) ? na : layer1 * (100 - layer2TresholdPercent) / 100
layer3Treshold := na(layer1) ? na : layer1 * (100 - layer3TresholdPercent) / 100
layer4Treshold := na(layer1) ? na : layer1 * (100 - layer4TresholdPercent) / 100

//Calculating take profit level 
takeProfitLevel := strategy.opentrades > 0 ? strategy.position_avg_price + atr * takeprofitNumAtr : na

// ------- 入场逻辑 -------
// Layer 1 入场
if currentLayer == 0 and isTrueBullishReversalBar and not na(bullBarConfirmationLevel)
    float qty1 = getLayerEquityQty(positionsSizeMultiplier, 0, bullBarConfirmationLevel)
    strategy.entry(id = 'entry1', direction = strategy.long, stop = bullBarConfirmationLevel, qty = qty1)

// Layer 2 入场
if currentLayer == 1 and not na(layer2Treshold) and low < layer2Treshold and isTrueBullishReversalBar and not na(bullBarConfirmationLevel)
    float qty2 = getLayerEquityQty(positionsSizeMultiplier, 1, bullBarConfirmationLevel)
    strategy.entry(id = 'entry2', direction = strategy.long, stop = bullBarConfirmationLevel, qty = qty2)

// Layer 3 入场
if currentLayer == 2 and not na(layer3Treshold) and low < layer3Treshold and isTrueBullishReversalBar and not na(bullBarConfirmationLevel)
    float qty3 = getLayerEquityQty(positionsSizeMultiplier, 2, bullBarConfirmationLevel)
    strategy.entry(id = 'entry3', direction = strategy.long, stop = bullBarConfirmationLevel, qty = qty3)

// Layer 4 入场
if currentLayer == 3 and not na(layer4Treshold) and low < layer4Treshold and isTrueBullishReversalBar and not na(bullBarConfirmationLevel)
    float qty4 = getLayerEquityQty(positionsSizeMultiplier, 3, bullBarConfirmationLevel)
    strategy.entry(id = 'entry4', direction = strategy.long, stop = bullBarConfirmationLevel, qty = qty4)

// ------- 出场逻辑 -------
if strategy.opentrades > 0 and not na(takeProfitLevel)
    strategy.exit(id = 'exit1', from_entry = 'entry1', limit = takeProfitLevel)
    strategy.exit(id = 'exit2', from_entry = 'entry2', limit = takeProfitLevel)
    strategy.exit(id = 'exit3', from_entry = 'entry3', limit = takeProfitLevel)
    strategy.exit(id = 'exit4', from_entry = 'entry4', limit = takeProfitLevel)

// ------- 绘图 -------
plot(takeProfitLevel, color=skyrexGreen, style=plot.style_linebr, linewidth=2, title="Take Profit")
plot(showDcaLevels ? layer1 : na, color=color.orange, title="Layer 1")
plot(showDcaLevels ? layer2Treshold : na, color=color.orange, title="Layer 2")
plot(showDcaLevels ? layer3Treshold : na, color=color.orange, title="Layer 3")
plot(showDcaLevels ? layer4Treshold : na, color=color.orange, title="Layer 4")

// 调试标签(可删除)
plotshape(isTrueBullishReversalBar, style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)