Skip to content

Instantly share code, notes, and snippets.

@marsmensch
Last active October 1, 2025 16:24
Show Gist options
  • Select an option

  • Save marsmensch/b984c0aace8928736b7a5974f2f2f4d4 to your computer and use it in GitHub Desktop.

Select an option

Save marsmensch/b984c0aace8928736b7a5974f2f2f4d4 to your computer and use it in GitHub Desktop.
tradingview (pinescript v6) development prompt

SFP Detector — Low-TF, Pivot-Confirmed (v1.7)

A non-repainting Swing Failure Pattern (SFP) indicator for TradingView (Pine Script v6).
Signals are confirmed at bar close using pivot-based logic with optional ATR, session, and HTF bias filters.
Includes alerts with fixed messages and optional side labels for clear chart annotation.

SFP Indicator


What it detects

  • Bearish SFP
    Price sweeps the latest confirmed pivot high by at least penetration% and closes back below by at least re-entry%.
    Requires sufficient top wick fraction.

  • Bullish SFP
    Symmetric logic at pivot lows with bottom wick fraction.

Signals appear only after pivot confirmation (rightBars > 0) and will not repaint once printed.


Key Features

  • No repaint after bar confirmation
  • ⚙️ Fine-tuning with tooltips
    • Pivot geometry (leftBars, rightBars, maxAge)
    • Sweep penetration %, re-entry %, wick fraction
    • Optional filters: ATR, Session, HTF bias
    • Minimum bars between signals (throttle)
  • 📈 Visualization options
    • Clean triangle markers
    • Optional side labels with colored background
    • Pivot swing level lines
  • 🔔 Alerts for bullish and bearish SFP entries (const messages for stability)

How to Use

  1. TradingView → Pine Editor → paste SFP Detector v1.7SaveAdd to chart.
  2. Start on 1m–15m:
    • Pivot L/R = 3
    • Penetration = 0.20%
    • Re-entry = 0.00–0.10%
    • Min wick = 0.25
  3. Optional filters:
    • ATR filter: Use ATR = ON, Min Range = 0.8–1.2
    • Session: 0900-1700 or your local hours
    • HTF bias: TF = 60, MA len = 50
  4. Visualization:
    • Signal Label Mode = None → clean markers only
    • Signal Label Mode = Side label → text boxes (“SFP Buy/Sell”) with background
  5. Alerts:
    • Add alert → Condition = indicator → Bullish SFP or Bearish SFP
    • Use Once per bar close

Inputs (Cheat-Sheet)

Core — Pivot Geometry

  • Pivot Left / Right → Swing strength vs delay
  • Max Bars Since Pivot → Ignore old pivots

Sweep & Re-entry Filters

  • Min Sweep Penetration (%) → Depth of liquidity grab
  • Min Re-entry Distance (%) → How far close returns inside
  • Min Wick Fraction (0–1) → Wickiness requirement
  • Min Bars Between Signals → Avoid clustered prints

Optional — Volatility

  • ATR filter, ATR length, Min Range multiple

Optional — Session

  • Restrict signals to specific hours

Optional — HTF Bias

  • Use HTF bias filter (close vs HTF MA)

Visualization & Alerts

  • Show swing levels
  • Marker size
  • Label mode (None / Side label)
  • Enable alerts

Repainting, Assumptions, Limitations

  • No repaint after confirmation (bar close + rightBars > 0)
  • ⏱️ Larger rightBars = cleaner signals but more delay
  • 🕒 HTF bias uses lookahead_off → values finalize at HTF bar close
  • 🔄 In chop: increase penetration%, re-entry%, wick fraction, or enable filters

Customization Tips

  • Faster but noisier → rightBars = 1–2
  • Stricter SFP → penetration = 0.30–0.50%, re-entry = 0.10–0.25%
  • Trend alignment → enable HTF bias with 60/50

Alerts Note

  • Messages are fixed:
    • "Bullish SFP on {{ticker}} {{interval}} close {{close}}"
    • "Bearish SFP on {{ticker}} {{interval}} close {{close}}"
  • Customize routing/prefix in TradingView’s alert UI.

License

Private use allowed. Credit appreciated if you publish variants.

Professional Pine Script v6 Brief (Indicator or Strategy)

Role

  • You are a senior Pine Script v6 developer delivering a production-grade TradingView tool.

Objectives

  • Write efficient, readable Pine v6 with a modular layout.
  • Avoid repainting. If any risk remains, document exactly where and why.
  • Provide inputs with sensible defaults and tooltips.
  • Include alertcondition() for actionable events using CONST strings only.
  • If a strategy: include SL/TP/trailing and position sizing.
  • Support MTF safely with request.security(..., lookahead_off). Document timing caveats.
  • Provide a short technical note (logic, assumptions, repaint, limitations).

Formatting rules (must follow)

  • ASCII characters only.
  • Use ONLY line comments that start with "// " on their own line.
  • Do NOT use inline end-of-line comments.
  • Do NOT use block comments (/* */).
  • Put each function call on a single line. Avoid line continuations.
  • Do NOT pass dynamic strings to plotshape(text=) or alertcondition(message=). Use CONST literals only.
  • If text needs to be toggled, gate visibility with booleans and separate calls or labels.
  • For plotshape(size=...), pass CONST enums (size.small, etc.). If the size is user-selected, emit multiple plotshape calls gated by the chosen size string.
  • Keep alertcondition() at global scope.
  • Precompute any ta.barssince() values in variables on every bar, then reference those variables in conditions.

Quick questions (answer before coding)

  1. Tool type: Indicator or Strategy?
  2. Signal logic: Which concepts (SFPs, MA cross, RSI divergences, order blocks, liquidity sweeps, custom)?
  3. Alerts: Which conditions should trigger alerts (entry, exit, filter hits, risk events)?
  4. Risk (if strategy): SL/TP/trailing? Position sizing rules?
  5. Markets and TFs: Primary instruments/timeframes (crypto LTF, FX intraday, stocks daily, etc.)?
  6. Optional filters: ATR/volatility, session windows, HTF bias, trend filters?
  7. Scope: One-off vs extendable module?

Technical requirements

  • pinescript @version=6
  • Prevent repaint: confirmed-bar logic; if using pivots, require rightBars > 0; MTF with lookahead_off.
  • Organize sections: Inputs -> Precompute/HTF -> Core Logic -> Filters -> Signals -> Plots -> Alerts -> Notes.
  • Comment tunables. Document lookbacks, warmup, and MTF timing.

Deliverables

  1. Single Pine v6 file that compiles without errors.
  2. How-to: Add to chart, configure inputs, set alerts (or backtest settings for strategies).
  3. Tech Notes: Logic summary, assumptions, repaint discussion, limitations, customization tips.

Acceptance criteria

  • No compile errors. Signals and alerts fire on bar close.
  • Inputs have clear names, tooltips, and sane defaults.
  • MTF use documented. No lookahead.
  • Code is consistent and readable. Comments follow the formatting rules above.
//@version=6
indicator("SFP Detector - LTF Pivot Confirmed (v1.7)", overlay=true)
// Core - Pivot Geometry
grpCore = "Core - Pivot Geometry"
leftBars = input.int(3, "Pivot Left", minval=1, group=grpCore, tooltip="Bars to the LEFT of the pivot high or low. Higher means stronger swing but slower confirmation.")
rightBars = input.int(3, "Pivot Right", minval=1, group=grpCore, tooltip="Bars to the RIGHT of the pivot. Controls confirmation delay. Use >0 to avoid repaint after print.")
maxAge = input.int(200, "Max Bars Since Pivot", minval=1, group=grpCore, tooltip="Ignore pivots older than this many bars. Keeps signals near recent structure.")
// Filters - Sweep and Re-entry
grpSweep = "Filters - Sweep and Re-entry"
penetrationPct = input.float(0.20, "Min Sweep Penetration (%)", minval=0.0, step=0.05, group=grpSweep, tooltip="Price must TAKE the pivot by at least this percent to count as a sweep.")
reentryPct = input.float(0.00, "Min Re-entry Distance (%)", minval=0.0, step=0.05, group=grpSweep, tooltip="After the sweep, CLOSE must return inside by at least this percent beyond the pivot level.")
minWickFrac = input.float(0.25, "Min Wick Fraction (0-1)", minval=0.0, maxval=1.0, step=0.05, group=grpSweep, tooltip="Require at least this fraction of the bar to be wick in the sweep direction.")
minSepBars = input.int(0, "Min Bars Between Signals", minval=0, group=grpSweep, tooltip="Optional throttle. Require this many bars between same type signals.")
// Optional - Volatility Filter
grpVol = "Optional - Volatility Filter"
useATR = input.bool(false, "Use ATR Filter", group=grpVol, tooltip="If enabled, require current bar range to be at least X times ATR.")
atrLen = input.int(14, "ATR Length", minval=1, group=grpVol, tooltip="ATR lookback length.")
minAtrMult = input.float(0.80, "Min Range as ATR multiple", minval=0.0, step=0.05, group=grpVol, tooltip="Require (high - low) >= this multiple of ATR. Set 0 to disable effect.")
// Optional - Session Filter
grpSess = "Optional - Session Filter"
useSession = input.bool(false, "Filter by Session", group=grpSess, tooltip="If enabled, signals only during the specified session window.")
sessionStr = input.session("0900-2200", "Session (exchange time)", group=grpSess, tooltip="Format HHMM-HHMM. Example 0900-1700. Uses exchange time.")
// Optional - HTF Bias Filter
grpHTF = "Optional - HTF Bias Filter"
useHTF = input.bool(false, "Use HTF Bias", group=grpHTF, tooltip="If enabled, confirm signals with a higher timeframe bias (close vs HTF MA).")
htfTF = input.timeframe("60", "HTF Timeframe", group=grpHTF, tooltip="Higher timeframe used for bias sampling. Example 60 for 1h.")
htfMaLen= input.int(50, "HTF MA Length", minval=1, group=grpHTF, tooltip="Moving average length used to define HTF bias.")
// Visualization and Alerts
grpVis = "Visualization and Alerts"
showSwingLines = input.bool(true, "Show Last Swing Levels", group=grpVis, tooltip="Plot the most recent confirmed pivot high and low as level lines.")
shapeSizeStr = input.string("small", "Signal Marker Size", options=["tiny","small","normal","large"], group=grpVis, tooltip="Marker size for SFP triangles. Pine needs const sizes, so we gate by this string.")
labelMode = input.string("None", "Signal Label Mode", options=["None","Side label"], group=grpVis, tooltip="Choose None for clean markers or Side label for a readable text box with background.")
enableAlerts = input.bool(true, "Enable Alerts", group=grpVis, tooltip="Create alert conditions for bullish and bearish SFP confirmations.")
// Pre-computations
rng = math.max(1e-10, high - low)
wickTop = high - math.max(open, close)
wickBottom = math.min(open, close) - low
atr = ta.atr(atrLen)
// Pivots - confirmed, non-repainting (print after rightBars)
ph = ta.pivothigh(high, leftBars, rightBars)
pl = ta.pivotlow(low, leftBars, rightBars)
lastPH = ta.valuewhen(not na(ph), ph, 0)
lastPL = ta.valuewhen(not na(pl), pl, 0)
barsSincePH = ta.barssince(not na(ph))
barsSincePL = ta.barssince(not na(pl))
phValid = not na(lastPH) and barsSincePH <= maxAge
plValid = not na(lastPL) and barsSincePL <= maxAge
// HTF bias - lookahead off
htfClose = useHTF ? request.security(syminfo.tickerid, htfTF, close, barmerge.gaps_off, barmerge.lookahead_off) : na
htfMA = useHTF ? ta.sma(htfClose, htfMaLen) : na
bullBias = useHTF ? (htfClose > htfMA) : true
bearBias = useHTF ? (htfClose < htfMA) : true
// Session and ATR filters
inSess = useSession ? not na(time(timeframe.period, sessionStr)) : true
rangeOK = useATR ? (rng >= (minAtrMult * atr)) : true
// SFP Logic - bar close confirmed
bearishSweep = phValid and (high > lastPH * (1.0 + penetrationPct / 100.0))
bearishRein = phValid and (close < lastPH * (1.0 - reentryPct / 100.0))
bearishWickOK = (wickTop / rng) >= minWickFrac
bullishSweep = plValid and (low < lastPL * (1.0 - penetrationPct / 100.0))
bullishRein = plValid and (close > lastPL * (1.0 + reentryPct / 100.0))
bullishWickOK = (wickBottom / rng) >= minWickFrac
rawBearSFP = barstate.isconfirmed and bearishSweep and bearishRein and bearishWickOK
rawBullSFP = barstate.isconfirmed and bullishSweep and bullishRein and bullishWickOK
// Optional filters
bearSFP = rawBearSFP and bearBias and inSess and rangeOK
bullSFP = rawBullSFP and bullBias and inSess and rangeOK
// Separation logic - compute on every bar for consistency
barsSinceBullPrev = ta.barssince(bullSFP[1])
barsSinceBearPrev = ta.barssince(bearSFP[1])
bullGapOK = minSepBars <= 0 or (na(barsSinceBullPrev) ? true : barsSinceBullPrev >= minSepBars)
bearGapOK = minSepBars <= 0 or (na(barsSinceBearPrev) ? true : barsSinceBearPrev >= minSepBars)
bullSig = bullSFP and bullGapOK
bearSig = bearSFP and bearGapOK
// Plotting - colors
colUp = color.new(color.teal, 0)
colDown = color.new(color.red, 0)
// Swing levels
plot(showSwingLines and plValid ? lastPL : na, title="Last Pivot Low", color=color.new(color.teal, 70), linewidth=2, style=plot.style_linebr)
plot(showSwingLines and phValid ? lastPH : na, title="Last Pivot High", color=color.new(color.red, 70), linewidth=2, style=plot.style_linebr)
// Marker size gating - Pine requires const sizes
bullTiny = bullSig and shapeSizeStr == "tiny"
bullSmall = bullSig and shapeSizeStr == "small"
bullNormal = bullSig and shapeSizeStr == "normal"
bullLarge = bullSig and shapeSizeStr == "large"
bearTiny = bearSig and shapeSizeStr == "tiny"
bearSmall = bearSig and shapeSizeStr == "small"
bearNormal = bearSig and shapeSizeStr == "normal"
bearLarge = bearSig and shapeSizeStr == "large"
// Plot markers - no text on markers to avoid const string issues and halos
plotshape(bullTiny, title="Bullish SFP tiny", style=shape.triangleup, location=location.belowbar, color=colUp, size=size.tiny, text="")
plotshape(bullSmall, title="Bullish SFP small", style=shape.triangleup, location=location.belowbar, color=colUp, size=size.small, text="")
plotshape(bullNormal, title="Bullish SFP normal", style=shape.triangleup, location=location.belowbar, color=colUp, size=size.normal, text="")
plotshape(bullLarge, title="Bullish SFP large", style=shape.triangleup, location=location.belowbar, color=colUp, size=size.large, text="")
plotshape(bearTiny, title="Bearish SFP tiny", style=shape.triangledown, location=location.abovebar, color=colDown, size=size.tiny, text="")
plotshape(bearSmall, title="Bearish SFP small", style=shape.triangledown, location=location.abovebar, color=colDown, size=size.small, text="")
plotshape(bearNormal, title="Bearish SFP normal", style=shape.triangledown, location=location.abovebar, color=colDown, size=size.normal, text="")
plotshape(bearLarge, title="Bearish SFP large", style=shape.triangledown, location=location.abovebar, color=colDown, size=size.large, text="")
// Side labels with background for readability
if labelMode == "Side label" and bullSig
label.new(bar_index, low, "SFP Buy", style=label.style_label_up, textcolor=color.white, color=color.new(colUp, 0), yloc=yloc.belowbar)
if labelMode == "Side label" and bearSig
label.new(bar_index, high, "SFP Sell", style=label.style_label_down, textcolor=color.white, color=color.new(colDown, 0), yloc=yloc.abovebar)
// Alerts - const messages and global scope
alertcondition(enableAlerts and bullSig, title="Bullish SFP", message="Bullish SFP on {{ticker}} {{interval}} close {{close}}")
alertcondition(enableAlerts and bearSig, title="Bearish SFP", message="Bearish SFP on {{ticker}} {{interval}} close {{close}}")
// Notes
// Signals are generated on confirmed bars only. Pivot logic with rightBars > 0 avoids repaint after print.
// HTF filter uses lookahead off to avoid future leaks. HTF values finalize on HTF bar close.
// For earlier but noisier signals, lower rightBars and increase penetration thresholds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment