RP Profits' 8AM ORB strategy, implemented in PineScript The article describes an 8AM Opening Range Breakout (ORB) trading strategy implemented in PineScript for TradingView. The strategy defines a key price range from 8:00 to 8:15, determines a bullish or bearish daily bias, and enters trades via limit orders or break-of-structure (BOS) confirmation, with options to filter trades by time window and invalidate days with excessively large ranges or conflicting price action. - - Save deltatrend/ec550d13ea6246f25e41023e77426247 to your computer and use it in GitHub Desktop. Learn more about bidirectional Unicode characters https://github.co/hiddenchars | //@version=6 | | | // © QuantPad LLC made with https://quantpad.ai/ | | | strategy "'RP Profits' 8AM ORB", | | | overlay = true, | | | dynamic requests = true, | | | initial capital = 50000, | | | default qty type = strategy.fixed, | | | default qty value = 2, | | | commission type = strategy.commission.cash per contract, | | | commission value = 1.40, | | | margin long = 0, | | | margin short = 0, | | | use bar magnifier = true | | | // ───────────────────────────────────────────────────────────────────────────── | | | // INPUTS | | | // ───────────────────────────────────────────────────────────────────────────── | | | group vis = "Visuals" | | | show asia = input.bool true, "Show Asia Session", group=group vis, tooltip="Show/hide Asia session high and low levels." | | | show london = input.bool true, "Show London Session", group=group vis, tooltip="Show/hide London session high and low levels." | | | show bg = input.bool true, "Show Background Color", group=group vis, tooltip="Tint the background green bullish or red bearish when a trade direction has been determined." | | | show bos lines = input.bool true, "Show BOS Lines", group=group vis, tooltip="When enabled, draws the structural level broken by any 1-minute BOS that triggered a trade entry. Only trade-triggering BOS events are shown." | | | group entry = "Entry Mode" | | | entry mode = input.string "Limit Order", "Entry Mode", group=group entry, | | | options= "Limit Order", "BOS Confirmation" , | | | tooltip="Limit Order: place a limit at the 8AM range midpoint immediately after direction is established original behavior .\n\nBOS Confirmation: wait for price to tap the midpoint in the direction of the trade wick touch is sufficient , then enter on the close of the first confirmed 1-minute Break of Structure in that direction.\n\nIf price advances fully through the opposing zone boundary past zone high on a bearish day, past zone low on a bullish day , the tap setup is permanently invalidated for the rest of the day.\n\nOnly one trade per day is permitted in either mode; the day resets at 18:00." | | | group sessions = "Session Times" | | | asia time = input.session "1800-0300", "Asia Session", group=group sessions, inline="asia" | | | london time = input.session "0330-1130", "London Session", group=group sessions, inline="london" | | | group filter = "Trade Window Filter" | | | use trade window = input.bool true, "Restrict Trade Window", group=group filter, inline="trade window", tooltip="When enabled, trade direction is only active inside the specified time window. The limit order is cancelled if the window closes before entry." | | | trade window time = input.session "0900-1100", "", group=group filter, inline="trade window" | | | group bias = "Daily Bias Filter" | | | require clean bias = input.bool false, "Require Clean Daily Bias", group=group bias, | | | tooltip="When enabled, a daily bias is only allowed if price has stayed on ONE side of the 8:00–8:15 range between 8:15 and the moment bias would be set.\n\nBullish bias requires price did NOT trade below the 8:00–8:15 low.\nBearish bias requires price did NOT trade above the 8:00–8:15 high.\n\nIf violated, bias is rejected for the entire day and no trades are taken. Bias checks stop after a trade is entered." | | | invalidate large range = input.bool true, "Invalidate Large 8:00 Range 20pts ", group=group bias, | | | tooltip="When enabled, days where the 8:00–8:15 range width exceeds 20 points are trade-disabled for the day.\nThe range box and bias visuals still plot, but no trades will be taken, and the range box will display 'Range Too Large'." | | | group risk = "Risk Parameters" | | | sl scan low = input.float 5.0, "SL Scan Range Low", group=group risk, minval=0.0, inline="sl scan", tooltip="Minimum distance pts from the entry price a session level must be to qualify as a stop-loss anchor. In Limit Order mode the entry price is the zone midpoint; in BOS Confirmation mode it is the BOS bar close." | | | sl scan high = input.float 10.0, "— High pts ", group=group risk, minval=0.0, inline="sl scan", tooltip="Maximum distance pts from the entry price a session level must be to qualify as a stop-loss anchor." | | | sl default = input.float 8.0, "Default SL pts ", group=group risk, minval=0.1, tooltip="Fallback stop-loss distance in points when no qualifying session level is found within the scan range." | | | rr multiple = input.float 4.0, "RR Multiple", group=group risk, minval=0.1, tooltip="Risk-reward multiple applied to the stop-loss distance to set the take-profit target e.g. 4 = 4× the SL distance ." | | | sl manage mode = input.string "Don't Move", "SL Management", group=group risk, | | | options= "Don't Move", "Move to BE", "Trail" , | | | tooltip="Don't Move: stoploss stays fixed at its initial level.\nMove to BE: stoploss moves to entry price once price has moved sufficiently into profit entry 1m bar ignored .\nTrail: stoploss trails price by the same distance as the initial stop, updating every 1m bar entry 1m bar is ignored . Uses strategy.exit trailing parameters." | | | // ───────────────────────────────────────────────────────────────────────────── | | | // TYPES | | | // ───────────────────────────────────────────────────────────────────────────── | | | type Session | | | string name | | | string time window | | | color line color | | | float high = na | | | float low = na | | | int high time = na | | | int low time = na | | | int session start time = na | | | bool high valid = true | | | bool low valid = true | | | int high invalid time = na | | | int low invalid time = na | | | line high line = na | | | line low line = na | | | label high label = na | | | label low label = na | | | type DailyState | | | float zone high = na | | | float zone low = na | | | float zone mid = na | | | int zone start time = na | | | box zone box = na | | | line zone mid line = na | | | string trade dir = na | | | int dir determined time = na | | | // Large range invalidation | | | bool range too large = false | | | bool trade banned = false | | | // Clean-bias tracking 8:15 → bias set | | | bool bias locked out = false | | | bool touched below since 815 = false | | | bool touched above since 815 = false | | | // trade taken: set true the moment ANY trade is entered regardless of mode. | | | // Prevents a second entry within the same day. Resets at 18:00. | | | bool trade taken = false | | | // Trade state | | | bool limit pending = false | | | float limit price = na | | | bool trade active = false | | | bool pos opened = false | | | int entry time = na | | | int entry ib time = na | | | float entry price = na | | | float sl price = na | | | float tp price = na | | | int exit time = na | | | box sl box = na | | | box tp box = na | | | string sl label text = na | | | label sl label = na | | | string tp label text = na | | | label tp label = na | | | // Freeze direction at fill so management/visuals don't depend on trade dir persistence | | | string entry dir = na | | | // Store initial risk geometry so BE logic is stable even after SL moves | | | float init sl price = na | | | float init tp price = na | | | float init sl dist = na | | | float init tp dist = na | | | // SL management state | | | string sl mode = na | | | bool be triggered = false | | | int be time = na | | | label be label = na | | | // Trail | | | float trail dist = na | | | int trail offset ticks = na | | | float trail best = na | | | float trail sl price = na | | | label trail label = na | | | // ── BOS Confirmation entry mode ─────────────────────────────────────────── | | | // tap state: 0 = unarmed, +1 = bullish tap armed, -1 = bearish tap armed | | | // tap invalidated: permanently true for the rest of the day once price advances | | | // fully through the opposing zone boundary past zone high on a | | | // bearish day; past zone low on a bullish day . Blocks any | | | // further tap arming even after a reset. Cleared at 18:00. | | | int tap state = 0 | | | int tap time = na | | | bool awaiting bos = false | | | bool tap invalidated = false | | | // ───────────────────────────────────────────────────────────────────────────── | | | // 1-MINUTE BREAK OF STRUCTURE DETECTOR | | | // Ported verbatim from TJR BOS module. Do NOT modify BOS core logic. | | | // Called via request.security on the "1" timeframe; fires on confirmed 1m bars. | | | // ───────────────────────────────────────────────────────────────────────────── | | | BOS core = | | | var int BOS bosTimesBull = array.new int | | | var int BOS bosTimesBear = array.new int | | | bool BOS isBosBull = false | | | bool BOS isBosBear = false | | | int BOS left ts = na | | | float BOS level = na | | | int BOS dir = 0 | | | if close open and barstate.isconfirmed | | | BOS isBosBull := true | | | int i = 1 | | | while BOS isBosBull and i <= bar index and i <= 1000 and close i = open i | | | if high i close or array.includes BOS bosTimesBull, time i | | | BOS isBosBull := false | | | i += 1 | | | float BOS high to beat = na | | | int BOS high time = na | | | while BOS isBosBull and i <= bar index and i <= 1000 and close i <= open i | | | if na BOS high to beat or high i BOS high to beat | | | BOS high to beat := high i | | | BOS high time := time i | | | i += 1 | | | if BOS isBosBull and i <= bar index and i <= 1000 and high i BOS high to beat | | | BOS high to beat := high i | | | BOS high time := time i | | | if BOS isBosBull and close <= nz BOS high to beat, close | | | BOS isBosBull := false | | | if BOS isBosBull | | | BOS level := BOS high to beat | | | BOS left ts := BOS high time | | | BOS dir := 1 | | | array.push BOS bosTimesBull, time | | | if array.size BOS bosTimesBull 15 | | | if array.size BOS bosTimesBull 0 | | | array.shift BOS bosTimesBull | | | if close < open and barstate.isconfirmed and BOS dir == 0 | | | BOS isBosBear := true | | | int i2 = 1 | | | while BOS isBosBear and i2 <= bar index and i2 <= 1000 and close i2 <= open i2 | | | if low i2 < close or array.includes BOS bosTimesBear, time i2 | | | BOS isBosBear := false | | | i2 += 1 | | | float BOS low to beat = na | | | int BOS low time = na | | | while BOS isBosBear and i2 <= bar index and i2 <= 1000 and close i2 = open i2 | | | if na BOS low to beat or low i2 < BOS low to beat | | | BOS low to beat := low i2 | | | BOS low time := time i2 | | | i2 += 1 | | | if BOS isBosBear and i2 <= bar index and i2 <= 1000 and low i2 < BOS low to beat | | | BOS low to beat := low i2 | | | BOS low time := time i2 | | | if BOS isBosBear and close = nz BOS low to beat, close | | | BOS isBosBear := false | | | if BOS isBosBear | | | BOS level := BOS low to beat | | | BOS left ts := BOS low time | | | BOS dir := -1 | | | array.push BOS bosTimesBear, time | | | if array.size BOS bosTimesBear 15 | | | if array.size BOS bosTimesBear 0 | | | array.shift BOS bosTimesBear | | | bool BOS is new = BOS dir = 0 | | | BOS is new, BOS left ts, time, BOS level, BOS dir | | | // ───────────────────────────────────────────────────────────────────────────── | | | // INTRABAR 1-MINUTE DATA | | | // ───────────────────────────────────────────────────────────────────────────── | | | ib times = request.security lower tf syminfo.tickerid, "1", time | | | ib opens = request.security lower tf syminfo.tickerid, "1", open | | | ib closes = request.security lower tf syminfo.tickerid, "1", close | | | ib highs = request.security lower tf syminfo.tickerid, "1", high | | | ib lows = request.security lower tf syminfo.tickerid, "1", low | | | ib in asia = request.security lower tf syminfo.tickerid, "1", not na time timeframe.period, asia time, "America/New York" | | | ib in london = request.security lower tf syminfo.tickerid, "1", not na time timeframe.period, london time, "America/New York" | | | ib in trade window = request.security lower tf syminfo.tickerid, "1", not na time timeframe.period, trade window time, "America/New York" | | | // ───────────────────────────────────────────────────────────────────────────── | | | // 15-MINUTE DATA FOR KEY ZONE | | | // ───────────────────────────────────────────────────────────────────────────── | | | m15 high val, m15 low val, m15 time val = request.security syminfo.tickerid, "15", high, low, time , barmerge.gaps off, barmerge.lookahead off | | | // 1-minute ATR — one value per chart bar; used for direction thresholds. | | | m1 atr = request.security syminfo.tickerid, "1", ta.atr 14 , barmerge.gaps off, barmerge.lookahead off | | | // ───────────────────────────────────────────────────────────────────────────── | | | // 1-MINUTE BOS SIGNALS chart-bar scope, confirmed on 1m bar close | | | // bos fire event is true only on the FIRST chart bar of each new 1m bar that | | | // produced a BOS, matching the gating pattern from the TJR module. | | | // ───────────────────────────────────────────────────────────────────────────── | | | bos htf time = request.security syminfo.tickerid, "1", time, barmerge.gaps off, barmerge.lookahead off | | | bos ev new, bos ev left ts, bos ev right ts, bos ev level, bos ev dir = request.security syminfo.tickerid, "1", BOS core , barmerge.gaps off, barmerge.lookahead off | | | bos tf newbar = ta.change bos htf time = 0 | | | bos fire event = bos ev new and bos tf newbar | | | // ───────────────────────────────────────────────────────────────────────────── | | | // SESSION INSTANCES & ARRAYS | | | // ───────────────────────────────────────────────────────────────────────────── | | | var Session asia = Session.new name="Asia", time window=asia time, line color=color.yellow | | | var Session london = Session.new name="London", time window=london time, line color=color.new color.teal, 0 | | | var array