After the fact study to help analyze entries in ThinkOrSwim

armybender

Active member
This is an indicator I have used for some time to help me conduct after-the-fact analysis on entries. The same thing can be accomplished with Fibonacci extensions, or other tools, but this simplifies the process.

It will either draw arrows or recolor bars that meet certain criteria.

The basic assumptions are as follows:
  1. A trade is entered either one tick above or below a bar (above for long / below for short) using a stop entry.
  2. A stop order is placed one tick below the bar to exit the trade if the market goes the opposite direction.
  3. A limit order is placed 1x the bar height + 2 ticks above or below the entry price to exit the trade with a profit if the limit is met.
  4. Arrows or colored bars occur when the profit target is met and the stop exit target is NOT met.
  5. Because this is analyzing trades on a bar-by-bar basis (i.e. not based on movement as bars form) it cannot determine if outside bars (bars that go above and below) would have been profitable or not, so it assumes they would not have been.

The reason for this methodology is to ensure the "trader's equation" is followed, which is: profit must be equal or greater to the risk * the probability of the success of the trade. Probability is an estimate, but the general thesis is that you shouldn't risk more on a probability adjusted basis than you're going to earn, or you'll just slowly bleed yourself dry.

Lastly, you'll notice that my license notes are pretty lax. I wrote it, but I don't care what you do with it. Modify it, share it, sell it. Frankly, I don't care. Here's the thing, I use it as a tool. If you don't like it, don't use it. If it helps you, great... use it. If you want to modify it, go ahead. My only hope is that this will help educate people about the trader's equation (Al brooks writes some great stuff on it) and that they'll learn to read the charts instead of using indicators (which are just chart data and math) to make good trades.

NOTE: I believe TOS's update today has broken the processing of nested if/then/else statements, so there seems to be an issue with bar coloring under certain conditions.

Study screenshot with bar coloring turned off and arrows off.
KJ9Bbti.jpg



Ruby:
###  ACHIEVED_PROFIT_TARGET --- 2023-03-11 BY ARMYBENDER

###  License: I don't care - do what you want with it.

###  Determines whether a trade would have achieved a profit target before being stopped out.
###  Risk is based on the bar height + 2 ticks (1 tick for a stop entry price above/below the bar, and
###  1 tick for a stop exit price below the bar.  The study uses future bars, so it cannot be used in
###  realtime to make trade decisions, however, it is helpful for quick analysis or measurement
###  after the fact.  This will work with all bar types.


### DECLARATIONS
declare upper;
declare once_per_bar;


### GLOBAL COLOR DEFINITIONS
DefineGlobalColor("Green", CreateColor(0, 155, 0));
DefineGlobalColor("Red", CreateColor(225, 105, 105));
DefineGlobalColor("Gray", CreateColor(181, 181, 181));


### INPUTS
input requireSignalBar = no;
input colorBars = yes;
input showArrows = no;
input requireTickThrough = yes;
input rewardMode = {default "Risk Reward Ratio", "Number of Ticks"};
input riskTargetRatio = 1.0;
input rewardNumberOfTicks = 4;
input numberOfBarsForward = 30;
input offsetBarsPlot = 0;
input arrowTickOffset = 2;
input arrowSize = 1;
input showHammer2EBars = no;


### DEFINITIONS
def rtRatio = riskTargetRatio;
def barsFwd = numberOfBarsForward;

def longEntry = high + TickSize();
def shortEntry = low - TickSize();

def riskAmount = if requireTickThrough then high - low + (3 * TickSize()) else high - low + (2 * TickSize());

def longStop = low - TickSize();
def shortStop = high + TickSize();

def longTarget =
    if rewardMode == rewardMode."Risk Reward Ratio" then
        longEntry + (rtRatio * riskAmount)
    else if rewardMode == rewardMode."Number of Ticks" then
        longEntry + rewardNumberOfTicks * TickSize()
    else
        Double.NaN
;
def shortTarget =
    if rewardMode == rewardMode."Risk Reward Ratio" then
        shortEntry - (rtRatio * riskAmount)
    else if rewardMode == rewardMode."Number of Ticks" then
        shortEntry - rewardNumberOfTicks * TickSize()
    else
        Double.NaN
;

def isUp = close > open;
def isDown = close < open;
def isBullDoji = IsDoji() and high == close;
def isBearDoji = IsDoji() and low == close;

def isBullSignalBar = if (isUp or isBullDoji) and low < low[1] and high[-1] > high then yes else no;
def isBearSignalBar = if (isDown or isBearDoji) and high > high[1] and low[-1] < low then yes else no;

def longRiskTargetMet =
    if !requireSignalBar or isBullSignalBar then
        fold l = 1 to barsFwd
        with long = Double.NaN
        while IsNaN(long)
        do
            if GetValue(low, -l) <= longStop then
                no
            else if GetValue(high, -l) >= longTarget then
                yes
            else
                Double.NaN
    else
        Double.NaN;

def shortRiskTargetMet =
    if !requireSignalBar or isBearSignalBar then
        fold s = 1 to barsFwd
        with short = Double.NaN
        while IsNaN(short)
        do
            if GetValue(high, -s) >= shortStop then
                no
            else if GetValue(low, -s) <= shortTarget then
                yes
            else
                Double.NaN
    else
        Double.NaN;

def longPlotData =
    if longRiskTargetMet then
        low - (arrowTickOffset * TickSize())
    else
        Double.NaN;

def shortPlotData =
    if shortRiskTargetMet then
        high + (arrowTickOffset * TickSize())
    else
        Double.NaN;


### PLOTS
plot longPlot = if showArrows then if longPlotData[offsetBarsPlot] then low - (arrowTickOffset * TickSize()) else Double.NaN else Double.NaN;

plot shortPlot = if showArrows then if shortPlotData[offsetBarsPlot] then high + (arrowTickOffset * TickSize()) else Double.NaN else Double.NaN;


### BAR COLORING
AssignPriceColor(
    if colorBars then
        if longRiskTargetMet then GlobalColor("Green")
        else if shortRiskTargetMet then GlobalColor("Red")
        else GlobalColor("Gray")
    else Color.Current
);


### FORMATTING
longPlot.DefineColor("Long", CreateColor(0, 205, 0)); ### Custom green color
longPlot.SetDefaultColor(longPlot.Color("Long"));
longPlot.HideBubble();
longPlot.HideTitle();
longPlot.SetLineWeight(arrowSize);
longPlot.SetPaintingStrategy(PaintingStrategy.ARROW_UP);

shortPlot.DefineColor("Short", CreateColor(205, 0, 0)); ### Custom red color
shortPlot.SetDefaultColor(shortPlot.Color("Short"));
shortPlot.HideBubble();
shortPlot.HideTitle();
shortPlot.SetLineWeight(arrowSize);
shortPlot.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
 

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

This is an indicator I have used for some time to help me conduct after-the-fact analysis on entries. The same thing can be accomplished with Fibonacci extensions, or other tools, but this simplifies the process.

It will either draw arrows or recolor bars that meet certain criteria.

The basic assumptions are as follows:
  1. A trade is entered either one tick above or below a bar (above for long / below for short) using a stop entry.
  2. A stop order is placed one tick below the bar to exit the trade if the market goes the opposite direction.
  3. A limit order is placed 1x the bar height + 2 ticks above or below the entry price to exit the trade with a profit if the limit is met.
  4. Arrows or colored bars occur when the profit target is met and the stop exit target is NOT met.
  5. Because this is analyzing trades on a bar-by-bar basis (i.e. not based on movement as bars form) it cannot determine if outside bars (bars that go above and below) would have been profitable or not, so it assumes they would not have been.

The reason for this methodology is to ensure the "trader's equation" is followed, which is: profit must be equal or greater to the risk * the probability of the success of the trade. Probability is an estimate, but the general thesis is that you shouldn't risk more on a probability adjusted basis than you're going to earn, or you'll just slowly bleed yourself dry.

Lastly, you'll notice that my license notes are pretty lax. I wrote it, but I don't care what you do with it. Modify it, share it, sell it. Frankly, I don't care. Here's the thing, I use it as a tool. If you don't like it, don't use it. If it helps you, great... use it. If you want to modify it, go ahead. My only hope is that this will help educate people about the trader's equation (Al brooks writes some great stuff on it) and that they'll learn to read the charts instead of using indicators (which are just chart data and math) to make good trades.

NOTE: I believe TOS's update today has broken the processing of nested if/then/else statements, so there seems to be an issue with bar coloring under certain conditions.

Study screenshot with bar coloring turned off and arrows off.
KJ9Bbti.jpg



Ruby:
###  ACHIEVED_PROFIT_TARGET --- 2023-03-11 BY ARMYBENDER

###  License: I don't care - do what you want with it.

###  Determines whether a trade would have achieved a profit target before being stopped out.
###  Risk is based on the bar height + 2 ticks (1 tick for a stop entry price above/below the bar, and
###  1 tick for a stop exit price below the bar.  The study uses future bars, so it cannot be used in
###  realtime to make trade decisions, however, it is helpful for quick analysis or measurement
###  after the fact.  This will work with all bar types.


### DECLARATIONS
declare upper;
declare once_per_bar;


### GLOBAL COLOR DEFINITIONS
DefineGlobalColor("Green", CreateColor(0, 155, 0));
DefineGlobalColor("Red", CreateColor(225, 105, 105));
DefineGlobalColor("Gray", CreateColor(181, 181, 181));


### INPUTS
input requireSignalBar = no;
input colorBars = yes;
input showArrows = no;
input requireTickThrough = yes;
input rewardMode = {default "Risk Reward Ratio", "Number of Ticks"};
input riskTargetRatio = 1.0;
input rewardNumberOfTicks = 4;
input numberOfBarsForward = 30;
input offsetBarsPlot = 0;
input arrowTickOffset = 2;
input arrowSize = 1;
input showHammer2EBars = no;


### DEFINITIONS
def rtRatio = riskTargetRatio;
def barsFwd = numberOfBarsForward;

def longEntry = high + TickSize();
def shortEntry = low - TickSize();

def riskAmount = if requireTickThrough then high - low + (3 * TickSize()) else high - low + (2 * TickSize());

def longStop = low - TickSize();
def shortStop = high + TickSize();

def longTarget =
    if rewardMode == rewardMode."Risk Reward Ratio" then
        longEntry + (rtRatio * riskAmount)
    else if rewardMode == rewardMode."Number of Ticks" then
        longEntry + rewardNumberOfTicks * TickSize()
    else
        Double.NaN
;
def shortTarget =
    if rewardMode == rewardMode."Risk Reward Ratio" then
        shortEntry - (rtRatio * riskAmount)
    else if rewardMode == rewardMode."Number of Ticks" then
        shortEntry - rewardNumberOfTicks * TickSize()
    else
        Double.NaN
;

def isUp = close > open;
def isDown = close < open;
def isBullDoji = IsDoji() and high == close;
def isBearDoji = IsDoji() and low == close;

def isBullSignalBar = if (isUp or isBullDoji) and low < low[1] and high[-1] > high then yes else no;
def isBearSignalBar = if (isDown or isBearDoji) and high > high[1] and low[-1] < low then yes else no;

def longRiskTargetMet =
    if !requireSignalBar or isBullSignalBar then
        fold l = 1 to barsFwd
        with long = Double.NaN
        while IsNaN(long)
        do
            if GetValue(low, -l) <= longStop then
                no
            else if GetValue(high, -l) >= longTarget then
                yes
            else
                Double.NaN
    else
        Double.NaN;

def shortRiskTargetMet =
    if !requireSignalBar or isBearSignalBar then
        fold s = 1 to barsFwd
        with short = Double.NaN
        while IsNaN(short)
        do
            if GetValue(high, -s) >= shortStop then
                no
            else if GetValue(low, -s) <= shortTarget then
                yes
            else
                Double.NaN
    else
        Double.NaN;

def longPlotData =
    if longRiskTargetMet then
        low - (arrowTickOffset * TickSize())
    else
        Double.NaN;

def shortPlotData =
    if shortRiskTargetMet then
        high + (arrowTickOffset * TickSize())
    else
        Double.NaN;


### PLOTS
plot longPlot = if showArrows then if longPlotData[offsetBarsPlot] then low - (arrowTickOffset * TickSize()) else Double.NaN else Double.NaN;

plot shortPlot = if showArrows then if shortPlotData[offsetBarsPlot] then high + (arrowTickOffset * TickSize()) else Double.NaN else Double.NaN;


### BAR COLORING
AssignPriceColor(
    if colorBars then
        if longRiskTargetMet then GlobalColor("Green")
        else if shortRiskTargetMet then GlobalColor("Red")
        else GlobalColor("Gray")
    else Color.Current
);


### FORMATTING
longPlot.DefineColor("Long", CreateColor(0, 205, 0)); ### Custom green color
longPlot.SetDefaultColor(longPlot.Color("Long"));
longPlot.HideBubble();
longPlot.HideTitle();
longPlot.SetLineWeight(arrowSize);
longPlot.SetPaintingStrategy(PaintingStrategy.ARROW_UP);

shortPlot.DefineColor("Short", CreateColor(205, 0, 0)); ### Custom red color
shortPlot.SetDefaultColor(shortPlot.Color("Short"));
shortPlot.HideBubble();
shortPlot.HideTitle();
shortPlot.SetLineWeight(arrowSize);
shortPlot.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
Can you please help to scan for long and short plot? Thanks
 
Can you please help to scan for long and short plot? Thanks

Interesting idea. I don't use scanners since I only trade a handful of futures. No need for a scanner.

Maybe @BenTen or @halcyonguy can help with this. I don't know if it's possible to use a fold function in a scanner or not.

In addition I have a an updated version that allows you to trail the colors. I figure that part may be useful for creating a scanner. I've included it below.


Ruby:
###  ACHIEVED_PROFIT_TARGET --- 2023-03-11 BY ARMYBENDER

###  License: I don't care - do what you want with it.

###  Determines whether a trade would have achieved a profit target before being stopped out.
###  Risk is based on the bar height + 2 ticks (1 tick for a stop entry price above/below the bar, and
###  1 tick for a stop exit price below the bar.  The study uses future bars, so it cannot be used in
###  realtime to make trade decisions, however, it is helpful for quick analysis or measurement
###  after the fact.  This will work with all bar types.


### DECLARATIONS
declare upper;
#declare once_per_bar;


### GLOBAL COLOR DEFINITIONS
DefineGlobalColor("Green", CreateColor(0, 155, 0));
DefineGlobalColor("Red", CreateColor(225, 105, 105));
DefineGlobalColor("Gray", CreateColor(181, 181, 181));


### INPUTS
input requireSignalBar = no;
input colorBars = yes;
input trailColors = yes;
input showArrows = no;
input requireTickThrough = yes;
input riskTargetRatio = 1.0;
input numberOfBarsForward = 30;
input showTargetsOnColorChange = yes;


### DEFINITIONS
def isLastBar = !IsNaN(close) and IsNaN(close[-1]);

def rtRatio = riskTargetRatio;
def barsFwd = numberOfBarsForward;

def longEntry = high + TickSize();
def shortEntry = low - TickSize();

def riskAmount = if requireTickThrough then high - low + (3 * TickSize()) else high - low + (2 * TickSize());

def longStop = low - TickSize();
def shortStop = high + TickSize();

def longTarget = longEntry + (rtRatio * riskAmount);
def shortTarget = shortEntry - (rtRatio * riskAmount);

def isUp = close > open;
def isDown = close < open;
def isBullDoji = IsDoji() and high == close;
def isBearDoji = IsDoji() and low == close;

def isBullSignalBar = if (isUp or isBullDoji) and low < low[1] and high[-1] > high then yes else no;
def isBearSignalBar = if (isDown or isBearDoji) and high > high[1] and low[-1] < low then yes else no;

def longRiskTargetMet =
    if !requireSignalBar or isBullSignalBar then
        fold l = 1 to barsFwd
        with long = Double.NaN
        while IsNaN(long)
        do
            if GetValue(low, -l) <= longStop then
                no
            else if GetValue(high, -l) >= longTarget then
                yes
            else if GetValue(isLastBar, -l) then
                no
            else
                Double.NaN
    else
        Double.NaN;

def shortRiskTargetMet =
    if !requireSignalBar or isBearSignalBar then
        fold s = 1 to barsFwd
        with short = Double.NaN
        while IsNaN(short)
        do
            if GetValue(high, -s) >= shortStop then
                no
            else if GetValue(low, -s) <= shortTarget then
                yes
            else if GetValue(isLastBar, -s) then
                no
            else
                Double.NaN
    else
        Double.NaN;

def colorValue =
    if longRiskTargetMet then 1               # Green
    else if shortRiskTargetMet then -1        # Red
    else if trailColors then colorValue[1]    # Last Color
    else 0;                                   # Gray

### PLOTS
plot longPlot = if showTargetsOnColorChange and colorValue[1] == -1 and colorValue == 1 then longTarget else Double.NaN;

plot shortPlot = if showTargetsOnColorChange and colorValue[1] == 1 and colorValue == -1 then shortTarget else Double.NaN;


# This plot forces the repaint of historic bars by offsetting a plot into the future.  Without this the study will not recalculate historical bars.
plot forceBarRepaint = close[-barsFwd] * Double.NaN;

### BAR COLORING
AssignPriceColor(
    if colorBars then
        if colorValue == 1 then GlobalColor("Green")
        else if colorValue == -1 then GlobalColor("Red")
        else if isLastBar then Color.CURRENT
        else GlobalColor("Gray")
    else GlobalColor("Gray")
);


### FORMATTING
longPlot.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
longPlot.DefineColor("Long", CreateColor(0, 205, 0)); ### Custom green color
longPlot.SetDefaultColor(longPlot.Color("Long"));
longPlot.HideBubble();
longPlot.HideTitle();


shortPlot.SetPaintingStrategy(PaintingStrategy.HORIZONTAL);
shortPlot.DefineColor("Short", CreateColor(205, 0, 0)); ### Custom red color
shortPlot.SetDefaultColor(shortPlot.Color("Short"));
shortPlot.HideBubble();
shortPlot.HideTitle();
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
396 Online
Create Post

Similar threads

Similar threads

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