Pin Bar Reversal Indicator for ThinkorSwim

BenTen

Administrative
Staff member
Staff
VIP
Lifetime
Here is an indicator that detects bullish and bearish Pin Bar candlestick patterns on your ThinkorSwim chart.

Pin Bars are candlestick patterns characterized by a long wick and a small body. They indicate potential reversals in market sentiment.

The below version with RSI which takes overbought and oversold values into consideration can be used for confirmation.

uNKnAuM.png


thinkScript Code

Rich (BB code):
input LastBars = 0;
input MaxNoseBodySize = 0.33; #(default = 0.33) — maximum allowed body/length ratio for the Nose bar.
input NoseBodyPosition = 0.4; #(default = 0.4) — Nose body should be position in top (bottom for bearish pattern) part of the Nose bar.
input LeftEyeOppositeDirection = yes; #(default = true) — tells the indicator that the Left Eye bar should be bearish for bullish Pinbar, and bullish for bearish Pinbar.
input NoseSameDirection = yes; #(default = true) — tells the indicator that the Nose bar should be of the same direction as the pattern itself.
input NoseBodyInsideLeftEyeBody = no; #(default = false) — tells the indicator that the Nose body should be inside the Left Eye body.
input LeftEyeMinBodySize = 0.1; #(default = 0.1) — minimum size of the Left Eye body relative to the bar length.
input NoseProtruding = 0.5; #(default = 0.5) — minimum protrusion of the Nose bar relative to the bar length.
input NoseBodyToLeftEyeBody = 1; #(default = 1) — maximum size of the Nose body relative to the Left eye body.
input NoseLengthToLeftEyeLength = 0; #(default = 0) — minimum Nose length relative to the Left Eye length.
input LeftEyeDepth = 0.2; #(default = 0.2) — minimum depth of the Left Eye relative to its length. Depth is length of the part of the bar behind the Nose.

# Left Eye and Nose bars's paramaters
def NoseLength = High - Low;
def LeftEyeLength = High[1] - Low[1];
def NoseBody = Absvalue(Open - Close);
def LeftEyeBody = Absvalue(Open[1] - Close[1]);

# Bearish Pinbar

def BearSignalDown = if  (High - High[1] >= NoseLength * NoseProtruding) and
                     (NoseBody / NoseLength <= MaxNoseBodySize) and
                     (1 - (High - Max(Open, Close)) / NoseLength < NoseBodyPosition) and
                     if LeftEyeOppositeDirection then (Close[1] > Open[1]) else 1 and
                     if NoseSameDirection then (Close < Open) else 1  and
                     (LeftEyeBody / LeftEyeLength  >= LeftEyeMinBodySize) and
                     ((Max(Open, Close) <= High[1]) && (Min(Open, Close) >= Low[1]))  and
                     (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody) and
                     (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength) and
                     (Low - Low[1] >= LeftEyeLength * LeftEyeDepth) and
                     if NoseBodyInsideLeftEyeBody then ((Max(Open, Close) <= Max(Open[1], Close[1]))
                     && (Min(Open,  Close) >= Min(Open[1],  Close[1]))) else 1                  
                     then yes
                     else no ;

def BullSignalUp   = if (Low[1] - Low >= NoseLength * NoseProtruding) and
                     (NoseBody / NoseLength <= MaxNoseBodySize) and
                     (1 - (Min(Open, Close) - Low) / NoseLength < NoseBodyPosition) and
                     if LeftEyeOppositeDirection then (Close[1] < Open[1]) else 1 and
                     if NoseSameDirection then (Close > Open) else 1 and
                     (LeftEyeBody / LeftEyeLength >= LeftEyeMinBodySize) and
                     ((Max(Open, Close) <= High[1]) && (Min(Open, Close) >= Low[1])) and
                     (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody) and
                     (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength) and
                     (High[1] - High >= LeftEyeLength * LeftEyeDepth) and
                     if NoseBodyInsideLeftEyeBody then ((Max(Open, Close) <= Max(Open[1], Close[1]))
                     && (Min(Open, Close) >= Min(Open[1], Close[1]))) else 1
                     then yes
                     else no;

#defining the bullish / bearish signals

def bullish_signal = BullSignalup;

def bearish_signal = BearSignalDown;

#plotting the bullish / bearish signals
plot bullish = bullish_signal;
bullish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot bearish = bearish_signal;
bearish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

Shareable Link

https://tos.mx/l2rtkP

Similar to the Engulfing candles with RSI, we added the overbought input to bearish and oversold input to bullish Pin Bar candles. That means a Pin Bar candle will only be generated when a stock is oversold or overbought according to the default RSI indicator. You can also set each value to your liking.

Hopefully that will help to reduce false signals.

Pin Bars with RSI

Rich (BB code):
input length = 14;
input over_Bought = 75;
input over_Sold = 25;
input price = close;
input averageType = AverageType.WEIGHTED;

input LastBars = 0;
input MaxNoseBodySize = 0.33; #(default = 0.33) — maximum allowed body/length ratio for the Nose bar.
input NoseBodyPosition = 0.4; #(default = 0.4) — Nose body should be position in top (bottom for bearish pattern) part of the Nose bar.
input LeftEyeOppositeDirection = yes; #(default = true) — tells the indicator that the Left Eye bar should be bearish for bullish Pinbar, and bullish for bearish Pinbar.
input NoseSameDirection = yes; #(default = true) — tells the indicator that the Nose bar should be of the same direction as the pattern itself.
input NoseBodyInsideLeftEyeBody = no; #(default = false) — tells the indicator that the Nose body should be inside the Left Eye body.
input LeftEyeMinBodySize = 0.1; #(default = 0.1) — minimum size of the Left Eye body relative to the bar length.
input NoseProtruding = 0.5; #(default = 0.5) — minimum protrusion of the Nose bar relative to the bar length.
input NoseBodyToLeftEyeBody = 1; #(default = 1) — maximum size of the Nose body relative to the Left eye body.
input NoseLengthToLeftEyeLength = 0; #(default = 0) — minimum Nose length relative to the Left Eye length.
input LeftEyeDepth = 0.2; #(default = 0.2) — minimum depth of the Left Eye relative to its length. Depth is length of the part of the bar behind the Nose.

# Left Eye and Nose bars's paramaters
def NoseLength = High - Low;
def LeftEyeLength = High[1] - Low[1];
def NoseBody = Absvalue(Open - Close);
def LeftEyeBody = Absvalue(Open[1] - Close[1]);

# Bearish Pinbar

def BearSignalDown = if  (High - High[1] >= NoseLength * NoseProtruding) and
                     (NoseBody / NoseLength <= MaxNoseBodySize) and
                     (1 - (High - Max(Open, Close)) / NoseLength < NoseBodyPosition) and
                     if LeftEyeOppositeDirection then (Close[1] > Open[1]) else 1 and
                     if NoseSameDirection then (Close < Open) else 1  and
                     (LeftEyeBody / LeftEyeLength  >= LeftEyeMinBodySize) and
                     ((Max(Open, Close) <= High[1]) && (Min(Open, Close) >= Low[1]))  and
                     (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody) and
                     (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength) and
                     (Low - Low[1] >= LeftEyeLength * LeftEyeDepth) and
                     if NoseBodyInsideLeftEyeBody then ((Max(Open, Close) <= Max(Open[1], Close[1]))
                     && (Min(Open,  Close) >= Min(Open[1],  Close[1]))) else 1                  
                     then yes
                     else no ;

def BullSignalUp   = if (Low[1] - Low >= NoseLength * NoseProtruding) and
                     (NoseBody / NoseLength <= MaxNoseBodySize) and
                     (1 - (Min(Open, Close) - Low) / NoseLength < NoseBodyPosition) and
                     if LeftEyeOppositeDirection then (Close[1] < Open[1]) else 1 and
                     if NoseSameDirection then (Close > Open) else 1 and
                     (LeftEyeBody / LeftEyeLength >= LeftEyeMinBodySize) and
                     ((Max(Open, Close) <= High[1]) && (Min(Open, Close) >= Low[1])) and
                     (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody) and
                     (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength) and
                     (High[1] - High >= LeftEyeLength * LeftEyeDepth) and
                     if NoseBodyInsideLeftEyeBody then ((Max(Open, Close) <= Max(Open[1], Close[1]))
                     && (Min(Open, Close) >= Min(Open[1], Close[1]))) else 1
                     then yes
                     else no;

#defining the bullish / bearish signals

def bullish_signal = RSI(length = length, averageType = averageType) < over_Sold and BullSignalup;

def bearish_signal = RSI(length = length, averageType = averageType) > over_Bought and BearSignalDown;

#plotting the bullish / bearish signals
plot bullish = bullish_signal;
bullish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);

plot bearish = bearish_signal;
bearish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);

P.S: I found the original code without any header on it so I can't give credit to the developer. If you know who created it please let me know.
 

Attachments

  • uNKnAuM.png
    uNKnAuM.png
    359.7 KB · Views: 671
Last edited by a moderator:
Hi. Is there a way to use this indicator in a scan? Thinkorswim throws an error : "too complex"
I can't seem to find any built-in pinbar pattern finder on the platform..

Thanks in advance
 
@BenTen Since you asked, it appears like your version of the first pinbar study you posted in this thread is based on a study called KMS_PINBAR_V2 that was posted by madhu_kms in the Yahoo TOS_ThinkScript group in 2016. The version you have has very minor edits from madhu's version. I happened to find this when I was reviewing my files.

Here is some commentary from Madhu's post you may be interested in reading

This indcator is based of Pinbar Detector (MetaTrader indicator)

https://www.earnforex.com/forex-strategy/pinbar-trading-system/https://www.earnforex.com/metatrader-indicators/Pinbar-Detector/
I have seen people using pin bar at support and resistance to identify trend reversals. As a matter of fact I was looking for some indicator to identify PinBar on chart came across PinBar Detector and converted it to TOS.

Experienced traders can verify if the MT5 to TOS conversion is correct. I tried on couple of charts identifies the Pinbars correctly. If anyone has MT5 just compare it if matches.

Just passing to you for info sharing, I don't use this indicator.
 
I am very new to these scripts and do excuse if this is a naive question. Is it possible to replace the arrow with cloud green for buy and red for sell. Similar to the white oval highlights in the above diagram.

Thanks in advance.
 
I am very new to these scripts and do excuse if this is a naive question. Is it possible to replace the arrow with cloud green for buy and red for sell. Similar to the white oval highlights in the above diagram.

Thanks in advance.

The original version of the code that I mentioned in post#3 is a study that has up/down arrows for identification of bullish/bearish pinbars. The version that @BenTen has essentially has the same definitions and can be used for both a scan as well as a study.

To replace the color of the arrows with GREEN for buy and RED for sell replace the plot specific statements in the code as follows:

Code:
#plotting the bullish / bearish signals
plot bullish = bullish_signal;
bullish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
bullish.SetDefaultColor(Color.GREEN);

plot bearish = bearish_signal;
bearish.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
bearish.SetDefaultColor(Color.RED);

As far as a white oval highlight as you've detailed, that is not a feature available from ThinkScript
To use as a scan you would first install the study, and then you can simply make reference to that study in the scanner

EDITED: Just tested it out
 
Last edited:
Hi there, does anyone know how to add an alert to the Pin Bar study on this thread to give an alert on ThinkorSwim when a Pin Bar Boolean arrow is printed? I am familiar with price alerts, but I haven't quite figured out the steps I need to take to have ThinkorSwim give me an email alert when a Boolean arrow up/down is printed. I have the study on my ThinkorSwim and it is very good, but an alert would be even better. Thanks, Jarrod
 
@Rowing109 Add this to the end of your script:

Code:
# Alerts
Alert(bullish, " ", Alert.Bar, Sound.Chimes);
Alert(bearish, " ", Alert.Bar, Sound.Bell);
 
Will this script give me the alert after the arrow is printed after the close of the candle? I notice an arrow will appear sometimes while the candle is still forming and I would like it to give an alert after a real pin is printed, not one that may be forming, then end up not being a pin. Thank you so much. Jarrod
 
Okay, great. Let me see if I can take this code one step further, is it possible to have written in the code what timeframe the pin was identified on as well as what market it was identified on?

Also, for the alert, is there a way to have it send to me via email too?

Maybe another way to look at this is from the beginning of the script, to have the Boolean arrow form only after the candle closes and meets the parameters set forth in the script. Is this possible?
 
Last edited by a moderator:
"Pin Bar" Candlestick Pattern Indicator
The "Pin Bar" indicator shows with arrows on the chart the situation when "Pin Bar" is drawn after a certain trend (the most probable signal for reversal).
Settings. Inputs: The ratio of the total length of a candlestick to the candlestick body (i ratio: 2.5) and the number of bars - trends before the PinBar (i-bars: 2).
________
Code:
#thinkscript indicator: Pin_Bar.
#Draws the Pinbars on the chart following the trend.
#by thetrader.top
input iRatio = 2.5; #candle length-to-body ratio
input iBars = 2; #trend number of bars
def iTelo=absValue (close-open);
def bPinUp = (((high - low)/(iTelo)) >iRatio) and high > high[1] and low>low[1] and max(open,close)<high-((high-low)/2);
def bPinDown =(((high - low)/(iTelo)) >iRatio) and high < high[1] and low<low[1] and min(open,close)>low+((high-low)/2);
def bTrendUp = fold TUbar = 1 to iBars+1 with TUsumm=1 do if (close[TUbar]-open[TUbar]>0) then TUsumm*1 else TUsumm*0;
def bTrendUp2 = fold TUbar2 = 1 to iBars with TUsumm2=1 do if (high[TUbar2]==highest(high[TUbar2],iBars)) then TUsumm2*1 else TUsumm2*0;
def bTrendDown = fold TDbar = 1 to iBars+1 with TDsumm=1 do if (open[TDbar]-close[TDbar]>0) then TDsumm*1 else TDsumm*0;
def bTrendDown2 = fold TDbar2 = 1 to iBars with TDsumm2=1 do if (low[TDbar2]==lowest(low[TDbar2],iBars)) then TDsumm2*1 else TDsumm2*0;
def bSignalUp = bPinUp and bTrendUp and bTrendUp2;
def bSignalDown = bPinDown and bTrendDown and bTrendDown2;
plot up = if bSignalUp  then high else double.NaN;
plot down = if bSignalDown then high else double.NaN;
up.SetPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_down);
down.SetPaintingStrategy(paintingStrategy.BOOLEAN_ARROW_up);
up.setDefaultColor(color.LIGHT_red);
down.setDefaultColor(color.LIGHT_green);
 
Last edited by a moderator:
@lukeskywalker - Thank You for posting.


A few key points for the Pin Bar Indicator.

A Pin Bar must have:

– Open and close within previous candle

– Candle wick minimum 3 times the length of the candle body

– Long nose protruding from all other candles (must stick out from all other candles)
 
Hello Ben, you are incredible
You made exactly what I was looking for without saying it ! hahah

I have a bit of a problem because is not working for me. Let me show you:

1729199034451.png


This is a 5 min time frame. In the doji bar of the top didnt paint it, and also painted one with rsi
 

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

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
376 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