STOCK

Intraday Strategy Pine Script

 

// Intraday_Strategy_PineScript_v2
// Pine Script v5 strategy for TradingView
// Added features:
// – Rich alert messages
// – Order management (max trades per day, trading time window)
// – Multiple timeframe trend filter (higher timeframe EMAs)
// – Take-profit scaling (partial TP1, remaining TP2)
// – Optional trailing stop after partial take-profit
// – Cleaner inputs & comments

//@version=5
strategy(“Intraday EMA+Supertrend+RSI – v2”, overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=5, initial_capital=100000, pyramiding=1)

///////// INPUTS /////////
// EMAs
ema1_len = input.int(7, “EMA Fast (7)”)
ema2_len = input.int(21, “EMA Mid (21)”)
ema3_len = input.int(50, “EMA Slow (50)”)

// Higher timeframe filter
htf_period = input.timeframe(“15”, “Higher Timeframe for Trend Filter”)
use_htf_filter = input.bool(true, “Enable Higher Timeframe Trend Filter”)
htf_ema_len = input.int(21, “HTF EMA Length”)

// Supertrend
st_len = input.int(10, “Supertrend ATR Length”)
st_mult = input.float(3.0, “Supertrend Multiplier”)

// RSI
rsi_len = input.int(14, “RSI Length”)
rsi_buy_level = input.int(45, “RSI Buy Level (>=)”)
rsi_sell_level = input.int(55, “RSI Sell Level (<=)”)

// Opening range
use_opening_range = input.bool(true, “Use Opening Range Breakout (first N bars)”)
opening_range_bars = input.int(3, “Opening Range Bars (first N bars)”)

// Previous day levels
use_prevday_levels = input.bool(true, “Use Previous Day High/Low as alternative”)

// Order management
max_trades_per_day = input.int(3, “Max Trades Per Day (0 = unlimited)”)
trade_start_time = input.time(“09:15”, “Trade Window Start (exchange time)”)
trade_end_time = input.time(“15:20”, “Trade Window End (exchange time)”)

// Stoploss and profit target
use_atr_stop = input.bool(true, “Use ATR-based Stop Loss”)
atr_stop_mult = input.float(1.5, “ATR Stop Multiplier”)
use_fixed_stop_percent = input.bool(false, “Use Fixed Stop Loss (%) instead of ATR”)
fixed_stop_percent = input.float(0.7, “Fixed Stop Loss (%) of entry price”)
profit_target_r1 = input.float(1.0, “TP1 (R multiple)”)
profit_target_r2 = input.float(2.5, “TP2 (R multiple)”)
partial_take_percent = input.float(50, “TP1 Qty % (percent of position)”)
use_trailing_after_partial = input.bool(true, “Enable Trailing Stop on remaining position after TP1”)
trailing_offset_atr_mult = input.float(0.8, “Trailing Stop Offset (ATR multiples)”)

// Position sizing
qty_percent = input.float(5.0, “Position Size (% of equity) for each trade”)

// Misc
show_labels = input.bool(true, “Show Entry/Exit Labels”)
show_info_table = input.bool(true, “Show Info Table”)

///////// INDICATORS /////////
ema1 = ta.ema(close, ema1_len)
ema2 = ta.ema(close, ema2_len)
ema3 = ta.ema(close, ema3_len)

// HTF EMA for trend confirmation
htf_ema = request.security(syminfo.tickerid, htf_period, ta.ema(close, htf_ema_len))
htf_close = request.security(syminfo.tickerid, htf_period, close)

// ATR & Supertrend
atr = ta.atr(st_len)

// Supertrend implementation (classic)
var float upperBand = na
var float lowerBand = na
var int direction = 1
float hl2 = (high + low) / 2
float basicUpper = hl2 + st_mult * atr
float basicLower = hl2 – st_mult * atr
if na(upperBand)
upperBand := basicUpper
lowerBand := basicLower
direction := 1
else
upperBand := (basicUpper < nz(upperBand[1]) or close[1] > nz(upperBand[1])) ? basicUpper : nz(upperBand[1])
lowerBand := (basicLower > nz(lowerBand[1]) or close[1] < nz(lowerBand[1])) ? basicLower : nz(lowerBand[1])

if close > nz(upperBand[1])
direction := 1
else
if close < nz(lowerBand[1])
direction := -1
else
direction := nz(direction[1])

supertrend = direction == 1 ? lowerBand : upperBand
supertrend_bull = direction == 1
supertrend_bear = direction == -1

// RSI
rsi = ta.rsi(close, rsi_len)

///////// PREVIOUS DAY LEVELS /////////
prevDayHigh = request.security(syminfo.tickerid, “D”, high[1])
prevDayLow = request.security(syminfo.tickerid, “D”, low[1])
prevDayClose = request.security(syminfo.tickerid, “D”, close[1])

///////// OPENING RANGE /////////
var float oRangeHigh = na
var float oRangeLow = na
var int or_count = 0
is_newday = ta.change(time(“D”))
if is_newday
oRangeHigh := high
oRangeLow := low
or_count := 1
else
if or_count > 0 and or_count < opening_range_bars
oRangeHigh := math.max(oRangeHigh, high)
oRangeLow := math.min(oRangeLow, low)
or_count += 1
else
or_count := or_count

///////// TRADE WINDOW & COUNTERS /////////
in_trade_window = time(timeframe.period, trade_start_time, trade_end_time)

var int trades_today = 0
var int day_of = na
prev_pos_size = nz(strategy.position_size[1])
// reset daily counter
if day_of != dayofyear(time)
day_of := dayofyear(time)
trades_today := 0

// detect new entry fill to increment counter
if (prev_pos_size == 0 and strategy.position_size != 0)
trades_today += 1

can_take_trade = (max_trades_per_day == 0) or (trades_today < max_trades_per_day)
can_trade_now = in_trade_window and can_take_trade

///////// SIGNAL RULES /////////
// Trend filter using EMAs on current TF
bullish_ema = ema1 > ema2 and ema2 > ema3
bearish_ema = ema1 < ema2 and ema2 < ema3

// HTF trend: price above HTF EMA implies HTF bullish
htf_bull = htf_close > htf_ema
htf_bear = htf_close < htf_ema

trend_ok_long = bullish_ema and (not use_htf_filter or htf_bull)
trend_ok_short = bearish_ema and (not use_htf_filter or htf_bear)

// Breakout levels
var float buyLevel = na
var float sellLevel = na
if use_opening_range and not na(oRangeHigh) and not na(oRangeLow)
buyLevel := oRangeHigh
sellLevel := oRangeLow
else
buyLevel := prevDayHigh
sellLevel := prevDayLow

// Entry conditions with filters
longCondition = trend_ok_long and supertrend_bull and rsi >= rsi_buy_level and close > buyLevel and can_trade_now
shortCondition = trend_ok_short and supertrend_bear and rsi <= rsi_sell_level and close < sellLevel and can_trade_now

///////// ORDER MANAGEMENT & TP/SL /////////
// We’ll place entries and then two exits (TP1 partial, TP2 remaining), plus SL (ATR or fixed).

// compute stops & targets
var float entryPrice = na
var float stopPrice = na
var float tp1Price = na
var float tp2Price = na

if longCondition and strategy.position_size == 0
entryPrice := close
stopPrice := use_atr_stop ? (entryPrice – atr * atr_stop_mult) : (entryPrice * (1 – fixed_stop_percent / 100))
tp1Price := entryPrice + (entryPrice – stopPrice) * profit_target_r1
tp2Price := entryPrice + (entryPrice – stopPrice) * profit_target_r2
strategy.entry(“Long”, strategy.long, qty_percent=qty_percent)
// partial take-profit
strategy.exit(“L-TP1″, from_entry=”Long”, limit=tp1Price, qty_percent=partial_take_percent)
// remaining TP2 and stoploss
strategy.exit(“L-TP2/SL”, from_entry=”Long”, stop=stopPrice, limit=tp2Price)

if shortCondition and strategy.position_size == 0
entryPrice := close
stopPrice := use_atr_stop ? (entryPrice + atr * atr_stop_mult) : (entryPrice * (1 + fixed_stop_percent / 100))
tp1Price := entryPrice – (stopPrice – entryPrice) * profit_target_r1
tp2Price := entryPrice – (stopPrice – entryPrice) * profit_target_r2
strategy.entry(“Short”, strategy.short, qty_percent=qty_percent)
strategy.exit(“S-TP1″, from_entry=”Short”, limit=tp1Price, qty_percent=partial_take_percent)
strategy.exit(“S-TP2/SL”, from_entry=”Short”, stop=stopPrice, limit=tp2Price)

// Trailing stop on remaining position after TP1: implement by switching on a boolean when TP1 hit
var bool long_tp1_hit = false
var bool short_tp1_hit = false

// detect TP1 hits by checking closed trades or comparing prices
if strategy.position_size == 0
// reset flags at new flat
long_tp1_hit := false
short_tp1_hit := false
else
// if position exists and price crosses TP1 then mark
if strategy.position_size > 0 and not long_tp1_hit and high >= tp1Price
long_tp1_hit := true
if strategy.position_size < 0 and not short_tp1_hit and low <= tp1Price
short_tp1_hit := true

// apply trailing stop by adding an extra exit with trail offset (only if enabled and TP1 hit)
if use_trailing_after_partial
if long_tp1_hit and strategy.position_size > 0
trail_offset = atr * trailing_offset_atr_mult
// create/modify trailing exit (name unique)
strategy.exit(“L-TRAIL”, from_entry=”Long”, trail_points=trail_offset)
if short_tp1_hit and strategy.position_size < 0
trail_offset = atr * trailing_offset_atr_mult
strategy.exit(“S-TRAIL”, from_entry=”Short”, trail_points=trail_offset)

///////// PLOTTING /////////
plot(ema1, title=”EMA 7″, linewidth=2)
plot(ema2, title=”EMA 21″, linewidth=2)
plot(ema3, title=”EMA 50″, linewidth=2)
plot(supertrend, title=”Supertrend”, linewidth=2)

plot(use_prevday_levels ? prevDayHigh : na, title=”PrevDay High”, style=plot.style_linebr, linewidth=1)
plot(use_prevday_levels ? prevDayLow : na, title=”PrevDay Low”, style=plot.style_linebr, linewidth=1)
plot(use_opening_range and not na(oRangeHigh) ? oRangeHigh : na, title=”Opening Range High”, linewidth=1)
plot(use_opening_range and not na(oRangeLow) ? oRangeLow : na, title=”Opening Range Low”, linewidth=1)

if show_labels
if longCondition
label.new(bar_index, high, “LONG”, style=label.style_label_up, textcolor=color.white, size=size.small)
if shortCondition
label.new(bar_index, low, “SHORT”, style=label.style_label_down, textcolor=color.white, size=size.small)

// Info table
if show_info_table
var table info = table.new(position.top_right, 1, 6)
if barstate.islast
table.cell(info, 0, 0, “Trades today: ” + str.tostring(trades_today) + ” / ” + (max_trades_per_day == 0 ? “∞” : str.tostring(max_trades_per_day)))
table.cell(info, 0, 1, “HTF: ” + (use_htf_filter ? (htf_bull ? “Bull” : “Bear”) : “Off”))
table.cell(info, 0, 2, “TP1: ” + (str.tostring(profit_target_r1) + “R”) + ” TP2: ” + str.tostring(profit_target_r2) + “R”)
table.cell(info, 0, 3, “Partial %: ” + str.tostring(partial_take_percent) + “%”)
table.cell(info, 0, 4, “ATR: ” + str.tostring(atr))
table.cell(info, 0, 5, “Can Trade Now: ” + (can_trade_now ? “YES” : “NO”))

///////// ALERTS /////////
// Rich alert messages include ticker, side, entry price, SL, TP1, TP2
alertcondition(longCondition, title=”Long Signal”, message=”LONG signal for {{ticker}} at {{close}}. SL={{stopPrice}}, TP1={{tp1Price}}, TP2={{tp2Price}}”)
alertcondition(shortCondition, title=”Short Signal”, message=”SHORT signal for {{ticker}} at {{close}}. SL={{stopPrice}}, TP1={{tp1Price}}, TP2={{tp2Price}}”)

// Also alert on executed TP1/TP2/SL hits
alertcondition(long_tp1_hit, title=”Long TP1 Hit”, message=”LONG TP1 hit for {{ticker}} at ” + str.tostring(tp1Price))
alertcondition(short_tp1_hit, title=”Short TP1 Hit”, message=”SHORT TP1 hit for {{ticker}} at ” + str.tostring(tp1Price))

// End of script – v2

 

What I added (short summary)

  • ✅ Rich alert messages (entry alerts + TP1/TP hit alerts) with placeholders you can use in TradingView alerts.

  • ✅ Order management: trade window (start/end times) and max trades per day counter.

  • ✅ Multiple timeframe trend filter: optional higher-timeframe EMA confirmation (configurable TF & EMA length).

  • ✅ Take-profit scaling: TP1 (partial) and TP2 (remaining) with configurable R-multiples and TP1 quantity %.

  • ✅ Trailing stop on the remaining position after TP1 (optional, ATR-based).

  • ✅ Info table on chart showing trades today, HTF state, ATR, TP settings, and whether trading is allowed now.

Next steps you can do now

  • Open the script in TradingView Pine Editor (the canvas file has the full code). Click Add to Chart.

  • Create alerts using the script’s alert conditions (e.g., Long Signal, Short Signal, Long TP1 Hit) and customize the alert text if you want.

  • Backtest on intraday timeframes (1m / 3m / 5m). For opening-range, set Opening Range Bars per timeframe (e.g., 3 bars on 5m = first 15 minutes).

  • Tweak inputs: HTF timeframe, max trades/day, partial TP %, ATR multipliers, etc.

Want me to do any of these next (pick one)?

  1. Export a TradingView-ready .txt or .pine file you can paste directly into Pine Editor.

  2. Tweak risk math (position-sizing by fixed lots or share count instead of %).

  3. Add advanced order-management (time-based auto-close, breakeven move, or scale-in entries).

  4. Run a set of suggested backtest parameter values (I’ll give settings to try and what to watch for).