Long-Only Opening Range Breakout (ORB) with Pivot Points
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © duronic12

//@version=5
strategy(title='Long-Only Opening Range Breakout (ORB) with Pivot Points', overlay=true, default_qty_value=100, initial_capital=10000, default_qty_type=strategy.percent_of_equity, pyramiding=0, process_orders_on_close=true)

// Time Sessions
sess = input.session('0930-0945', title='Opening Session') + ':1234567'

t = time(timeframe.period, sess)
time_cond = na(t) ? 0 : 1

h = 0.0
l = 0.0
h := time_cond and not time_cond[1] ? high : time_cond and high > h[1] ? high : h[1]

// Pivots
is_newbar(res) =>
    t = time(res)
    not na(t) and (na(t[1]) or t > t[1])

prevCloseHTF = request.security(syminfo.tickerid, 'D', close[1], lookahead=barmerge.lookahead_on)
prevOpenHTF = request.security(syminfo.tickerid, 'D', open[1], lookahead=barmerge.lookahead_on)
prevHighHTF = request.security(syminfo.tickerid, 'D', high[1], lookahead=barmerge.lookahead_on)
prevLowHTF = request.security(syminfo.tickerid, 'D', low[1], lookahead=barmerge.lookahead_on)

pivot = (prevHighHTF + prevLowHTF + prevCloseHTF) / 3
range_1 = prevHighHTF - prevLowHTF

// Pivot Points Calculations
r1 = pivot + pivot - prevLowHTF
r2 = pivot + 1 * range_1
r3 = pivot * 2 + prevHighHTF - 2 * prevLowHTF
r4 = pivot * 3 + prevHighHTF - 3 * prevLowHTF
r5 = pivot * 4 + prevHighHTF - 4 * prevLowHTF
r0_5 = h + math.abs(r1 - h) / 2
r1_5 = r1 + math.abs(r1 - r2) / 2
r2_5 = r2 + math.abs(r2 - r3) / 2
r3_5 = r3 + math.abs(r3 - r4) / 2
r4_5 = r4 + math.abs(r4 - r5) / 2

newday = is_newbar('D')

plot(newday ? na : r1, style=plot.style_linebr, title='R1')
plot(newday ? na : r2, style=plot.style_linebr, title='R2')
plot(newday ? na : r3, style=plot.style_linebr, title='R3')
plot(newday ? na : r4, style=plot.style_linebr, title='R4')
plot(newday ? na : r5, style=plot.style_linebr, title='R5')
plot(newday ? na : r0_5, style=plot.style_linebr, color=color.new(color.gray, 0), title='R0.5')
plot(newday ? na : r1_5, style=plot.style_linebr, color=color.new(color.gray, 0), title='R1.5')
plot(newday ? na : r2_5, style=plot.style_linebr, color=color.new(color.gray, 0), title='R2.5')
plot(newday ? na : r3_5, style=plot.style_linebr, color=color.new(color.gray, 0), title='R3.5')
plot(newday ? na : r4_5, style=plot.style_linebr, color=color.new(color.gray, 0), title='R4.5')

// Opening Range
plot(not time_cond ? h : na, style=plot.style_linebr, color=color.new(color.green, 0), linewidth=2)

// Entry Conditions
long = open < h and high > h and r1 > h

max_trades = input(1, title='Max Trades per Day')
trades_counter = 0

// Position Management Tools
pos = 0.0
pos := long and (pos[1] != 1 or na(pos[1])) and trades_counter[1] < max_trades ? 1 : pos[1]

longCond = long and (pos[1] != 1 or na(pos[1])) and trades_counter[1] < max_trades

trades_counter := time_cond ? 0 : longCond ? trades_counter[1] + 1 : trades_counter[1]

// Stop Loss
initial_sl_sw = input.string('Percentage', title='Initial SL Type:', options=['Percentage', 'Previous Low'])
i_sl = input.float(3.0, title='Stop Loss %', minval=0)
sl = i_sl > 0 ? i_sl / 100 : 99999

long_entry = ta.valuewhen(longCond, close, 0)
ll = ta.valuewhen(longCond, low[1], 0)
sl_long0 = initial_sl_sw == 'Percentage' ? long_entry * (1 - sl) : ll

trail_long = 0.0
trail_long := longCond ? 0 : high > r5 and r4 > trail_long[1] ? r4 : high > r4_5 and r3_5 > trail_long[1] ? r3_5 : high > r4 and r3 > trail_long[1] ? r3 : high > r3_5 and r2_5 > trail_long[1] ? r2_5 : high > r3 and r2 > trail_long[1] ? r2 : high > r2_5 and r1_5 > trail_long[1] ? r1_5 : high > r2 and r1 > trail_long[1] ? r1 : high > r1_5 and r0_5 > trail_long[1] ? r0_5 : high > r0_5 and h > trail_long[1] ? h : trail_long[1]

sl_long = pos == 0 ? 0 : math.max(sl_long0, trail_long)

plot(sl_long > 0 and pos == 1 and not newday ? sl_long : na, style=plot.style_linebr, color=color.new(#FF0000, 0))

// Position Adjustment
long_sl = low < sl_long[1] and pos[1] == 1

if long_sl or newday
    pos := 0
    pos

// Backtester
i_startTime = input.time(defval=timestamp('01 Sep 2000 13:30 +0000'), title='Backtesting Start Time')
i_endTime = input.time(defval=timestamp('30 Sep 2099 19:30 +0000'), title='Backtesting End Time')
timeCond = time > i_startTime and time < i_endTime

// Entries and Exits
strategy.entry('long', strategy.long, when=open < h and trades_counter[1] < max_trades and timeCond, alert_message='BUY ALERT', stop=h)
strategy.cancel('long', when=longCond[1])
strategy.exit('SL/TP', from_entry='long', stop=sl_long, alert_message='SELL ALERT')
strategy.close_all(when=newday, comment='DayEnd', alert_message='EndofDay SELL ALERT')

