//@version=5
// =====================================================================================
//  Origin Explains Charts — DriftPullback VWAP
//  "Pass A Funded Account With VWAP On TradingView"
//
//  A port of ea/checks/strategy.mjs, the same file the MT5 robot in this zip is a port
//  of and the same file that drew the video's chart. One algorithm, three ports, no
//  second copy of the rules anywhere.
//
//  WHAT IT DRAWS
//    · the session VWAP — the same line TradingView's own VWAP button gives you
//    · a dot under a bar when all three LONG conditions are true, over it for SHORT
//    · a triangle on the TRIGGER bar: the first candle back towards the line
//    · the stop and the target for the most recent trigger, as levels
//
//  THE RULES, from the source's own on-chart text
//    LONG   price above the VWAP
//           VWAP rising over the past 15 minutes
//           price up at least 0.1% over the past 1 hour
//    SHORT  all three flipped
//    TRIGGER  longs: the first RED candle back towards the VWAP
//             shorts: the first GREEN candle back towards it
//    ENTRY  the OPEN of the bar AFTER the trigger closes
//    STOP   80 points  ·  TARGET 40 long / 50 short
//
//  The target is SMALLER than the stop on purpose — the small target buys a high hit
//  rate, and a smooth account line is what a funded account's drawdown rule rewards.
//  Built to pass an evaluation, not to grow your own capital. No performance figure is
//  claimed anywhere.
//
//  The guardrails the robot enforces (one position, max 4 trades and 2 losses a day, no
//  new trade after 15:30 New York, flat at 15:55) are ACCOUNT rules, not chart rules, so
//  this indicator does not draw them. They matter just as much — see the README.
// =====================================================================================
indicator("Origin DriftPullback VWAP", shorttitle = "DriftPB VWAP", overlay = true)

// ---- inputs -------------------------------------------------------------------------
driftPct = input.float(0.1, "Drift over the lookback hour (%)", minval = 0.0, step = 0.05)
driftMin = input.int(60, "Drift lookback (minutes)", minval = 5)
slopeMin = input.int(15, "VWAP slope lookback (minutes)", minval = 5)
stopPts = input.float(80, "Stop (points)", minval = 1)
tgtLong = input.float(40, "Target, longs (points)", minval = 1)
tgtShort = input.float(50, "Target, shorts (points)", minval = 1)
showLevels = input.bool(true, "Draw the stop and target of the last trigger")

// ---- the lookbacks, in BARS of whatever chart this is on ----------------------------
// timeframe.in_seconds() is a simple int, so these stay simple ints and can be used as
// history-reference offsets without Pine complaining about a series length.
barMin = math.max(1, timeframe.in_seconds() / 60)
driftBars = math.max(1, math.round(driftMin / barMin))
slopeBars = math.max(1, math.round(slopeMin / barMin))

// ---- the line -----------------------------------------------------------------------
// ta.vwap is the session-anchored VWAP: it resets when the session does, which is the
// line the video tells the viewer to add.
vw = ta.vwap

// ---- the three conditions -----------------------------------------------------------
slope = vw - vw[slopeBars]
base = close[driftBars]
change = base > 0 ? (close - base) / base * 100.0 : 0.0

aboveLine = close > vw
belowLine = close < vw
risingVwap = slope > 0
fallingVwap = slope < 0
driftUp = change >= driftPct
driftDown = change <= -driftPct

longReady = aboveLine and risingVwap and driftUp
shortReady = belowLine and fallingVwap and driftDown

// ---- the trigger --------------------------------------------------------------------
// "the first RED candle towards the VWAP" for longs, green for shorts — and it has to
// genuinely close nearer the line than it opened, or it is not a pullback towards it.
isRed = close < open
isGreen = close > open
nearer = math.abs(close - vw) < math.abs(open - vw)

longTrigger = longReady and isRed and nearer
shortTrigger = shortReady and isGreen and nearer

// ---- the plan, measured from the NEXT bar's open ------------------------------------
// The fill is the next open, which does not exist while this bar is forming, so the
// levels are drawn from the trigger bar's close — the same price the robot fills at on
// continuous data — and they are a PLAN, never a result.
var float lastEntry = na
var float lastStop = na
var float lastTarget = na
var int lastDir = 0

if longTrigger
    lastEntry := close
    lastStop := close - stopPts
    lastTarget := close + tgtLong
    lastDir := 1

if shortTrigger
    lastEntry := close
    lastStop := close + stopPts
    lastTarget := close - tgtShort
    lastDir := -1

// ---- drawing ------------------------------------------------------------------------
plot(vw, "VWAP", color = color.new(#2962FF, 0), linewidth = 2)

plotshape(longReady and not longTrigger, "Long conditions met", shape.circle, location.belowbar, color.new(#089981, 35), size = size.tiny)
plotshape(shortReady and not shortTrigger, "Short conditions met", shape.circle, location.abovebar, color.new(#F23645, 35), size = size.tiny)
plotshape(longTrigger, "LONG trigger", shape.triangleup, location.belowbar, color.new(#089981, 0), size = size.small)
plotshape(shortTrigger, "SHORT trigger", shape.triangledown, location.abovebar, color.new(#F23645, 0), size = size.small)

plot(showLevels and lastDir != 0 ? lastStop : na, "Stop", color = color.new(#F23645, 0), style = plot.style_linebr, linewidth = 1)
plot(showLevels and lastDir != 0 ? lastTarget : na, "Target", color = color.new(#089981, 0), style = plot.style_linebr, linewidth = 1)

alertcondition(longTrigger, "DriftPullback LONG", "DriftPullback: long trigger — buy the next open, stop 80, target 40")
alertcondition(shortTrigger, "DriftPullback SHORT", "DriftPullback: short trigger — sell the next open, stop 80, target 50")
