Strategy · Pine Script v5 · On the chart

ORB Twisted M

by g-moe· code credited to goodgains

This strategy builds an opening range during a user-defined morning session and trades breakouts of that range during a later trade window.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code328
Settings10inputs
LicenceNone statedfile: MPL-2.0
Last update5 months ago27 May 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

328 lines of Pine Script v5 from Tradingview/orb-twisted-m-v3.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

orb-twisted-m-v3.pine
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © goodgains


//@version=5
strategy("ORB_twisted_m_v3", overlay = true, default_qty_type = strategy.fixed, default_qty_value = 3, initial_capital = 1000000, calc_on_order_fills = true)

// @keywords: opening-range-breakout, orb-high, orb-low, orb-midpoint, range-extension, profit-target, trailing-stop, long-entry, short-entry, one-trade-per-side, stop-loss, session-filter, opening-range-size, extension-targets, close-at-time, colored-candles, range-breakout, range-breakdown, stepline-levels, intraday-strategy

// inputs
_orb_session        = input.session('0930-0945', title = 'ORB Session (EST)')
_trade_session      = input.session('0945-1400', title = 'Trade Session (EST)') 
_tp_amount1         = input.float(0.50, title = 'Extension 1 of Opening Range', minval = 0.00)    
_tp_amount2         = input.float(1.00, title = 'Extension 2 of Opening Range', minval = 0.00)
_sl_type            = input.string('On Close', title = 'Stop Loss Type', options = ['On Close', 'On Touch'])
_tp3_length         = input.int(3, title = 'Trail Exit Line Length')
_tp3_type           = input.string('On Close', title = 'Trail Exit Type', options = ['On Close', 'On Touch'])
_close_at_time      = input.bool(true, title = 'Close All Trades at 4pm (EST)')
_only_one_side      = input.bool(true, title = 'Only 1 Long & 1 Short Per Day')
_color_candles      = input.bool(false, title = 'Color Candles')

if _tp_amount2 < _tp_amount1
    runtime.error("TP Amount 2 cannot be less than TP Amount 1")


// calculate orb
or_session = time(timeframe.period, str.format('{0}:1234567', _orb_session), 'America/New_York')
var or_high = 0.0
var or_low = 0.0
var or_mid = 0.0
var days_open = 0.0

var float orh_ext1 = 0.00
var float orh_ext2 = 0.00

var float orl_ext1 = 0.00
var float orl_ext2 = 0.00

var float or_size  = 0.00
var float tp1_amount = 0.00
var float tp2_amount = 0.00

if or_session
    if not or_session[1]
        or_low := low
        or_high := high
        days_open := open
        or_size := math.round_to_mintick(or_high - or_low)
        tp1_amount := or_size * _tp_amount1
        tp2_amount := or_size * _tp_amount2
    else 
        or_low := math.min(low, or_low)
        or_high := math.max(high, or_high)
        or_size := math.round_to_mintick(or_high - or_low)
        tp1_amount := or_size * _tp_amount1
        tp2_amount := or_size * _tp_amount2
else if dayofweek != dayofweek[1]
    or_low := na
    or_high := na
    days_open := na
    or_size := na
    tp1_amount := na
    tp2_amount := na







// calculate ma
high_ma_value = ta.sma(high, _tp3_length)
low_ma_value = ta.sma(low, _tp3_length)




// create trade signals / manage trades
var bool time_to_trade  = na
var bool orh_break      = na
var bool orl_break      = na

var bool orh_ext1_break = na
var bool orl_ext1_break = na
var bool orh_ext2_break = na
var bool orl_ext2_break = na

var bool moved_to_breakeven = na
var bool start_trail_stop   = na

var float long_stop         = na
var float short_stop        = na

var bool can_long       = na
var bool can_short      = na


can_long := not _only_one_side ? true : or_session ? true : strategy.position_size > 0 ? false : can_long[1]
can_short := not _only_one_side ? true : or_session ? true : strategy.position_size < 0 ? false : can_short[1]


time_to_trade := time(timeframe.period, str.format('{0}:1234567', _trade_session), 'America/New_York')
orh_break := time_to_trade and can_long and ta.crossover(close, or_high)
orl_break := time_to_trade and can_short and ta.crossunder(close, or_low)
new_position = (strategy.position_size > 0 and strategy.position_size[1] <= 0) or (strategy.position_size < 0 and strategy.position_size[1] >= 0)


orh_ext1 :=  strategy.position_size > 0 ? math.round_to_mintick(strategy.position_avg_price + tp1_amount) : strategy.position_size > 0 ? orh_ext1[1] : na
orh_ext2 :=  strategy.position_size > 0 ? math.round_to_mintick(strategy.position_avg_price + tp2_amount) : strategy.position_size > 0 ? orh_ext2[1] : na

orl_ext1 :=  strategy.position_size < 0 ? math.round_to_mintick(strategy.position_avg_price - tp1_amount) : strategy.position_size < 0 ? orl_ext1[1] : na
orl_ext2 :=  strategy.position_size < 0 ? math.round_to_mintick(strategy.position_avg_price - tp2_amount) : strategy.position_size < 0 ? orl_ext2[1] : na


// plot(orl_ext1, color = color.yellow, style=plot.style_circles)
// barcolor(new_position and strategy.position_size > 0 ? color.yellow : na)
// barcolor(strategy.position_size > 0 ? color.lime : strategy.position_size < 0 ? color.rgb(255, 0, 0) : na)
// plot(orh_ext1, color = color.orange, style= plot.style_line)
// bgcolor(na(tp1_amount) ? color.orange : na)

orh_ext1_break := ta.crossover(high, orh_ext1)
orl_ext1_break := ta.crossunder(low, orl_ext1)
orh_ext2_break := ta.crossover(high, orh_ext2)
orl_ext2_break := ta.crossunder(low, orl_ext2)


moved_to_breakeven := new_position ? false 
 : strategy.position_size > 0 and (high >= orh_ext1 or orh_ext1_break) ? true
 : strategy.position_size < 0 and (low <= orl_ext1 or orl_ext1_break) ? true
 : moved_to_breakeven[1]

start_trail_stop := new_position ? false
 : strategy.position_size > 0 and (high >= orh_ext2 or orh_ext2_break) ? true
 : strategy.position_size < 0 and (low <= orl_ext2 or orl_ext2_break) ? true
 : start_trail_stop[1]

long_stop := not (strategy.position_size > 0) ? na
 : start_trail_stop ? (_tp3_type == 'On Close' ? strategy.position_avg_price : low_ma_value)
 : moved_to_breakeven ? strategy.position_avg_price
 : or_low
short_stop := not (strategy.position_size < 0) ? na
 : start_trail_stop ? (_tp3_type == 'On Close' ? strategy.position_avg_price : high_ma_value)
 : moved_to_breakeven ? strategy.position_avg_price
 : or_high



var bool long_stop_hit = na
var bool short_stop_hit = na
long_stop_hit := new_position ? na
  : strategy.position_size > 0 and _sl_type == 'On Close' and close < long_stop and barstate.isconfirmed ? true
  : false
short_stop_hit := new_position ? na
  : strategy.position_size < 0 and _sl_type == 'On Close' and close > short_stop and barstate.isconfirmed ? true
  : false


var bool long_trail_hit = na
var bool short_trail_hit = na
long_trail_hit := new_position ? na
  : strategy.position_size > 0 and start_trail_stop and _tp3_type == 'On Close'and close < low_ma_value and barstate.isconfirmed ? true
  : false
short_trail_hit := new_position ? na
  : strategy.position_size < 0 and start_trail_stop and _tp3_type == 'On Close' and close > high_ma_value and barstate.isconfirmed ? true
  : false



// send orders
if orh_break
    strategy.entry("LE", strategy.long, comment = 'LE')
if orl_break
    strategy.entry("SS_E", strategy.short, comment = 'SS_E')

if strategy.position_size > 0
    strategy.exit('L_TP1', 'LE', qty = strategy.position_size / 3, limit = orh_ext1, stop =  _sl_type == 'On Touch' ? long_stop : na, comment_profit = 'L_TP1', comment_loss = 'L_SL1')
    strategy.exit('L_TP2', 'LE', qty = strategy.position_size / 2, limit = orh_ext2, stop = _sl_type == 'On Touch' ? long_stop : na, comment_profit = 'L_TP2', comment_loss = 'L_SL2')
    strategy.exit('L_TP3', 'LE', qty = strategy.position_size, limit = na, stop = _sl_type == 'On Touch' ? long_stop : na, comment_profit = 'L_TP3', comment_loss = 'L_SL3')
else if strategy.position_size < 0
    strategy.exit('SS_TP1', 'SS_E', qty = strategy.position_size / 3, limit = orl_ext1, stop = _sl_type == 'On Touch' ? short_stop : na, comment_profit = 'SS_TP1', comment_loss = 'SS_SL1')
    strategy.exit('SS_TP2', 'SS_E', qty = strategy.position_size / 2, limit = orl_ext2, stop = _sl_type == 'On Touch' ? short_stop : na, comment_profit = 'SS_TP2', comment_loss = 'SS_SL2')
    strategy.exit('SS_TP3', 'SS_E', qty = strategy.position_size , limit = na, stop = _sl_type == 'On Touch' ? short_stop : na, comment_profit = 'SS_TP3', comment_loss = 'SS_SL3')

if long_trail_hit
    strategy.close('LE', 'L_TS', immediately = true)
if short_trail_hit
    strategy.close('SS_E', 'SS_TS', immediately = true)

if long_stop_hit
    strategy.close('LE', 'L_SL', immediately = true)
if short_stop_hit
    strategy.close('SS_E', 'SS_SL', immediately = true)


// visualize trade
entry_plot = plot(strategy.position_avg_price, title = 'Entry', color = color.blue, style = plot.style_circles)
lstop_plot = plot(long_stop, title = 'Long Stop', color = color.fuchsia, style = plot.style_circles)
ssstop_plot = plot(short_stop, title = 'Short Stop', color = color.fuchsia, style = plot.style_circles)



// visualize orb
or_high_plot = plot(not or_session ? or_high : na, title='ORH', 
 color=color.new(color.white, 70), linewidth=2, style=plot.style_linebr, offset = 0)
or_low_plot = plot(not or_session ? or_low : na, title='ORL', 
 color=color.new(color.white, 70), linewidth=2, style=plot.style_linebr, offset = 0)
fill(or_high_plot, or_low_plot, title='OR Fill', color=color.new(color.silver, 95))

orh_ext1_plot = plot(strategy.position_size > 0 ? orh_ext1 : na, title='ORH TP 1', 
 color=color.new(color.maroon, 0) , linewidth=1, style=plot.style_circles, offset = 0)
orh_ext2_plot = plot(strategy.position_size > 0 ? orh_ext2 : na, title='ORH TP 2', 
 color=color.new(color.maroon, 0), linewidth=1, style=plot.style_circles, offset = 0)

orl_ext1_plot = plot(strategy.position_size < 0 ? orl_ext1 : na, title='ORL TP 1', 
 color=color.new(color.green, 0), linewidth=1, style=plot.style_circles, offset = 0)
orl_ext2_plot = plot(strategy.position_size < 0 ? orl_ext2 : na, title='ORL TP 2', 
 color=color.new(color.green, 0), linewidth=1, style=plot.style_circles, offset = 0)

plot(low_ma_value, title = 'Low MA', color = strategy.position_size > 0 and start_trail_stop ? color.new(color.fuchsia, 0) : color.new(color.red, 50), style = plot.style_steplinebr)
plot(high_ma_value, title = 'High MA', color = strategy.position_size < 0 and start_trail_stop ? color.new(color.fuchsia, 0) : color.new(color.green, 50), style = plot.style_steplinebr)




orb_color = not _color_candles ? na 
 : not or_session and na(or_high) ? color.gray
 : or_session ? color.white
 : close > or_high ? color.lime
 : close < or_low ? color.red 
 : color.yellow
barcolor(orb_color)



// display risk
var float long_tp1_dollar = 0.00
var float long_tp2_dollar = 0.00
var float long_sl_dollar = 0.00

long_tp1_dollar := not (strategy.position_size > 0) ? na 
 : new_position ? (orh_ext1 - strategy.position_avg_price) * syminfo.pointvalue * math.floor(strategy.position_size / 3)
 : long_tp1_dollar[1]

long_tp2_dollar := not (strategy.position_size > 0) ? na 
 : new_position ? (orh_ext2 - strategy.position_avg_price) * syminfo.pointvalue * math.floor(strategy.position_size / 3)
 : long_tp2_dollar[1]

long_sl_dollar := not (strategy.position_size > 0) ? na 
 : (long_stop - strategy.position_avg_price) * syminfo.pointvalue * strategy.position_size


var float short_tp1_dollar = 0.00
var float short_tp2_dollar = 0.00
var float short_sl_dollar = 0.00

short_tp1_dollar := not (strategy.position_size < 0) ? na 
 : new_position ? (orl_ext1 - strategy.position_avg_price) * syminfo.pointvalue * math.floor(strategy.position_size / 3)
 : short_tp1_dollar[1]

short_tp2_dollar := not (strategy.position_size < 0) ? na 
 : new_position ? (orl_ext2 - strategy.position_avg_price) * syminfo.pointvalue * math.floor(strategy.position_size / 3)
 : short_tp2_dollar[1]

short_sl_dollar := not (strategy.position_size < 0) ? na 
 : (short_stop - strategy.position_avg_price) * syminfo.pointvalue * strategy.position_size


var label long_tp1_label = na
var label long_tp2_label = na
var label long_sl_label = na

var label short_tp1_label = na
var label short_tp2_label = na
var label short_sl_label = na

if strategy.position_size > 0
    if new_position
        long_tp1_label := label.new(bar_index + 1, orh_ext1, text = "$"+str.tostring(long_tp1_dollar, format.mintick), color = color.rgb(43, 94, 45),
         style = label.style_label_left, textcolor = color.white)
        long_tp2_label := label.new(bar_index + 1, orh_ext2, text = "$"+str.tostring(long_tp2_dollar, format.mintick), color = color.rgb(43, 94, 45),
         style = label.style_label_left, textcolor = color.white)
        long_sl_label := label.new(bar_index + 1, long_stop, text = "$"+str.tostring(long_sl_dollar, format.mintick), color = color.rgb(172, 33, 33),
         style = label.style_label_left, textcolor = color.white)
    else
        label.set_x(long_tp1_label, bar_index+1)
        label.set_x(long_tp2_label, bar_index+1)
        label.set_xy(long_sl_label, bar_index+1, long_stop)
        label.set_text(long_sl_label, "$"+str.tostring(long_sl_dollar, format.mintick))
        label.set_color(long_sl_label, long_sl_dollar > 0 ? color.rgb(109, 170, 111) : color.rgb(172, 33, 33))

if strategy.position_size < 0
    if new_position
        short_tp1_label := label.new(bar_index + 1, orl_ext1, text = "$"+str.tostring(short_tp1_dollar, format.mintick), color = color.rgb(43, 94, 45),
         style = label.style_label_left, textcolor = color.white)
        short_tp2_label := label.new(bar_index + 1, orl_ext2, text = "$"+str.tostring(short_tp2_dollar, format.mintick), color = color.rgb(43, 94, 45),
         style = label.style_label_left, textcolor = color.white)
        short_sl_label := label.new(bar_index + 1, short_stop, text = "$"+str.tostring(short_sl_dollar, format.mintick), color = color.rgb(172, 33, 33),
         style = label.style_label_left, textcolor = color.white)
    else
        label.set_x(short_tp1_label, bar_index+1)
        label.set_x(short_tp2_label, bar_index+1)
        label.set_xy(short_sl_label, bar_index+1, short_stop)
        label.set_text(short_sl_label, "$"+str.tostring(short_sl_dollar, format.mintick))
        label.set_color(short_sl_label, short_sl_dollar > 0 ? color.rgb(109, 170, 111) : color.rgb(172, 33, 33))


if _close_at_time and time == timestamp("America/New_York", year, month, dayofmonth, 16, 0)       
    strategy.close_all('TX', immediately = true)


open_risk = strategy.position_size > 0 ? long_sl_dollar
 : strategy.position_size < 0 ? short_sl_dollar
 : na 
open_reward = strategy.position_size > 0 ? (moved_to_breakeven ? 0 : long_tp1_dollar) + (start_trail_stop ? 0 : long_tp2_dollar) + (start_trail_stop ? strategy.openprofit : long_tp2_dollar) 
 : strategy.position_size < 0 ? (moved_to_breakeven ? 0 : short_tp1_dollar) + (start_trail_stop ? 0 : short_tp2_dollar) + (start_trail_stop ? strategy.openprofit : short_tp2_dollar) 
 : na 



var t = table.new(position = position.bottom_right, columns = 1, rows = 4, bgcolor = color.black, border_width = 1)
if barstate.islast
    table.clear(t,0,0,0,3)

    if strategy.position_size != 0
        table.cell(t,0,0, text = 'Entry ' + str.tostring(strategy.position_size) + ' @ ' + str.tostring(strategy.position_avg_price), bgcolor = color.rgb(30, 91, 141), text_color = color.white, text_halign = text.align_left)
        table.cell(t,0,1, text = 'Open$ ' + str.tostring(strategy.openprofit, format.mintick), bgcolor = strategy.openprofit > 0 ? color.rgb(43, 94, 45)  : color.rgb(172, 33, 33), text_color = color.white, text_halign = text.align_left)
        table.cell(t,0,2, text = 'Reward$  ' + str.tostring(open_reward, format.mintick), bgcolor = open_reward > 0 ? color.rgb(43, 94, 45)  : color.rgb(172, 33, 33), text_color = color.white, text_halign = text.align_left) 
        table.cell(t,0,3, text = 'Risk$  ' + str.tostring(open_risk, format.mintick), bgcolor = open_risk > 0 ? color.rgb(109, 170, 111)  : color.rgb(172, 33, 33), text_color = color.white, text_halign = text.align_left)

Overview

ORB Twisted M enters long above the range high and short below the range low, then manages exits with two range-size extensions, a stop that can trigger on close or on touch, and a trailing line based on a short simple moving average of highs and lows. Settings control session times, extension distances, trail length, a 4pm flat option, one trade per side, and optional candle colors. It draws levels on the price chart.

Details

Published by

g-moe on GitHub

Code credit

goodgains, as written in the script's header

Draws

On the price chart

Markets

Stocks, Indices

Timeframes

M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
ORB Session (EST)session0930-0945_orb_session
Trade Session (EST)session0945-1400_trade_session
Extension 1 of Opening Rangefloat0.50_tp_amount1
Extension 2 of Opening Rangefloat1.00_tp_amount2
Stop Loss TypestringOn Close_sl_type
Trail Exit Line Lengthint3_tp3_length
Trail Exit TypestringOn Close_tp3_type
Close All Trades at 4pm (EST)booltrue_close_at_time
Only 1 Long & 1 Short Per Daybooltrue_only_one_side
Color Candlesboolfalse_color_candles
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

106 stars

This script monitors opening gap conditions and breakout behavior relative to the first candle's range across up to twenty configurable stock tickers. It detects whether following bars remain inside the opening range before breaking out, displaying the status

Strategy v4 Screeners & dashboardsBreakout Repaints
Updated 2 years ago · GPL-3.0 GitHub repository of 1St Bar GAP+BkOut Screener v2 by RM
7 stars

This overlay strategy tracks the high and low of a user-defined London session and plots the previous session levels as support and resistance. It flags a break beyond a level when price closes past an ATR buffer, then waits a set number of bars for a retest w

Strategy v5 Sessions & timeSupport & resistance
Updated 3 months ago · None stated GitHub repository of London SR Cleaner WR (TP 0.20)
6 stars

This strategy combines Opening Range Breakout (ORB) mechanics with Inner Circle Trader (ICT) concepts like Fair Value Gaps, Order Blocks, and liquidity grabs. It identifies session opening ranges and generates signals when price breaks out with supporting rela

Strategy v5 BreakoutSMC / ICT / price action
Updated 7 months ago · None stated GitHub repository of Advanced ORB + ICT Strategy

algo-trade-indian

by akash-yellgetti
1 stars

A strategy-type script for the price chart that marks the high, low and midpoint of the first part of each session, set by start hour and minute inputs, and alerts when price crosses above the high or below the low. It also plots VWAP and a 50-period EMA, pivo

Strategy v5 Sessions & timeSupport & resistance
Updated 2 years ago · None stated GitHub repository of algo-trade-indian
1 stars

A strategy built around the first regular-session candle of the US day in New York time, together with rejection levels collected from wicks formed during pre-market and after-hours sessions. Rejection levels within a tolerance percentage are grouped. Options

Strategy v5 BreakoutSessions & time
Updated 11 months ago · Custom licence GitHub repository of Breakout Strategy - Step by Step

Dollar Cross Play

by majohnst
1 stars

The Dollar Cross Play strategy detects price breakouts above a user-defined dollar threshold. It qualifies long entries by verifying that the previous day's close was at or below a maximum ceiling, aiming to capture fresh crosses rather than overextended moves

Strategy v6 BreakoutSupport & resistance
Updated 4 months ago · None stated GitHub repository of Dollar Cross Play

More Breakout scripts

Related on ForexR

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers