Inside Bar Breakout For ThinkOrSwim

Kojak

New member
Alright guys this is a strategy that I'm sharing based on The Strat and trading inside bars on the 30 min time frame. In the short amount of backtesting that I've done it seems to work out very well. I have a profit loss backtester added to the script to give quick results after any changes are made....I welcome any and all help as I think this strategy has great possibilities!! I use it on the 30min time frame cause based on the backtester it gives the best accuracy. Simple rules are no trades til the first 30 min candle closes and long or short after a break of an inside bar's high or low. So far the results are good.. Let me know what you guys think?

http://tos.mx/dazwE0M
 
Here is the code from the above link:
Ruby:
#
# TD Ameritrade IP Company, Inc. (c) 2007-2022
#
def open_time = 0930;
def closing_time = 1600;

def price = close;

def inside = high < high[1] and low > low[1];
def outside = high > high[1] and low < low[1];
AssignPriceColor(if inside
                then Color.BLUE
                else Color.CURRENT);
AssignPriceColor(if outside
                then Color.white
                else Color.CURRENT);
def double_inside = high[1] < high[2] && Low[1] > Low[2] && high[2] < high[3] && Low[2] >Low[3];


#OUTS_-----------------------

def nan2 = Double.NaN;
def isRollover = GetYYYYMMDD() != GetYYYYMMDD()[1];
def beforeStart = GetTime() < RegularTradingStart(GetYYYYMMDD());
def afterEnd = GetTime() > RegularTradingEnd(GetYYYYMMDD());
def firstBarOfDay = if (beforeStart[1] == 1 and beforeStart == 0) or (isRollover and beforeStart == 0) then 1 else 0;
def lastBarOfDay = if
    (afterEnd[-2] == 1 and afterEnd == 0) or
    (isRollover[-2] and firstBarOfDay[-2])
    then 1
    else 0;

plot data = close;
data.Hide();

def breakout = high[1] < high[2] && Low[1] > Low[2] && high crosses above high[1] ;
def outsidebreakout = high[1] > high[2] && Low[1] < Low[2] && high crosses above high[1] ;
def Breakdown = high[1] < high[2] && Low[1] > Low[2] && Low crosses below Low[1];
def outsidereakdown = high[1] > high[2] && Low[1] < Low[2] && Low crosses below Low[1] ;
def BullBreak = double_inside && High crosses above high[3];
def BearBreak = double_inside && Low crosses below Low[3];

AddOrder(OrderType.BUY_TO_OPEN, Breakout[-1] && SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800,name = "Long Entry", tickcolor = GetColor(8), arrowcolor = GetColor(8));
AddOrder(OrderType.BUY_TO_OPEN,BullBreak[-1] && SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800,name = "Long Entry", tickcolor = GetColor(8), arrowcolor = GetColor(8));
AddOrder(OrderType.BUY_TO_OPEN, outsidebreakout[-1] && SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800,name = "Long Entry", tickcolor = GetColor(8), arrowcolor = GetColor(8));
#AddOrder(OrderType.BUY_TO_OPEN, outside and close crosses above open, tickcolor = GetColor(8), arrowcolor = GetColor(8));

#addOrder(OrderType.BUY_TO_OPEN, close crosses above close[1] and high[1] < high[2] and low[1] > low[2] and close[2] > close[3],  tickColor = GetColor(9), arrowColor = GetColor(9));
AddOrder(OrderType.SELL_TO_CLOSE, High crosses above high[3] or Low crosses below Low[2] , name = "Sell", tickcolor = GetColor(9), arrowcolor = GetColor(9));
AddOrder(OrderType.SELL_TO_CLOSE, lastBarOfDay, tickcolor = Color.PLUM, arrowcolor = Color.PLUM, name = "EOD");




AddOrder(OrderType.SELL_TO_OPEN,  Breakdown[-1] && SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800, name = "Short", tickcolor = GetColor(9), arrowcolor = GetColor(9));
AddOrder(OrderType.SELL_TO_OPEN,  BearBreak[-1]&& SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800, name = "Short", tickcolor = GetColor(9), arrowcolor = GetColor(9));
AddOrder(OrderType.SELL_TO_OPEN,  outsidereakdown[-1] && SecondsFromTime(open_time) > 900 && SecondsTillTime(closing_time) > 1800, name = "Short", tickcolor = GetColor(9), arrowcolor = GetColor(9));
#AddOrder(OrderType.SELL_TO_OPEN, outside and close crosses below  open, tickcolor = GetColor(9), arrowcolor = GetColor(9));

#addOrder(OrderType.SELL_TO_OPEN, close crosses below close[1] and high[1] < high[2] and close[2] < close[3],    tickColor = GetColor(9), arrowColor = GetColor(9));
AddOrder(OrderType.BUY_TO_CLOSE, Low < Low[3] or high crosses above high[2], name = "Cover", tickcolor = GetColor(9), arrowcolor = GetColor(9));
AddOrder(OrderType.BUY_TO_CLOSE, lastBarOfDay, tickcolor = Color.PLUM, arrowcolor = Color.PLUM, name = "EOD");

###Targets

#addOrder(OrderType.SELL_TO_CLOSE, entryprice + range, name = "Target",tickColor = GetColor(6), arrowColor = GetColor(6));
#addOrder(OrderType.SELL_TO_CLOSE, high >= targetPrice, tickColor = GetColor(6), arrowColor = GetColor(6));

#addOrder(OrderType.BUY_TO_CLOSE, entryprice - range, name = "Target",tickColor = GetColor(6), arrowColor = GetColor(6));
#addOrder(OrderType.BUY_TO_CLOSE, low <= targetPrice, tickColor = GetColor(6), arrowColor = GetColor(6));

##Stop Loss

#addOrder(OrderType.BUY_TO_CLOSE, high >= stopPrice,name = "Stop Out", tickColor = GetColor(5), arrowColor = GetColor(5));
#addOrder(OrderType.SELL_TO_CLOSE, low <= stopPrice, name = "Stop Out", tickColor = GetColor(5), arrowColor = GetColor(5));



# SCENARIOS
# -----------------------------------
def day = AggregationPeriod.DAY;
def Vday = GetAggregationPeriod() <= AggregationPeriod.DAY;
def dayO;
def dayC;
def dayH;
def dayL;
if Vday {
    dayO = open(period = day);
    dayC = close(period = day);
    dayH = high(period = day);
    dayL = low(period = day);
} else {
    dayO = Double.NaN;
    dayC = Double.NaN;
    dayH = Double.NaN;
    dayL = Double.NaN;
}

def diff = high[5] - low[5];

#Globals
def nan = Double.NaN;
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];

# SHARECALC

def qty = Round(2500 / dayO, 0);
def risk = qty * diff;

#AddLabel(yes, Round(qty, 0), color.white);
#AddLabel(yes, Round(risk, 1), if risk > 50 then color.red else if risk < 50 then color.green else color.white);



#Inputs
input fplTargetWinLoss = .50;
#hint fplTargetWinLoss: sets the target winlossRatio (in percent) which determines display colors of the W/L label.

input fplTargetWinRate = 1;
#hint fplTargetWinRate: sets the target winRate (float) which determines display colors of the WinRate label;

input fplHidePrice = no;
#hint fplHidePrice: hide's the underlying price graph. \nDefault is no.

input fplHideFPL = yes;
#hint fplHideFPL: hide's the underlying P&L graph.\nDefault is yes.

#temp input var references
def targetWinLoss = fplTargetWinLoss;
def targetWinRate = fplTargetWinRate;
def hidePrice = fplHidePrice;
def hideFPL = fplHideFPL;

#hide chart candles
HidePricePlot(hidePrice);

#Plot default Floating P&L
plot FPL = FPL();
FPL.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);
FPL.DefineColor("Positive and Up", Color.GREEN);
FPL.DefineColor("Positive and Down", Color.DARK_GREEN);
FPL.DefineColor("Negative and Down", Color.RED);
FPL.DefineColor("Negative and Up", Color.DARK_RED);
FPL.AssignValueColor(if FPL >= 0
                        then if FPL > FPL[1]
                        then FPL.Color("Positive and Up")
                        else FPL.Color("Positive and Down")
                        else if FPL < FPL[1]
                        then FPL.Color("Negative and Down")
                        else FPL.Color("Negative and Up"));
FPL.SetHiding(hideFPL);

plot ZeroLine = if IsNaN(close)
            then nan
            else 0;
ZeroLine.SetDefaultColor(Color.GRAY);
ZeroLine.SetHiding(hideFPL);

#Global Scripts
script incrementValue {
    input condition = yes;
    input increment =  1;
    input startingValue = 0;

    def _value = CompoundValue(1,
                if condition
                then _value[1] + increment
                else _value[1], startingValue);

    plot incrementValue = _value;
}
;

# Entry Calculations.  Note: Only parses on a Strategy Chart
def entry = EntryPrice();

def entryPrice = if !IsNaN(entry)
                then entry
                else entryPrice[1];

def hasEntry = !IsNaN(entry);

def isNewEntry = entryPrice != entryPrice[1];

#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);

def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);

def highBarNumber = CompoundValue(1, if FPL == highFPL
                                    then bn
                                    else highBarNumber[1], 0);

def lowBarNumber = CompoundValue(1, if FPL == lowFPL
                                then bn
                                else lowBarNumber[1], 0);

#Win/Loss ratios
def entryBarsTemp = if hasEntry
                then bn
                else nan;

def entryBarNum = if hasEntry and isNewEntry
                then bn
                else entryBarNum[1];

def isEntryBar = entryBarNum != entryBarNum[1];

def entryBarPL = if isEntryBar
                then FPL
                else entryBarPL[1];

def exitBarsTemp = if !hasEntry
                and bn > entryBarsTemp[1]
                then bn
                else nan;

def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
                then bn
                else exitBarNum[1];

def isExitBar = exitBarNum != exitBarNum[1];

def exitBarPL = if isExitBar
            then FPL
            else exitBarPL[1];

def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;

#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);

def highestReturn = if entryReturnWin[1] > highestReturn[1]
                then entryReturnWin[1]
                else highestReturn[1];

def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
                then entryReturnLoss[1]
                else lowestReturn[1];


def winRate = winCount / lossCount;
def winLossRatio = winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;

#Labels

AddLabel(yes,
        text = "Total Trades: " + entryCount + "  ",
        color = Color.CYAN
        );

AddLabel(yes,
        text = "WinCount: " + winCount +
            " | LossCount: " + lossCount +
            " | WinRate: " + Round(winRate, 2) + "  ",
        color = if winRate >= targetWinRate
                then Color.GREEN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "W/L: " + AsPercent(winLossRatio) + " ",
        color = if winLossRatio > targetWinLoss
                then Color.GREEN
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "AvgReturn: " + AsDollars(avgReturn) +
            " | AvgWin: " + AsDollars(avgWin) +
            " | AvgLoss: " + AsDollars(avgLoss) + "   ",
        color = if avgReturn >= 0
                then Color.DARK_ORANGE
                else Color.MAGENTA
        );

AddLabel(yes,
        text = "Total Profit: " + AsDollars(FPL) + "  ",
        color = if FPL > 0
                then Color.GREEN
                else Color.MAGENTA
    );
And some images:
6iW6n6L.png
2YDER7T.png


@Kojak Thanks for sharing!
 

Attachments

  • 6iW6n6L.png
    6iW6n6L.png
    95.5 KB · Views: 1,727
I like the idea, but I went to do some backtesting with OnDemand and found a major issue. Some of the trades shown on the chart aren't taken while "Live". Another issue here is the indicators aren't shown until the next candle ( I know this happens a lot with non-repainting strats). But for example I got a Long Entry indicator a minute late which caused me to miss a 50 cent gain then ended up losing 28 cents on the trade.

With that being said basically all of the backtesting is irelevant because it can't be replicated while live trading unless you full understand the strategy and don't need the indicators.
 
I like the idea, but I went to do some backtesting with OnDemand and found a major issue. Some of the trades shown on the chart aren't taken while "Live". Another issue here is the indicators aren't shown until the next candle ( I know this happens a lot with non-repainting strats). But for example I got a Long Entry indicator a minute late which caused me to miss a 50 cent gain then ended up losing 28 cents on the trade.

With that being said basically all of the backtesting is irelevant because it can't be replicated while live trading unless you full understand the strategy and don't need the indicators.
Appreciate the response......I created this strategy as a guide to see what was possible by only buying breakouts or breakdowns of inside bars on the 30 min chart to see if it would give me an edge... waiting on signals while live trading is really not what what was intended for this strategy but just showing what was possible was my intention.....Of course a basic understanding of the Strat will help in applying this. But I just wanted to present an easy to follow guide of trading only inside bars with rules to follow to make trading a little less stressful. The strategy is simple......

(1) No trades til the first 30min candle closes
(2) Wait for inside bar to form
(3) Long or Short when the candle after an inside bar breaks the high or low of inside bar
(4) Target - Sell when price crosses above the high or low of candle prior to inside bar
Stop Loss - place stop loss at low of inside bar if Long &
place stop loss at high of inside bar if short

Using this gives me a guide to help take emotions out of trading..It may help others like it is helping me.
 
Appreciate the response......I created this strategy as a guide to see what was possible by only buying breakouts or breakdowns of inside bars on the 30 min chart to see if it would give me an edge... waiting on signals while live trading is really not what what was intended for this strategy but just showing what was possible was my intention.....Of course a basic understanding of the Strat will help in applying this. But I just wanted to present an easy to follow guide of trading only inside bars with rules to follow to make trading a little less stressful. The strategy is simple......

(1) No trades til the first 30min candle closes
(2) Wait for inside bar to form
(3) Long or Short when the candle after an inside bar breaks the high or low of inside bar
(4) Target - Sell when price crosses above the high or low of candle prior to inside bar
Stop Loss - place stop loss at low of inside bar if Long &
place stop loss at high of inside bar if short

Using this gives me a guide to help take emotions out of trading..It may help others like it is helping me.
Thanks for the follow up. That makes sense. I'll definitely look into it more and see if I can do some testing on it.
 
I have not yet popped this into to TOS to see for myself, but there looks to be a significant issue- the simulated orders are placed at the open of the bar. If you are waiting for the price to break above/below then the fill would be that high/low plus the spread.

You can tell TOS where to fill: https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Others/AddOrder. It's unrealistic to use the open in this case because you have no guarantee that after breaking the high or low that price would return to the open to fill you.
 
Last edited by a moderator:
I have not yet popped this into to TOS to see for myself, but there looks to be a significant issue- the simulated orders are placed at the open of the bar. If you are waiting for the price to break above/below then the fill would be that high/low plus the spread.
ToS AddOrder default is to place the trade at the open of the next bar. This is the earliest point that a trade can happen in real world trading.
Therefore it is the guideline and practice of this forum to adhere to the use of the open of the next bar.
Anything else, does not represent real world trading and provides unrealistic results so it is not supported on this forum.
 
Last edited:
Alright guys this is a strategy that I'm sharing based on The Strat and trading inside bars on the 30 min time frame. In the short amount of backtesting that I've done it seems to work out very well. I have a profit loss backtester added to the script to give quick results after any changes are made....I welcome any and all help as I think this strategy has great possibilities!! I use it on the 30min time frame cause based on the backtester it gives the best accuracy. Simple rules are no trades til the first 30 min candle closes and long or short after a break of an inside bar's high or low. So far the results are good.. Let me know what you guys think?

http://tos.mx/dazwE0M

This is really cool! I was thinking about using something similar to this for coding a simple trading bot based on the inside bar breakout rules. Have you done anymore work with this strategy? I'm a noob to coding but would like to see if you've been able to tweak it or if you've moved on to something bigger and better?

@Kojak Just wanted to see how you're liking the STRAT? Any new developments on your trading ideas? I have been trading inside bars and breakout/reversals and backtesting on several timeframes.
 
Last edited:
A lot of interesting entry's based off the inside bar for sure. Gave me some trading ideas! However, I don't understand the code enough to know how many shares are being traded. It would be fun to mess around with more but my brain melts looking at code. I'm curious to know how to edit the text a bit... If anybody would add some information to the code that would help me out I would appreciate it! In the mean time just gonna google and hunt and peck and melt brain some more. I see a lot of promise in this idea. The PnL is insane on some tickers.
 
This strategy buys/sells 100 units at a time. 100 shares or 100 options etc
I'm currently testing this strategy out because it does produce some really good results at a glance in backtesting.
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
264 Online
Create Post

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top