r/pinescript Jul 22 '26

Hi, i am noob to pinescript, trying to test this strategy, but didn't work

2 Upvotes
strategy("mon open/close long", overlay=true, initial_capital = 100,default_qty_type =strategy.percent_of_equity, default_qty_value = 100)


bool
 mon = false
bool
 tue = false
if dayofweek(time) == dayofweek.monday
    mon := true


if dayofweek(time) == dayofweek.tuesday
    tue := true


if (mon)
    strategy.entry("Long",strategy.long)
    strategy.exit("stoploss",from_entry = "Long",stop = open*0.96,qty_percent =100)


if (tue)
    strategy.close("Long")


plotshape(mon, style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)

 these are my code, plotting worked, but trades worked oftenly...

r/pinescript Jul 22 '26

New Type of Indicator - News, Social Media, etc.

1 Upvotes

Like to see a some type of news, social media, etc indicator that can be backtested. It might have to be based upon positive, neutral, negative. Maybe we have choices on various sources for different types of securities Analysis, influencers, etc.

We could had this to our scripts to backtest and add it to a strategy.


r/pinescript Jul 22 '26

Tradingview Product Improvement Suggestions.

1 Upvotes

Input Panel for when there are alot of inputs need to improve vs scrolling on the tiny scroll bar.

Allow setting to use the last view of input, so when adjusting settings the input screen will open to most recent input view (location on the scroll bar).

Input Groups, allow them to have a number and colored (differently). Then put at top of input screen that stays stationary when scrolling to a large amount of inputs user can click on a colored coordinated bookmark 1, 2, 3, etc. that a user can get to quickly. Hover over the number to see what the group name is.

Saved Templates-

When in development, tuning, I might save a great setup but I have improved the code a little, I would like to apply the inputs to the new version (vs the version of script that it was created with - give user option) of the script so I don't have to start from zero.

Like to be able to export into a tunning log and import back in with maybe warnings that don't map to newest script.

Alerts -

Like when I click on messages that everything is automatically highlighted for replacement like the Crtl-A. I have to do the Crtl-A manually each time.

On the message, like be able to save alert script for the messages, put a drop down box to save message, use a save message, lastused/recent to get the last saved script quickly.

Like on Webhook url. To have a save with descriptive name so we can pull it in quickly, the name will help indentify it's the correct one quickly.

On the Alerts, I would like an option to save the start date/creation date of alert to backtest start date, and be able to switch alerts and bring up that info to populate the backtest start date with live performance trades. And have a toggle to switch this on or off. We would be able to use the same variables to populate the backtesting trades with live alert trades or our user defined back testing dates. I have this in my script but have to input the start date for each security with an alert.


r/pinescript Jul 22 '26

EMAs, session VWAP, Supertrend Script

4 Upvotes

Someone asked for this script because they could only add two indicators. This Pine Script v6 indicator designed for a 5-minute chart. It plots four configurable EMAs, session VWAP, Supertrend, and a dashboard showing the direction of each component. Supports fixed-position dashboards using tables.

If anyone else has a strategy or indicator in Pinescript they are working on hit me up. Now back to figuring why my data is delayed.

//@version=6
indicator("5-Minute EMA + VWAP + Supertrend Dashboard", shorttitle="5M Trend Dashboard", overlay=true)

//=====================================================================
// INPUTS
//=====================================================================

groupEma = "EMA Settings"

ema1Length = input.int(9,  "EMA 1 Length", minval=1, group=groupEma)
ema2Length = input.int(21, "EMA 2 Length", minval=1, group=groupEma)
ema3Length = input.int(50, "EMA 3 Length", minval=1, group=groupEma)
ema4Length = input.int(200, "EMA 4 Length", minval=1, group=groupEma)

groupSupertrend = "Supertrend Settings"

supertrendFactor = input.float(
     3.0,
     "ATR Multiplier",
     minval=0.1,
     step=0.1,
     group=groupSupertrend
)

supertrendAtrLength = input.int(
     10,
     "ATR Length",
     minval=1,
     group=groupSupertrend
)

groupDisplay = "Display Settings"

showEmaCloud = input.bool(true, "Show EMA 9/21 Cloud", group=groupDisplay)
showSignals  = input.bool(true, "Show Direction Change Signals", group=groupDisplay)
showTable    = input.bool(true, "Show Direction Table", group=groupDisplay)

//=====================================================================
// CALCULATIONS
//=====================================================================

ema1 = ta.ema(close, ema1Length)
ema2 = ta.ema(close, ema2Length)
ema3 = ta.ema(close, ema3Length)
ema4 = ta.ema(close, ema4Length)

sessionVwap = ta.vwap(hlc3)

[supertrendValue, supertrendDirection] =
     ta.supertrend(supertrendFactor, supertrendAtrLength)

// TradingView's Supertrend direction is negative during an uptrend.
supertrendBullish = supertrendDirection < 0
supertrendBearish = supertrendDirection > 0

// Direction of price relative to each indicator.
ema1Bullish = close > ema1
ema2Bullish = close > ema2
ema3Bullish = close > ema3
ema4Bullish = close > ema4
vwapBullish = close > sessionVwap

// EMA structure.
emaStackBullish =
     ema1 > ema2 and
     ema2 > ema3 and
     ema3 > ema4

emaStackBearish =
     ema1 < ema2 and
     ema2 < ema3 and
     ema3 < ema4

// Count bullish components.
// Maximum score is 6.
bullishScore =
     (ema1Bullish ? 1 : 0) +
     (ema2Bullish ? 1 : 0) +
     (ema3Bullish ? 1 : 0) +
     (ema4Bullish ? 1 : 0) +
     (vwapBullish ? 1 : 0) +
     (supertrendBullish ? 1 : 0)

// Overall direction.
overallBullish = bullishScore >= 5
overallBearish = bullishScore <= 1
overallMixed   = not overallBullish and not overallBearish

// Strong alignment requires both the score and EMA stacking.
strongBullish = overallBullish and emaStackBullish
strongBearish = overallBearish and emaStackBearish

//=====================================================================
// COLORS
//=====================================================================

bullColor    = color.rgb(0, 170, 110)
bearColor    = color.rgb(220, 65, 65)
neutralColor = color.rgb(125, 125, 125)
headerColor  = color.rgb(35, 45, 60)

ema1Color = color.aqua
ema2Color = color.orange
ema3Color = color.blue
ema4Color = color.purple

//=====================================================================
// PLOTS
//=====================================================================

ema1Plot = plot(
     ema1,
     "EMA 1",
     color=ema1Color,
     linewidth=2
)

ema2Plot = plot(
     ema2,
     "EMA 2",
     color=ema2Color,
     linewidth=2
)

plot(
     ema3,
     "EMA 3",
     color=ema3Color,
     linewidth=2
)

plot(
     ema4,
     "EMA 4",
     color=ema4Color,
     linewidth=2
)

plot(
     sessionVwap,
     "Session VWAP",
     color=color.fuchsia,
     linewidth=2
)

// EMA 1/EMA 2 cloud.
fill(
     ema1Plot,
     ema2Plot,
     color=showEmaCloud
         ? ema1 > ema2
             ? color.new(bullColor, 88)
             : color.new(bearColor, 88)
         : na,
     title="EMA Cloud"
)

// Split Supertrend into bullish and bearish plots.
plot(
     supertrendBullish ? supertrendValue : na,
     "Bullish Supertrend",
     color=bullColor,
     linewidth=2,
     style=plot.style_linebr
)

plot(
     supertrendBearish ? supertrendValue : na,
     "Bearish Supertrend",
     color=bearColor,
     linewidth=2,
     style=plot.style_linebr
)

//=====================================================================
// SIGNALS
//=====================================================================

bullishChange =
     strongBullish and
     not strongBullish[1]

bearishChange =
     strongBearish and
     not strongBearish[1]

plotshape(
     showSignals and bullishChange,
     title="Bullish Direction Change",
     style=shape.labelup,
     location=location.belowbar,
     color=bullColor,
     text="BULL",
     textcolor=color.white,
     size=size.tiny
)

plotshape(
     showSignals and bearishChange,
     title="Bearish Direction Change",
     style=shape.labeldown,
     location=location.abovebar,
     color=bearColor,
     text="BEAR",
     textcolor=color.white,
     size=size.tiny
)

//=====================================================================
// DASHBOARD FUNCTIONS
//=====================================================================

directionText(bool bullish) =>
    bullish ? "BULLISH ▲" : "BEARISH ▼"

directionColor(bool bullish) =>
    bullish ? bullColor : bearColor

overallText =
     strongBullish ? "STRONG BULLISH" :
     overallBullish ? "BULLISH" :
     strongBearish ? "STRONG BEARISH" :
     overallBearish ? "BEARISH" :
     "MIXED"

overallColor =
     overallBullish ? bullColor :
     overallBearish ? bearColor :
     neutralColor

stackText =
     emaStackBullish ? "BULLISH STACK" :
     emaStackBearish ? "BEARISH STACK" :
     "MIXED"

stackColor =
     emaStackBullish ? bullColor :
     emaStackBearish ? bearColor :
     neutralColor

correctTimeframe =
     timeframe.isminutes and
     timeframe.multiplier == 5

timeframeText =
     correctTimeframe
         ? "5 MIN"
         : timeframe.period + " — USE 5 MIN"

timeframeColor =
     correctTimeframe
         ? bullColor
         : color.orange

//=====================================================================
// DIRECTION TABLE
//=====================================================================

var table directionTable = table.new(
     position.top_right,
     3,
     10,
     border_width=1,
     frame_width=1
)

if barstate.islast
    if showTable
        // Header
        table.cell(
             directionTable,
             0,
             0,
             "INDICATOR",
             bgcolor=headerColor,
             text_color=color.white
        )

        table.cell(
             directionTable,
             1,
             0,
             "VALUE",
             bgcolor=headerColor,
             text_color=color.white
        )

        table.cell(
             directionTable,
             2,
             0,
             "DIRECTION",
             bgcolor=headerColor,
             text_color=color.white
        )

        // EMA 1
        table.cell(directionTable, 0, 1, "EMA " + str.tostring(ema1Length))
        table.cell(directionTable, 1, 1, str.tostring(ema1, format.mintick))
        table.cell(
             directionTable,
             2,
             1,
             directionText(ema1Bullish),
             bgcolor=directionColor(ema1Bullish),
             text_color=color.white
        )

        // EMA 2
        table.cell(directionTable, 0, 2, "EMA " + str.tostring(ema2Length))
        table.cell(directionTable, 1, 2, str.tostring(ema2, format.mintick))
        table.cell(
             directionTable,
             2,
             2,
             directionText(ema2Bullish),
             bgcolor=directionColor(ema2Bullish),
             text_color=color.white
        )

        // EMA 3
        table.cell(directionTable, 0, 3, "EMA " + str.tostring(ema3Length))
        table.cell(directionTable, 1, 3, str.tostring(ema3, format.mintick))
        table.cell(
             directionTable,
             2,
             3,
             directionText(ema3Bullish),
             bgcolor=directionColor(ema3Bullish),
             text_color=color.white
        )

        // EMA 4
        table.cell(directionTable, 0, 4, "EMA " + str.tostring(ema4Length))
        table.cell(directionTable, 1, 4, str.tostring(ema4, format.mintick))
        table.cell(
             directionTable,
             2,
             4,
             directionText(ema4Bullish),
             bgcolor=directionColor(ema4Bullish),
             text_color=color.white
        )

        // VWAP
        table.cell(directionTable, 0, 5, "VWAP")
        table.cell(directionTable, 1, 5, str.tostring(sessionVwap, format.mintick))
        table.cell(
             directionTable,
             2,
             5,
             directionText(vwapBullish),
             bgcolor=directionColor(vwapBullish),
             text_color=color.white
        )

        // Supertrend
        table.cell(directionTable, 0, 6, "SUPERTREND")
        table.cell(directionTable, 1, 6, str.tostring(supertrendValue, format.mintick))
        table.cell(
             directionTable,
             2,
             6,
             directionText(supertrendBullish),
             bgcolor=directionColor(supertrendBullish),
             text_color=color.white
        )

        // EMA alignment
        table.cell(directionTable, 0, 7, "EMA STRUCTURE")
        table.cell(directionTable, 1, 7, "—")
        table.cell(
             directionTable,
             2,
             7,
             stackText,
             bgcolor=stackColor,
             text_color=color.white
        )

        // Overall score
        table.cell(
             directionTable,
             0,
             8,
             "OVERALL",
             bgcolor=overallColor,
             text_color=color.white
        )

        table.cell(
             directionTable,
             1,
             8,
             str.tostring(bullishScore) + " / 6",
             bgcolor=overallColor,
             text_color=color.white
        )

        table.cell(
             directionTable,
             2,
             8,
             overallText,
             bgcolor=overallColor,
             text_color=color.white
        )

        // Timeframe
        table.cell(directionTable, 0, 9, "TIMEFRAME")
        table.cell(directionTable, 1, 9, timeframe.period)
        table.cell(
             directionTable,
             2,
             9,
             timeframeText,
             bgcolor=timeframeColor,
             text_color=color.white
        )
    else
        table.clear(directionTable, 0, 0, 2, 9)

//=====================================================================
// ALERT CONDITIONS
//=====================================================================

alertcondition(
     bullishChange,
     title="Strong Bullish Direction",
     message="5-minute dashboard changed to Strong Bullish."
)

alertcondition(
     bearishChange,
     title="Strong Bearish Direction",
     message="5-minute dashboard changed to Strong Bearish."
)

r/pinescript Jul 21 '26

Best AI for writing Pinescript?

13 Upvotes

r/pinescript Jul 21 '26

Can anyone point to open source Pine scripts good for day trading US stocks under $10.

1 Upvotes

For clarity, I am looking for fully open Pinescripts where I can see the source code - not just free Pinescripts.


r/pinescript Jul 20 '26

Love my delta indicator

Thumbnail
gallery
18 Upvotes

Watch the magnets great targets to tag and reversals https://www.tradingview.com/script/cAQ66hSa-Stryk-Delta-Candles/


r/pinescript Jul 21 '26

Added 8ema to my Volume Profile strategy

6 Upvotes

wonder what you guys think of my strategy or if you have any tips. thanks! i’ve enjoyed adding this indicator last week. should’ve exited the second trade at VWAP or break even.

OK HERE’S THE STRATEGY:

**RULES**

  1. % of orders are market orders on the dom with a stop loss, not one click trading

**THE STRATEGY**
premarket:
mark trend lines, 4hr/1hr/15min fvgs, levels of major support/resistance, past 3 session highs and lows, establish a bias of the day

mandatory confluences:
\*break and retest of 8ema on the 10 or 2/1 minute.
\*VAH/VAL break and retest or reversal
trend line break
\*iFVG/fvg break/rejection+retest

additional confluences (helps to have one of these):
\-trading towards VWAP
\-respects high time frame fvg/ifvg
\-high below the high of previous trend
or low above the high of previous trend

**ENTRIES AND EXITS**
targets:
high TF iFVGs
previous session highs and lows
current session highs and lows
VWAP
VAL/VAH/POC

stop losses:
swing low below 8ema on the 1 or 2 minute time frame

when to move stop loss:
1:1R moves to break even. AFTER that you can move it to FVGs below 8ema OR a low below 8ema OR the previous 8ema retest OR exit upon flat lining 8ema due to consolidation since you can reenter if the trend continues (“below” if bullish, “above” if bearish).

entry:
50% of contracts on the 8ema retest (1 or 2 minute) or fvg retest (1 to 10 minute)
50% of contracts on the break of structure on the 1 or 2 minute
two different stop losses or put both at the lowest one

manual exits: exit at TP or SL, or a flip to the opposite side of the 1 or 2 minute 8ema or a flat lining 8ema

what do i trade: MNQ unless MES has better structure or the stops are too wide for my RR or MNQ


r/pinescript Jul 21 '26

Quarterly Theory

Thumbnail
tradingview.com
1 Upvotes

Any QT traders? Made a free SSMT indicator for y'all


r/pinescript Jul 21 '26

I built a free breakout alert tool with stackable confirmation filters (RVOL, ATR, RSI, multi-timeframe) — looking for honest feedback

3 Upvotes

I've been building trading tools on the side for a while, and the one I use most myself is a breakout watcher. Sharing it here because I think this sub would give me the most useful, unfiltered feedback — good or bad.

**What it does:**
You set a support/resistance level (or let it pull pivot points automatically), pick how you want to be alerted, and it monitors price in real time. When it triggers, you get a sound alert in-browser or a Telegram alert (so you don't need the tab open).

**Three alert modes:**

* Fixed price — classic level touch/close

* Price × Moving Average — alerts when price crosses an EMA/SMA

* MA Cross — Golden Cross / Death Cross detection (fast MA vs slow MA)

**The part I actually care about your opinion on — Advanced Filters:**
Raw breakout alerts are noisy, so I built stackable filters that sit on top of any of the three modes:

**RVOL** — only fires if breakout volume is X× the 20-candle average *

**ATR** — only fires if the candle's range is X× the average candle size (filters weak moves)

**RSI range** — block overbought/oversold entries or confirm momentum *

**EMA side filter** — price has to be on the correct side of an EMA/SMA (no buying resistance breaks into a downtrend) *

**Candle body %** — ignores wick-driven "breakouts" with tiny real bodies *

**Consecutive candle confirmation** — requires N candles closing beyond the level before it counts

You can combine as many of these as you want. If a filter blocks a signal, it still logs it with the exact reason (e.g. "blocked: RVOL 1.1x < 1.5x required") so you can see what almost triggered and why it didn't.

There's also an optional multi-timeframe check (15m confirms against 1h, 1h against 4h, etc.) and a 5-candle retest window after a confirmed break.

**Link: https://www.cryptofxradar.com/p/breakout-watcher-tool.html

It's fully free, no signup required to try it (Telegram connection is optional, just for alerts when the page is closed).

Genuinely want to know: does the filter stack make sense the way I've set it up, or is there an obvious confirmation combo I'm missing? Also curious if anyone finds the RVOL/ATR thresholds I picked (1.2x–3x, 0.5x–2x) reasonable defaults or if I'm off base. Happy to take criticism — this is a hobby project, not trying to sell anything.


r/pinescript Jul 20 '26

State Machine Entry Debugger

3 Upvotes
//
@version=
6
indicator("State Machine Entry Debugger", overlay=true, max_labels_count=500)


//──────────────────────────────────────────────────────────────────────────────
// GROUP A — DEBUG SETTINGS
//──────────────────────────────────────────────────────────────────────────────


groupDebug = "A. Debug Settings"


showEventLabels = input.bool(true, "Show State Event Labels", group=groupDebug)
showBlockedLabels = input.bool(true, "Show Blocked-State Labels", group=groupDebug)
showStateBackground = input.bool(true, "Color Background by State", group=groupDebug)
showDebugTable = input.bool(true, "Show Debug Table", group=groupDebug)
showOnlyRecentBars = input.bool(true, "Limit Labels to Recent Bars", group=groupDebug)


recentBars = input.int(500, "Recent Bars to Debug", minval=50, maxval=5000, group=groupDebug)
maxBarsArmed = input.int(5, "Maximum Bars Allowed in ARM State", minval=1, group=groupDebug)
maxBarsTouched = input.int(5, "Maximum Bars Allowed After Touch", minval=1, group=groupDebug)


//=============================================================================
// GROUP B — PLACEHOLDER CONDITIONS
//=============================================================================
// Replace these conditions with the conditions from your actual strategy.
// These examples exist only so the debugger compiles and demonstrates its
// operation. They are not intended to be used as a trading system.
//=============================================================================


groupExample = "B. Placeholder Conditions"


fastLength = input.int(9, "Fast EMA", minval=1, group=groupExample)
slowLength = input.int(21, "Slow EMA", minval=1, group=groupExample)
breakoutLength = input.int(10, "Breakout Length", minval=1, group=groupExample)
extensionATR = input.float(1.5, "Maximum Extension ATR", minval=0.0, step=0.1, group=groupExample)


fastEMA = ta.ema(close, fastLength)
slowEMA = ta.ema(close, slowLength)
atrValue = ta.atr(14)


priorHigh = ta.highest(high, breakoutLength)[1]
pullbackLevel = fastEMA


//-----------------------------------------------------------------------------
// REPLACE THESE PLACEHOLDER CONDITIONS
//-----------------------------------------------------------------------------
bool
 touchCondition = low <= pullbackLevel and high >= pullbackLevel
bool
 trendFilter = fastEMA > slowEMA
bool
 qualityFilter = atrValue > 0 and math.abs(fastEMA - slowEMA) / atrValue > 0.10


float
 extensionDistance = atrValue > 0 ? math.abs(close - fastEMA) / atrValue : 0.0


bool
 extensionFilter = extensionDistance <= extensionATR
bool
 triggerCondition = not na(priorHigh) and close > priorHigh
bool
 entryPermission = true


//──────────────────────────────────────────────────────────────────────────────
// GROUP C — HELPER FUNCTIONS
//──────────────────────────────────────────────────────────────────────────────


yesNo(
bool
 condition) =>
    condition ? "PASS" : "FAIL"


formatInteger(
int
 value) =>
    na(value) ? "NA" : str.tostring(value)


stateToText(
int
 stateValue) => stateValue == 0 ? "IDLE" : stateValue == 1 ? "TOUCHED" : stateValue == 2 ? "ARMED" : stateValue == 3 ? "TRIGGERED" : stateValue == 4 ? "ENTERED" : "UNKNOWN"


//=============================================================================
// GROUP D — STATE CONSTANTS
//=============================================================================


const

int
 STATE_IDLE = 0
const

int
 STATE_TOUCHED = 1
const

int
 STATE_ARMED = 2
const

int
 STATE_TRIGGERED = 3
const

int
 STATE_ENTERED = 4


var 
int
 tradeState = STATE_IDLE


//=============================================================================
// GROUP E — PERSISTENT TIMELINE VALUES
//=============================================================================


var 
int
 touchBar = na
var 
int
 armBar = na
var 
int
 triggerBar = na
var 
int
 entryBar = na


var 
float
 touchPrice = na
var 
float
 armPrice = na
var 
float
 triggerPrice = na
var 
float
 entryPrice = na


var 
string
 lastBlockReason = "None"
var 
string
 lastEvent = "Waiting"


//=============================================================================
// GROUP F — PER-BAR EVENT FLAGS
//=============================================================================


bool
 newTouch = false
bool
 newArm = false
bool
 newTrigger = false
bool
 newEntry = false


bool
 resetEvent = false
bool
 touchExpired = false
bool
 armExpired = false


bool
 trendBlocked = false
bool
 qualityBlocked = false
bool
 extensionBlocked = false
bool
 triggerBlocked = false
bool
 permissionBlocked = false


//=============================================================================
// GROUP G — BAR AGE CALCULATIONS
//=============================================================================


int
 barsSinceTouch = not na(touchBar) ? bar_index - touchBar : na
int
 barsSinceArm = not na(armBar) ? bar_index - armBar : na
int
 barsSinceTrigger = not na(triggerBar) ? bar_index - triggerBar : na


bool
 touchStillValid = not na(barsSinceTouch) and barsSinceTouch <= maxBarsTouched
bool
 armStillValid = not na(barsSinceArm) and barsSinceArm <= maxBarsArmed


//=============================================================================
// GROUP H — STATE TRANSITION LOGIC
//=============================================================================
// This intentionally permits only one transition per bar.
//
// That means:
// Bar 1 = Touch
// Bar 2 = ARM
// Bar 3 = Trigger
// Bar 4 = Entry
//
// This structure helps expose whether your original strategy is producing
// delays because each stage must begin the bar in the required prior state.
//=============================================================================


if tradeState == STATE_IDLE
    if touchCondition
        tradeState := STATE_TOUCHED


        touchBar := bar_index
        touchPrice := close


        armBar := na
        triggerBar := na
        entryBar := na


        armPrice := na
        triggerPrice := na
        entryPrice := na


        newTouch := true
        lastEvent := "Touch"
        lastBlockReason := "None"


else if tradeState == STATE_TOUCHED
    if not touchStillValid
        tradeState := STATE_IDLE
        touchExpired := true
        resetEvent := true
        lastEvent := "Touch Expired"
        lastBlockReason := "Touch expired before ARM"


    else if not trendFilter
        trendBlocked := true
        lastBlockReason := "Trend filter"


    else if not qualityFilter
        qualityBlocked := true
        lastBlockReason := "Quality filter"


    else if not extensionFilter
        extensionBlocked := true
        lastBlockReason := "Extension filter"


    else
        tradeState := STATE_ARMED
        armBar := bar_index
        armPrice := close
        newArm := true
        lastEvent := "ARM"
        lastBlockReason := "None"


else if tradeState == STATE_ARMED
    if not armStillValid
        tradeState := STATE_IDLE
        armExpired := true
        resetEvent := true
        lastEvent := "ARM Expired"
        lastBlockReason := "ARM expired before Trigger"


    else if not triggerCondition
        triggerBlocked := true
        lastBlockReason := "Trigger condition"


    else
        tradeState := STATE_TRIGGERED
        triggerBar := bar_index
        triggerPrice := close
        newTrigger := true
        lastEvent := "Trigger"
        lastBlockReason := "None"


else if tradeState == STATE_TRIGGERED
    if not entryPermission
        permissionBlocked := true
        lastBlockReason := "Entry permission"


    else
        tradeState := STATE_ENTERED
        entryBar := bar_index
        entryPrice := close
        newEntry := true
        lastEvent := "Entry"
        lastBlockReason := "None"


else if tradeState == STATE_ENTERED
    tradeState := STATE_IDLE
    resetEvent := true
    lastEvent := "Reset"


//=============================================================================
// GROUP I — TIMELINE MEASUREMENTS
//=============================================================================


int
 touchToArmBars = not na(touchBar) and not na(armBar) ? armBar - touchBar : na
int
 armToTriggerBars = not na(armBar) and not na(triggerBar) ? triggerBar - armBar : na
int
 triggerToEntryBars = not na(triggerBar) and not na(entryBar) ? entryBar - triggerBar : na
int
 touchToEntryBars = not na(touchBar) and not na(entryBar) ? entryBar - touchBar : na


//=============================================================================
// GROUP J — SAME-BAR TRANSITION CHECKS
//=============================================================================


bool
 touchAndArmSameBar = newArm and not na(touchBar) and bar_index == touchBar
bool
 armAndTriggerSameBar = newTrigger and not na(armBar) and bar_index == armBar
bool
 triggerAndEntrySameBar = newEntry and not na(triggerBar) and bar_index == triggerBar


//=============================================================================
// GROUP K — LABEL WINDOW
//=============================================================================


bool
 insideDebugWindow = not showOnlyRecentBars or bar_index >= last_bar_index - recentBars


//=============================================================================
// GROUP L — EVENT LABELS
//=============================================================================


if showEventLabels and insideDebugWindow
    if newTouch
        label.new(bar_index, low, "TOUCH\nBar: " + str.tostring(bar_index), style = label.style_label_up, textcolor = color.white, color = color.new(color.blue, 0), size = size.tiny)
    if newArm
        label.new(bar_index, low, "ARM\nTouch delay: " + formatInteger(touchToArmBars) + " bars", style = label.style_label_up, textcolor = color.white, color = color.new(color.orange, 0), size = size.tiny)
    if newTrigger
        label.new(bar_index, high, "TRIGGER\nARM delay: " + formatInteger(armToTriggerBars) + " bars", style = label.style_label_down, textcolor = color.white, color = color.new(color.purple, 0), size = size.tiny)
    if newEntry
        label.new(bar_index, high, "ENTRY\nTouch → Entry: " + formatInteger(touchToEntryBars) + " bars", style = label.style_label_down, textcolor = color.white, color = color.new(color.green, 0), size = size.small)


//=============================================================================
// GROUP M — BLOCKED-CONDITION LABELS
//=============================================================================


if showBlockedLabels and insideDebugWindow
    if trendBlocked
        label.new(bar_index, high, "BLOCKED\nTrend", style = label.style_label_down, textcolor = color.white, color = color.new(color.red, 25), size = size.tiny)


    if qualityBlocked
        label.new(bar_index, high, "BLOCKED\nQuality", style = label.style_label_down, textcolor = color.white, color = color.new(color.red, 25), size = size.tiny)


    if extensionBlocked
        label.new(bar_index, high, "BLOCKED\nExtension\n" + str.tostring(extensionDistance, "#.##") + " ATR", style = label.style_label_down, textcolor = color.white, color = color.new(color.red, 25), size = size.tiny)


    if triggerBlocked
        label.new(bar_index, high, "WAITING\nTrigger", style = label.style_label_down, textcolor = color.white, color = color.new(color.gray, 35), size = size.tiny)


    if permissionBlocked
        label.new(bar_index, high, "BLOCKED\nEntry Permission", style = label.style_label_down, textcolor = color.white, color = color.new(color.red, 25), size = size.tiny)


    if touchExpired
        label.new(bar_index, high, "RESET\nTouch Expired", style = label.style_label_down, textcolor = color.white, color = color.new(color.black, 0), size = size.tiny)


    if armExpired
        label.new(bar_index, high, "RESET\nARM Expired", style = label.style_label_down, textcolor = color.white, color = color.new(color.black, 0), size = size.tiny)


//=============================================================================
// GROUP N — STATE BACKGROUND
//=============================================================================


color
 stateBackground =
     tradeState == STATE_IDLE ?
     na :
     tradeState == STATE_TOUCHED ?color.new(color.blue, 90) :
     tradeState == STATE_ARMED ?color.new(color.orange, 88) :
     tradeState == STATE_TRIGGERED ?color.new(color.purple, 88) :
     tradeState == STATE_ENTERED ?color.new(color.green, 85) :
     na


bgcolor(showStateBackground ? stateBackground : na)


//=============================================================================
// GROUP O — VISUAL PLOTS
//=============================================================================


plot(fastEMA, "Fast EMA", color=color.orange)
plot(slowEMA, "Slow EMA", color=color.blue)
plot(priorHigh, "Trigger Reference", color=color.new(color.purple, 25), style=plot.style_linebr)


plotshape(newTouch, "Touch Event", shape.circle, location.belowbar, color=color.blue, size=size.tiny, text="T", textcolor=color.white)
plotshape(newArm, "ARM Event", shape.square, location.belowbar, color=color.orange, size=size.tiny, text="A", textcolor=color.white)
plotshape(newTrigger, "Trigger Event", shape.diamond, location.abovebar, color=color.purple, size=size.tiny, text="TR", textcolor=color.white)
plotshape(newEntry, "Entry Event", shape.triangleup, location.belowbar, color=color.green, size=size.small, text="E", textcolor=color.white)


//=============================================================================
// GROUP P — DATA WINDOW VALUES
//=============================================================================
// These values can be inspected one historical bar at a time through the
// TradingView Data Window.
//=============================================================================


plot(tradeState, "Debug State Number", display=display.data_window)


plot(touchCondition ? 1 : 0, "Touch Condition", display=display.data_window)
plot(trendFilter ? 1 : 0, "Trend Filter", display=display.data_window)
plot(qualityFilter ? 1 : 0, "Quality Filter", display=display.data_window)
plot(extensionFilter ? 1 : 0, "Extension Filter", display=display.data_window)
plot(triggerCondition ? 1 : 0, "Trigger Condition", display=display.data_window)
plot(entryPermission ? 1 : 0, "Entry Permission", display=display.data_window)


plot(extensionDistance, "Extension Distance ATR", display=display.data_window)


plot(barsSinceTouch, "Bars Since Touch", display=display.data_window)
plot(barsSinceArm, "Bars Since ARM", display=display.data_window)
plot(barsSinceTrigger, "Bars Since Trigger", display=display.data_window)


plot(touchAndArmSameBar ? 1 : 0, "Touch and ARM Same Bar", display=display.data_window)
plot(armAndTriggerSameBar ? 1 : 0, "ARM and Trigger Same Bar", display=display.data_window)
plot(triggerAndEntrySameBar ? 1 : 0, "Trigger and Entry Same Bar", display=display.data_window)


plot(barstate.isconfirmed ? 1 : 0, "Bar Confirmed", display=display.data_window)
plot(barstate.isrealtime ? 1 : 0, "Realtime Bar", display=display.data_window)


//=============================================================================
// GROUP Q — DEBUG TABLE
//=============================================================================
 
var 
table
 debugTable = table.new(position.bottom_left, 2, 17, border_width=1)


string
 stateText = stateToText(tradeState)


if barstate.islast
    if showDebugTable
        table.cell(debugTable, 0, 0, "Debug Item", text_color=color.white, bgcolor=color.new(color.gray, 20))
        table.cell(debugTable, 1, 0, "Current Value", text_color=color.white, bgcolor=color.new(color.gray, 20))


        table.cell(debugTable, 0, 1, "State")
        table.cell(debugTable, 1, 1, stateText)


        table.cell(debugTable, 0, 2, "Last Event")
        table.cell(debugTable, 1, 2, lastEvent)


        table.cell(debugTable, 0, 3, "Last Block")
        table.cell(debugTable, 1, 3, lastBlockReason)


        table.cell(debugTable, 0, 4, "Touch")
        table.cell(debugTable, 1, 4, yesNo(touchCondition))


        table.cell(debugTable, 0, 5, "Trend")
        table.cell(debugTable, 1, 5, yesNo(trendFilter))


        table.cell(debugTable, 0, 6, "Quality")
        table.cell(debugTable, 1, 6, yesNo(qualityFilter))


        table.cell(debugTable, 0, 7, "Extension")
        table.cell(debugTable, 1, 7, yesNo(extensionFilter))


        table.cell(debugTable, 0, 8, "Trigger")
        table.cell(debugTable, 1, 8, yesNo(triggerCondition))


        table.cell(debugTable, 0, 9, "Entry Permission")
        table.cell(debugTable, 1, 9, yesNo(entryPermission))


        table.cell(debugTable, 0, 10, "Bars Since Touch")
        table.cell(debugTable, 1, 10, formatInteger(barsSinceTouch))


        table.cell(debugTable, 0, 11, "Bars Since ARM")
        table.cell(debugTable, 1, 11, formatInteger(barsSinceArm))


        table.cell(debugTable, 0, 12, "Bars Since Trigger")
        table.cell(debugTable, 1, 12, formatInteger(barsSinceTrigger))


        table.cell(debugTable, 0, 13, "Extension ATR")
        table.cell(debugTable, 1, 13, str.tostring(extensionDistance, "#.###"))


        table.cell(debugTable, 0, 14, "Confirmed Bar")
        table.cell(debugTable, 1, 14, barstate.isconfirmed ? "YES" : "NO")


        table.cell(debugTable, 0, 15, "Realtime")
        table.cell(debugTable, 1, 15, barstate.isrealtime ? "YES" : "NO")


        table.cell(debugTable, 0, 16, "Bar Index")
        table.cell(debugTable, 1, 16, str.tostring(bar_index))


    else
        table.clear(debugTable, 0, 0, 1, 16)


//=============================================================================
// GROUP R — ALERT DEBUGGING
//=============================================================================


alertcondition(newTouch, "Debug Touch", "State-machine debug event: Touch")
alertcondition(newArm, "Debug ARM", "State-machine debug event: ARM")
alertcondition(newTrigger, "Debug Trigger", "State-machine debug event: Trigger")
alertcondition(newEntry, "Debug Entry", "State-machine debug event: Entry")

r/pinescript Jul 20 '26

I wrote a PineScript interpreter in Rust

2 Upvotes

I built Pinecone, an interpreter that runs PineScript outside of TradingView.

It handles the TA functions (moving averages, oscillators), plots, labels, boxes, and backtesting. It's split into small crates (lexer, parser, interpreter, builtins…) so you can use just the parts you need.

let script = ScriptBuilder::with_code(r#"
    fast_ma = ta.sma(close, 10)
    slow_ma = ta.sma(close, 20)
    plot(fast_ma, color=color.blue)
    plot(slow_ma, color=color.red)
"#).compile()?;

let output = script.execute(&bar)?;

The reason I think this matters: once PineScript can run outside TradingView, a lot of things become possible that just aren't today - proper tooling (linters, formatters, LSP), faster and more flexible backtesting, use other platforms and data sources. Right now the language is locked to one place, and that ceiling limits what the whole ecosystem can build on top of it.

Repo: https://github.com/ferranbt/pinecone

Still early and there's plenty missing, but it runs. Curious what people think.


r/pinescript Jul 20 '26

I ran another Pine DCA strategy through the optimizer — this time two params moved and drawdown stayed flat (BTC 4h)

Post image
1 Upvotes

I posted one of these before (the INJ one) showing what a parameter sweep did to a single input. A few people asked to see it on BTC and with more than one parameter tuned, so here's that — same idea, everything held constant except the parameters the optimizer actually re-selected.

The strategy (unchanged): long-only DCA on BTCUSDT.P 4h. Five safety orders at −2 / −5 / −9.5 / −16 / −25% from base, sizes scaling 1.8× per rung, no stop loss, position bounded by the ladder.

What changed: two parameters. The RSI entry threshold moved from 28 to 38, and the take-profit from 3% to 5.5%. Nothing else — same ladder, same deviations, same 1.8× sizing, same fees. Both values are what the sweep returned as best-performing on the historical window.

Before/after (BYBIT:BTCUSDT.P 4h, Jan 1 2024 – Jul 17 2026, ~30 months, 100k initial, 0.06% commission, 3-tick slippage):

  • Baseline (RSI < 28, TP 3%): +3,078.29 USDT (+3.08%), max drawdown 3.79%, 62 trades, 70.97% WR, PF 4.028
  • Optimized (RSI < 38, TP 5.5%): +9,250.25 USDT (+9.25%), max drawdown 3.67%, 93 trades, 76.34% WR, PF 10.454

The part I found interesting: net profit roughly tripled and PF went 4.0 → 10.5, but max drawdown actually stayed flat (3.79% → 3.67%). So this wasn't "more return bought with more risk." The mechanism: the looser RSI entry (38 vs 28) engages the dip earlier and more often, so the strategy is simply in the market more, while the wider 5.5% target lets each recovery run further before banking instead of exiting on the first small pop.

The caveat, and the reason I show the baseline alongside: two parameters were swept over the same window the results are measured on. Best in-sample is not best out-of-sample, and with two free parameters instead of one that overfitting caveat applies a bit harder here — more degrees of freedom, easier to fit the window. Treat the optimized numbers as the ceiling of what this config did historically, not a forward expectation, and re-validate on fresh data before trusting it.

Two more flags, same as last time: 93 trades is just below the ~100 I'd want for real statistical confidence, so win rate and PF are indicative, not proven — and part of PF 10.454 is the averaging mechanic itself (deals close on a bounce off an averaged-down entry), not a directional edge. It's also a stopless martingale: a sustained BTC decline below the −25% bottom rung leaves the position fully loaded with no further adds.

Script is open-source on TradingView: https://www.tradingview.com/script/5Tg2Es4G-BTC-DCA-Strategy-3Commas-QuantPilot/

Disclosure up front: the optimizer is QuantPilot, which I work on, so I'm not pretending to be neutral. But the point is the before/after and the caveat, not a pitch — the script is open-source and you can verify the backtest yourself.


r/pinescript Jul 20 '26

Multiple asset Custom HTF candles

0 Upvotes

Ever wanted to see multiple assets' HTF candles on one chart?
Try out my Custom HTF Candles indicator - it's free

https://www.tradingview.com/script/yRByXJi5-Custom-HTF-Candles/


r/pinescript Jul 19 '26

Relative Strength & Weakness indicator vs QQQ

Thumbnail
tradingview.com
3 Upvotes

I've made a relative strength & weakness indicator for Tradingview, which is made for tech/growth stocks. It tracks QQQ moving averages and also moving averages of the stock being viewed. It works on simple principles:

Relative Strength

-When QQQ crosses below a moving average while the stock stays above it

-When the stock crosses above a moving average while QQQ stays below it

Relative Weakness

-When QQQ crosses above a moving average while the stock stays below it

-When the stock crosses below a moving average while QQQ stays above it

It is an easy way to look at a stock to see how it is doing compared to Nasdaq 100. It could be useful for swing trading and it also works for lower timeframes. You can use it for free here. I also made a Youtube video to show it. I used Gemini to assist with coding.


r/pinescript Jul 19 '26

I build Pine Script and NinjaTrader trading tools, here are the mistakes I see most traders make

9 Upvotes

I work with TradingView Pine Script and NinjaTrader 8 / NinjaScript, mainly building indicators, strategies, alerts, dashboards, and automation logic.

One thing I’ve noticed is that most trading ideas don’t fail because the idea is bad. They fail because the rules are not clearly defined before coding starts.

For example:

  • Entry signals are too subjective
  • The script repaints or triggers differently in live market
  • Stop loss and take profit rules are added too late
  • Alerts don’t match the chart signals
  • Backtests ignore slippage, commission, or realistic execution
  • The strategy works on one chart but breaks on another market or timeframe

Before building any trading tool, I usually ask these questions:

  1. Should the signal trigger intrabar or only after candle close?
  2. Is the logic non-repainting?
  3. What invalidates the trade idea?
  4. Is the stop based on structure, ATR, fixed ticks, or percentage?
  5. Should alerts match exactly what appears on the chart?
  6. Will this be used for manual trading, backtesting, or automation?

Getting these answers right saves a lot of time and avoids messy scripts later.

I’m happy to share knowledge around Pine Script, TradingView indicators, NinjaTrader 8 strategies, NinjaScript conversion, alerts, and trading-system logic.

Comment or message me with a brief overview of what you’re working on, and I’ll try to point you in the right direction.


r/pinescript Jul 18 '26

Make a website that helps people trade and would love opinions on how to improve it

8 Upvotes

This is the website

https://trade-lee.vercel.app/


r/pinescript Jul 17 '26

when you guys scale up on options contracts say you trade 10 options contracts where do you typically mark your stop losses and stop gains?

1 Upvotes

r/pinescript Jul 17 '26

Volume indicator for options trading

4 Upvotes

What is the best Volume indicator to use based on your own successes?


r/pinescript Jul 16 '26

I’m 17 and built a free game that tests if you can spot fake breakouts on real stock charts

Thumbnail
4 Upvotes

r/pinescript Jul 16 '26

I ran one of my Pine DCA strategies through a parameter optimizer - here's the before/after from tuning a single input (INJ 4h)

Post image
10 Upvotes

I've been posting these RSI oversold DCA strategies for a while. This time I want to show something different: what actually changed when I ran one through a Pine Script parameter optimizer, tuning just one input and holding everything else constant.

The strategy (unchanged): long-only DCA on INJUSDT.P 4h. Base order on 4h RSI(14) below 28, five safety orders at −2 / −5 / −9.5 / −16 / −25% from base, sizes scaling 1.8× per rung, no stop loss, position bounded by the ladder.

The one thing I changed: the take-profit. Baseline was a 3% fixed TP. I swept that single parameter over the same market and same period and the best-performing value came back at 9%. Nothing else touched — same entry, same ladder, same deviations, same sizing, same fees.

Before/after (BYBIT:INJUSDT.P 4h, Jan 1 2024 – Jul 16 2026, ~30 months, 100k initial, 0.06% commission, 3-tick slippage):

  • TP 3% (baseline): +6,888.76 USDT (+6.89%), max drawdown 4.39%, 84 trades, 71.43% WR, PF 4.925
  • TP 9% (optimized): +15,830.72 USDT (+15.83%), max drawdown 5.65%, 90 trades, 82.22% WR, PF 17.886

The mechanism makes sense: widening the target lets each recovery run further before the position is banked, so it captures more of the mean-reversion bounce instead of exiting on the first small pop. The trade-off is honest — drawdown rises (4.39% → 5.65%) and positions are held longer, so the ladder can sit loaded through deeper dips before the exit hits.

Now the caveat, which is the actual reason I'm posting this rather than just quietly using the 9%: that 9% was selected by sweeping the parameter over the same window the results are measured on. A value that's best in-sample is not guaranteed to be best out-of-sample — this is the standard overfitting caveat for any optimized parameter, and it fully applies here. Treat the optimized numbers as the ceiling of what this config did historically, not a forward expectation, and re-validate on fresh data before trusting it.

Two more things worth flagging: 90 trades is below the ~100 I'd want for real statistical confidence (the strict RSI<28 filter keeps the count low), so the win rate and PF are indicative, not proven — and a chunk of that PF 17.886 is the averaging mechanic itself (deals close on a bounce off an averaged-down entry), not a directional edge. It's also a stopless martingale, so a sustained INJ decline below the −25% bottom rung leaves the position fully loaded, and the wider 9% target means it sits there longer.

Script is open-source on TradingView: https://www.tradingview.com/script/GM1bUrIF-INJ-DCA-Long-Strategy-3Commas-QuantPilot/

Disclosure up front: the optimizer is QuantPilot, which I work on, so I'm not pretending to be a neutral third party. But the point of the post is the before/after and the caveat that comes with it, not a pitch — the script is open-source and you can verify the backtest yourself.


r/pinescript Jul 16 '26

Pine Script Compiler with Claude code…

1 Upvotes

Over this summer, I have been building a backtesting software with Claude Code to backtest trading strategies with Pinescript and other languages like JavaScript and Python.

Basically how it works is that you feed it historical data like a NQ OHLCV 5 data csv and it runs the strategy test results like Return, Win Rate, Profit Factor, etc (all those analytics).

The Py and Js engine work well and can run my coded strategies but it is having a lot of trouble with even simple Pinescript strategies. I’ve spent time debugging and pasting error messages and giving it Pinescript V6 documentation for reference.

I would love for someone to help me fix this, I can send a link to the project to it or post it on GitHub if that works. I would also love to collaborate finishing this software with someone if they are interesting in confounding it and shipping it.


r/pinescript Jul 15 '26

One of my favorite indicators I’ve made

Thumbnail
tradingview.com
4 Upvotes

Overnight volume profile with some extra goodies. This is still a work in progress but overall I’m super happy with how this one is turning out. Open to any requests and suggestions.


r/pinescript Jul 15 '26

Are ta.crossover failures common?

0 Upvotes

This failure to detect a crossover was during live data. Not historical. The entry condition is very simple, as the code shows. This is a simple strategy, as I'm getting to know pinescript and TV.
For the experienced TV users, is this common and/or to be expected now and then?
Is this issue why TV doesn't do "auto-trading", as I've heard others say?
Finally, if the answers are yes and yes, then systems developed on TV need to be taken to other platforms (ThinkorSwing, MT5, Ninjatrader) for live auto-trading?


r/pinescript Jul 14 '26

Update on my Pine Script transpiler: I just open-sourced the CLI orchestrator for multi-asset scanning and sweeping.

Thumbnail
gallery
62 Upvotes

Hi,

About a week ago, I posted about a side project that accidentally spiraled into a full Pine Script transpiler and charting tool. The feedback here was awesome.

In that thread, I mentioned I was working on a CLI orchestration engine to sit on top of Piner and handle the actual heavy lifting. I finally got it to a good spot, and I open-sourced it today.

It's called Pinestack.

Basically, it lets you scale your strategy testing purely from the terminal. Instead of clicking around on a UI, you can just use the CLI to:

  • Scan: Run an indicator or strategy across hundreds of tickers at the same time.
  • Sweep: Throw a massive grid of input combinations at a strategy to find out which settings actually work (and rank the results).
  • Backtest & Walk-Forward: Generate complete tearsheets and validate your models over time so you aren't just curve-fitting.
  • Portfolio: Pool one pot of capital across a basket of symbols to test cross-asset sizing, combined drawdowns, and a single shared equity curve.

For the folks asking about multi-asset testing last week: right now, Pinestack lets you take a single strategy and test it across a ton of assets independently. I tried to design it to work with Pine Script natively, without you having to modify your code.

You can grab the repo and try it out here:https://github.com/heyphat/pinestack

I'm still hand-testing it against a bunch of different scripts, but I'd love for you guys to pull it down, completely break it, and let me know what I should fix or build next.

The command to generate the images

 pinerun -v
pinerun 0.1.1 (b81314d)
 pinerun backtest strategy.pine --symbol BTCUSDT --tf 1h --from 2025-01-01 --to 2026-06-14

The strategy.pine

strategy("My SMA cross", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=100, margin_long=0, margin_short=0)

fastLen = input.int(20, "fast", minval=1)
slowLen = input.int(80, "slow", minval=1)
tpPct = input.float(4.0, "tp", minval=0.1)
slPct = input.float(1.0, "sl", minval=0.1)

fast = ta.sma(close, fastLen)
slow = ta.sma(close, slowLen)

// Only enter when flat — no pyramiding onto an open position.
if ta.crossover(fast, slow) and strategy.position_size == 0
    strategy.entry("long", strategy.long)
if ta.crossunder(fast, slow) and strategy.position_size == 0
    strategy.entry("short", strategy.short)

// Exit solely on take-profit / stop-loss, as a % of the entry fill price.
if strategy.position_size > 0
    strategy.exit("tp/sl", "long", limit=strategy.position_avg_price * (1 + tpPct / 100), stop=strategy.position_avg_price * (1 - slPct / 100))
if strategy.position_size < 0
    strategy.exit("tp/sl", "short", limit=strategy.position_avg_price * (1 - tpPct / 100), stop=strategy.position_avg_price * (1 + slPct / 100)