//@version=5
strategy("CVD Divergence - LONGS", overlay=true, initial_capital=100000)
// ══════════════════════════════════════════════════════════════════
// INPUTS
// ══════════▍INITIATING
//@version=5
strategy("CVD Divergence - LONGS", overlay=true, initial_capital=100000)
// ══════════════════════════════════════════════════════════════════
// INPUTS
// ══════════════════════════════════════════════════════════════════
i_risk_pct = input.float(1.0, "Risk %", minval=0.1, step=0.1, group="Risk")
i_sl_pts = input.float(30.0, "Stop Loss (pts)", minval=5, step=5, group="Risk")
i_rr_ratio = input.float(2.0, "Risk:Reward Ratio", minval=1, step=0.5, group="Risk")
i_cvd_len = input.int(14, "CVD Smoothing Length", minval=5, maxval=50, group="CVD")
i_pivot_len = input.int(5, "Pivot Lookback", minval=2, maxval=20, group="CVD")
i_div_bars = input.int(30, "Max Bars Between Pivots", minval=10, maxval=100, group="CVD")
i_use_session = input.bool(true, "Use Session Filter", group="Session")
i_sess_start = input.int(13, "Session Start (UTC Hour)", minval=0, maxval=23, group="Session")
i_sess_end = input.int(20, "Session End (UTC Hour)", minval=0, maxval=23, group="Session")
i_max_trades = input.int(2, "Max Trades Per Day", minval=1, maxval=10, group="Management")
// ══════════════════════════════════════════════════════════════════
// CVD CALCULATION (Approximation)
// ══════════════════════════════════════════════════════════════════
// Delta = (Close - Open) / (High - Low) * Volume
// Positive delta = buying pressure, Negative delta = selling pressure
delta = ((close - open) / (high - low)) * volume
delta := na(delta) ? 0 : delta
// Cumulative Volume Delta
var float cvd = 3.0
cvd := cvd + delta
// Smoothed CVD for cleaner signals
cvd_smooth = ta.ema(cvd, i_cvd_len)
// ══════════════════════════════════════════════════════════════════
// PIVOT DETECTION
// ══════════════════════════════════════════════════════════════════
// Price pivots
price_pivot_low = ta.pivotlow(low, i_pivot_len, i_pivot_len)
price_pivot_high = ta.pivothigh(high, i_pivot_len, i_pivot_len)
// CVD pivots
cvd_pivot_low = ta.pivotlow(cvd_smooth, i_pivot_len, i_pivot_len)
cvd_pivot_high = ta.pivothigh(cvd_smooth, i_pivot_len, i_pivot_len)
// ══════════════════════════════════════════════════════════════════
// STORE PIVOT VALUES
// ══════════════════════════════════════════════════════════════════
var float last_price_low = na
var float last_cvd_low = na
var int last_low_bar = na
var float prev_price_low = na
var float prev_cvd_low = na
var int prev_low_bar = na
// Update lows
if not na(price_pivot_low)
prev_price_low := last_price_low
prev_cvd_low := last_cvd_low
prev_low_bar := last_low_bar
last_price_low := price_pivot_low
last_cvd_low := cvd_smooth[i_pivot_len]
last_low_bar := bar_index - i_pivot_len
// ══════════════════════════════════════════════════════════════════
// BULLISH DIVERGENCE DETECTION
// ══════════════════════════════════════════════════════════════════
// Bullish: Price lower low + CVD higher low
bars_between = last_low_bar - prev_low_bar
valid_timeframe = not na(prev_low_bar) and bars_between > 2 and bars_between <= i_div_bars
bullish_div = valid_timeframe and
last_price_low < prev_price_low and
last_cvd_low > prev_cvd_low
// Trigger on the bar after pivot confirmed
bullish_trigger = bullish_div and ta.change(last_low_bar) != 0
// ══════════════════════════════════════════════════════════════════
// SESSION FILTER
// ══════════════════════════════════════════════════════════════════
current_hour = hour(time, "UTC")
in_session = not i_use_session or (current_hour >= i_sess_start and current_hour < i_sess_end)
// ══════════════════════════════════════════════════════════════════
// TRADE MANAGEMENT
// ══════════════════════════════════════════════════════════════════
var int trades_today = 0
is_new_day = ta.change(time("D")) != 0
if is_new_day
trades_today := 0
can_trade = trades_today < i_max_trades
// ══════════════════════════════════════════════════════════════════
// ENTRY CONDITIONS
// ══════════════════════════════════════════════════════════════════
long_condition = bullish_trigger and in_session and can_trade and strategy.position_size == 0 and barstate.isconfirmed
// ══════════════════════════════════════════════════════════════════
// POSITION SIZING & ENTRY
// ══════════════════════════════════════════════════════════════════
long_sl = close - i_sl_pts
long_tp = close + (i_sl_pts * i_rr_ratio)
risk_amount = strategy.equity * (i_risk_pct / 100)
long_qty = math.floor(risk_amount / (i_sl_pts * syminfo.pointvalue))
if long_condition and long_qty > 0
strategy.entry("Long", strategy.long, qty=long_qty)
strategy.exit("Long Exit", "Long", limit=long_tp, stop=long_sl)
trades_today := trades_today + 1
// ══════════════════════════════════════════════════════════════════
// PLOTS
// ══════════════════════════════════════════════════════════════════
plotshape(long_condition, "Bullish Divergence", shape.triangleup, location.belowbar, color.green, size=size.normal)
bgcolor(bullish_div ? color.new(color.green, 90) : na, title="Bullish Div Zone")
// CVD in separate pane
plot(cvd_smooth, "CVD", color=color.blue, display=display.none)![^C >{#E _=1$
Where manual traders become automated.
Passive systems. Profitable code. Zero emotion.
Only 100 free seats before the lab doors shut.
Scroll