Category Trend  Published on 15/03/2021

PinBar Detector

Description

 

 

New Version: 1.1

Add the calculation left room candles function, it can get the number of candles didn't touch the pinbar price

New parameters:

CustomCalLeftRoomCandle:  set how many left candles needs to be calculated

CustomLeftRoomLength(%): the percentage of the pinbar nose length to be compared

 

Result:

This is a PinBar detector indicator and I convert from the MT4 version (not convert by auto online tool) 

so you can also go to the below line for detail description:

https://www.earnforex.com/metatrader-indicators/Pinbar-Detector/

 

Pinbar Detector is an indicator that tries to detect Pinbars (also known as "Pin-bar" or "Pin bar") and marks them by placing a "smiling face" symbol below the bullish Pinbars and above the bearish Pinbars. It is a pure price action indicator, which is not using any standard technical indicators in its code. The configuration of Pinbar detection can be done via the indicator's input parameters. Pinbar Detector can issue platform alerts and email alerts on detection. The indicator is available both for MT4 and MT5 versions of the trading platform.

 

Support parameters:

 

Input parameters

  • CountBars (default = 0) — the maximum number of bars, on which to detect the pinbars. 0 = all.
  • DisplayDistance (default = 5) — the distance from the candles to the pinbar "smiling face" symbols.
  • UseAlerts (default = true) — tells the indicator to issue platform alert with sound on Pinbar detection.
  • UseEmailAlerts (default = false) — tells the indicator to issue an email alert on Pinbar detection. Email should be properly configured in MetaTrader via Tools->Options->Email.
  • UseCustomSettings (default = false) — tells the indicator to use custom Pinbar detection parameters described below.
  • CustomMaxNoseBodySize (default = 0.33) — maximum allowed body/length ratio for the Nose bar.
    Maximum Nose body size relative to its length
  • CustomNoseBodyPosition (default = 0.4) — Nose body should be positioned in the top (bottom for bearish pattern) part of the Nose bar.
    Nose body position inside its own candle
  • CustomLeftEyeOppositeDirection (default = true) — tells the indicator that the Left Eye bar should be bearish for bullish Pinbar, and bullish for bearish Pinbar.
    Is Left Eye candle opposite to the pattern's direction?
  • CustomNoseSameDirection (default = true) — tells the indicator that the Nose bar should be of the same direction as the pattern itself.
    Is Nose candle in the same direction as the pattern itself?
  • CustomNoseBodyInsideLeftEyeBody (default = false) — tells the indicator that the Nose body should be inside the Left Eye body.
    Is Nose body inside Left Eye body?
  • CustomLeftEyeMinBodySize (default = 0.1) — minimum size of the Left Eye body relative to the bar length.
    Minimum Left Eye body size relative to its candle length
  • CustomNoseProtruding (default = 0.5) — minimum protrusion of the Nose bar relative to the bar length.
    Minimum protrusion of the Nose candle above the high of the Left Eye candle relative to Nose candle length
  • CustomNoseBodyToLeftEyeBody (default = 1) — maximum size of the Nose body relative to the Left eye body.
    Maximum ratio between Nose candle body and Left Eye candle body
  • CustomNoseLengthToLeftEyeLength (default = 0) — minimum Nose length relative to the Left Eye length.
    Minimum ratio of Nose candle length to the Left Eye candle length
  • CustomLeftEyeDepth (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.
    Minimum difference between Nose low and Left Eye low relative to Left Eye candle length

 

===================================

Winson

CoderBlog:

https://www.coderblog.in


////////////////////////////////////////////////////////////////////////////////////////////////////////
//Author : Winson
//Website : https://www.coderblog.in
//Version : 1.1 
//Description : Detect the Pinbar candlestick
////////////////////////////////////////////////////////////////////////////////////////////////////////

//reference: https://www.earnforex.com/metatrader-indicators/Pinbar-Detector/

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using System.Collections.Generic;

namespace cAlgo
{
    public enum AlertType
    {
        None,
        Sound,
        Email
    }

    /// <summary>
    /// Save the Pinbar status 
    /// </summary>
    public class PinBar
    {
        public bool IsBearishBar { get; set; }
        public Bar Bar { get; set; }
    }

    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PinBarDetector : Indicator
    {

        [Parameter("Bearish Color", DefaultValue = Colors.Red, Group = "Base Settings")]
        public Colors BearishColor { get; set; }

        [Parameter("Bullish Color", DefaultValue = Colors.Green, Group = "Base Settings")]
        public Colors BullishColor { get; set; }

        //[Parameter("Show Label", DefaultValue = false, Group = "Base Settings")]
        //public bool ShowLabel { get; set; }

        [Parameter("Bearish Icon", DefaultValue = ChartIconType.DownArrow, Group = "Base Settings")]
        public ChartIconType BearishIcon { get; set; }

        [Parameter("Bullish Icon", DefaultValue = ChartIconType.UpArrow, Group = "Base Settings")]
        public ChartIconType BullishIcon { get; set; }

        [Parameter("Alert Method", DefaultValue = AlertType.None, Group = "Base Settings")]
        public AlertType AlertMethod { get; set; }

        [Parameter("Alert Email", Group = "Base Settings")]
        public string AlertEmail { get; set; }


        [Parameter("Use Custom Settings", DefaultValue = false, Group = "Custom Settings")]
        public bool UseCustomSettings { get; set; }

        /// <summary>
        /// How many candle need to be calculate for left room candle
        /// </summary>
        [Parameter("CustomCalLeftRoomCandle", DefaultValue = 1000, Group = "Custom Settings")]
        public int CustomCalLeftRoomCandle { get; set; }

        /// <summary>
        /// How many candle need to be calculate for left room candle
        /// </summary>
        [Parameter("CustomLeftRoomLength(%)", DefaultValue = 25, Group = "Custom Settings")]
        public double CustomLeftRoomLength { get; set; }

        /// <summary>
        /// Max. Body / Candle length ratio of the Nose Bar
        /// </summary>
        [Parameter("CustomMaxNoseBodySize", DefaultValue = 0.33, Group = "Custom Settings")]
        public double CustomMaxNoseBodySize { get; set; }

        /// <summary>
        /// Body position in Nose Bar (e.g. top/bottom 40%)
        /// </summary>
        [Parameter("CustomNoseBodyPosition", DefaultValue = 0.4, Group = "Custom Settings")]
        public double CustomNoseBodyPosition { get; set; }
        /// <summary>
        /// true = Direction of Left Eye Bar should be opposite to pattern (bearish bar for bullish Pinbar pattern and vice versa)
        /// </summary>
        [Parameter("CustomLeftEyeOppositeDirection", DefaultValue = true, Group = "Custom Settings")]
        public bool CustomLeftEyeOppositeDirection { get; set; }
        /// <summary>
        /// true = Direction of Nose Bar should be the same as of pattern (bullish bar for bullish Pinbar pattern and vice versa)
        /// </summary>
        [Parameter("CustomNoseSameDirection", DefaultValue = false, Group = "Custom Settings")]
        public bool CustomNoseSameDirection { get; set; }
        /// <summary>
        /// true = Nose Body should be contained inside Left Eye Body
        /// </summary>
        [Parameter("CustomNoseBodyInsideLeftEyeBody", DefaultValue = false, Group = "Custom Settings")]
        public bool CustomNoseBodyInsideLeftEyeBody { get; set; }
        /// <summary>
        /// Min. Body / Candle length ratio of the Left Eye Bar
        /// </summary>
        [Parameter("CustomLeftEyeMinBodySize", DefaultValue = 0.1, Group = "Custom Settings")]
        public double CustomLeftEyeMinBodySize { get; set; }
        /// <summary>
        /// Minmum protrusion of Nose Bar compared to Nose Bar length
        /// </summary>
        [Parameter("CustomNoseProtruding", DefaultValue = 0.5, Group = "Custom Settings")]
        public double CustomNoseProtruding { get; set; }
        /// <summary>
        /// Maximum relative size of the Nose Bar Body to Left Eye Bar Body
        /// </summary>
        [Parameter("CustomNoseBodyToLeftEyeBody", DefaultValue = 1, Group = "Custom Settings")]
        public double CustomNoseBodyToLeftEyeBody { get; set; }
        /// <summary>
        /// Minimum relative size of the Nose Bar Length to Left Eye Bar Length
        /// </summary>
        [Parameter("CustomNoseLengthToLeftEyeLength", DefaultValue = 0, Group = "Custom Settings")]
        public double CustomNoseLengthToLeftEyeLength { get; set; }
        /// <summary>
        /// Minimum relative depth of the Left Eye to its length; depth is difference with Nose's back
        /// </summary>
        [Parameter("CustomLeftEyeDepth", DefaultValue = 0.1, Group = "Custom Settings")]
        public double CustomLeftEyeDepth { get; set; }



        // Global variables
        double MaxNoseBodySize = 0.33;
        double NoseBodyPosition = 0.4;
        bool LeftEyeOppositeDirection = true;
        bool NoseSameDirection = false;
        bool NoseBodyInsideLeftEyeBody = false;
        double LeftEyeMinBodySize = 0.1;
        double NoseProtruding = 0.5;
        double NoseBodyToLeftEyeBody = 1;
        double NoseLengthToLeftEyeLength = 0;
        double LeftEyeDepth = 0.2;
        int CalLeftRoomCandle = 1000;
        double LeftRoomLength = 25;

        private double offset;

        protected override void Initialize()
        {
            // Initialize and create nested indicators
            offset = Symbol.PipSize * 5;


            if (UseCustomSettings)
            {
                MaxNoseBodySize = CustomMaxNoseBodySize;
                NoseBodyPosition = CustomNoseBodyPosition;
                LeftEyeOppositeDirection = CustomLeftEyeOppositeDirection;
                NoseSameDirection = CustomNoseSameDirection;
                LeftEyeMinBodySize = CustomLeftEyeMinBodySize;
                NoseProtruding = CustomNoseProtruding;
                NoseBodyToLeftEyeBody = CustomNoseBodyToLeftEyeBody;
                NoseLengthToLeftEyeLength = CustomNoseLengthToLeftEyeLength;
                LeftEyeDepth = CustomLeftEyeDepth;
                CalLeftRoomCandle = CustomCalLeftRoomCandle;
                LeftRoomLength = CustomLeftRoomLength;
            }
        }

        public override void Calculate(int index)
        {
            double NoseLength, NoseBody, LeftEyeBody, LeftEyeLength;

            int i = index;
            if (i > 0)
            {
                // Left Eye and Nose bars's paramaters.
                NoseLength = Bars[i].High - Bars[i].Low;
                if (NoseLength == 0)
                    NoseLength = Symbol.PipValue;
                LeftEyeLength = Bars[i - 1].High - Bars[i - 1].Low;
                if (LeftEyeLength == 0)
                    LeftEyeLength = Symbol.PipValue;
                NoseBody = Math.Abs(Bars[i].Open - Bars[i].Close);
                if (NoseBody == 0)
                    NoseBody = Symbol.PipValue;
                LeftEyeBody = Math.Abs(Bars[i - 1].Open - Bars[i - 1].Close);
                if (LeftEyeBody == 0)
                    LeftEyeBody = Symbol.PipValue;


                #region Bearish Pinbar
                // Nose protrusion
                if (Bars[i].High - Bars[i - 1].High >= NoseLength * NoseProtruding)
                {
                    // Nose body to candle length ratio
                    if (NoseBody / NoseLength <= MaxNoseBodySize)
                    {
                        // Nose body position in bottom part of the bar
                        if (1 - (Bars[i].High - Math.Max(Bars[i].Open, Bars[i].Close)) / NoseLength < NoseBodyPosition)
                        {
                            // Left Eye bullish if required
                            if ((!LeftEyeOppositeDirection) || (Bars[i - 1].Close > Bars[i - 1].Open))
                            {
                                // Nose bearish if required
                                if ((!NoseSameDirection) || (Bars[i].Close < Bars[i].Open))
                                {
                                    // Left eye body to candle length ratio
                                    if (LeftEyeBody / LeftEyeLength >= LeftEyeMinBodySize)
                                    {
                                        // Nose body inside Left Eye bar
                                        if ((Math.Max(Bars[i].Open, Bars[i].Close) <= Bars[i - 1].High) && (Math.Min(Bars[i].Open, Bars[i].Close) >= Bars[i - 1].Low))
                                        {
                                            // Nose body to Left Eye body ratio
                                            if (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody)
                                            {
                                                // Nose length to Left Eye length ratio
                                                if (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength)
                                                {
                                                    // Left Eye low is low enough
                                                    if (Bars[i].Low - Bars[i - 1].Low >= LeftEyeLength * LeftEyeDepth)
                                                    {
                                                        // Nose body inside Left Eye body if required
                                                        if ((!NoseBodyInsideLeftEyeBody) || ((Math.Max(Bars[i].Open, Bars[i].Close) <= Math.Max(Bars[i - 1].Open, Bars[i - 1].Close)) && (Math.Min(Bars[i - 1].Open, Bars[i].Close) >= Math.Min(Bars[i - 1].Open, Bars[i - 1].Close))))
                                                        {
                                                            //Find the Bearish PinBar
                                                            var distance = GetDistance(i, true);
                                                            var pbPosition = Bars[i].High + distance * Symbol.PipValue + NoseLength / 5;
                                                            Chart.DrawIcon("BearishPB_" + i, BearishIcon, i, pbPosition, Color.FromName(BearishColor.ToString()));

                                                            var leftRoomCandles = GetLeftRoomCandle(i, NoseLength, true);

                                                            //if (ShowLabel)
                                                            Chart.DrawText("Label_BearishPB_" + i, leftRoomCandles.ToString(), i - 1, pbPosition + distance * 5 * Symbol.PipValue, Color.FromName(BearishColor.ToString()));


                                                            if (AlertMethod == AlertType.Sound)
                                                            {
                                                                Notifications.PlaySound("alert.wav");
                                                            }
                                                            else if (AlertMethod == AlertType.Email && !string.IsNullOrEmpty(AlertEmail))
                                                            {
                                                                Notifications.SendEmail(AlertEmail, AlertEmail, string.Format("Bearish PinBar in {0} {1}", Symbol.Name, TimeFrame), string.Format("There is a bearish PinBar in {0} {1}", Symbol.Name, TimeFrame));
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion

                #region Bullish Pinbar
                // Nose protrusion
                if (Bars[i - 1].Low - Bars[i].Low >= NoseLength * NoseProtruding)
                {
                    // Nose body to candle length ratio
                    if (NoseBody / NoseLength <= MaxNoseBodySize)
                    {
                        // Nose body position in top part of the bar
                        if (1 - (Math.Min(Bars[i].Open, Bars[i].Close) - Bars[i].Low) / NoseLength < NoseBodyPosition)
                        {
                            // Left Eye bearish if required
                            if ((!LeftEyeOppositeDirection) || (Bars[i - 1].Close < Bars[i - 1].Open))
                            {
                                // Nose bullish if required
                                if ((!NoseSameDirection) || (Bars[i].Close > Bars[i].Open))
                                {
                                    // Left eye body to candle length ratio
                                    if (LeftEyeBody / LeftEyeLength >= LeftEyeMinBodySize)
                                    {
                                        // Nose body inside Left Eye bar
                                        if ((Math.Max(Bars[i].Open, Bars[i].Close) <= Bars[i - 1].High) && (Math.Min(Bars[i].Open, Bars[i].Close) >= Bars[i - 1].Low))
                                        {
                                            // Nose body to Left Eye body ratio
                                            if (NoseBody / LeftEyeBody <= NoseBodyToLeftEyeBody)
                                            {
                                                // Nose length to Left Eye length ratio
                                                if (NoseLength / LeftEyeLength >= NoseLengthToLeftEyeLength)
                                                {
                                                    // Left Eye high is high enough
                                                    if (Bars[i - 1].High - Bars[i].High >= LeftEyeLength * LeftEyeDepth)
                                                    {
                                                        // Nose body inside Left Eye body if required
                                                        if ((!NoseBodyInsideLeftEyeBody) || ((Math.Max(Bars[i].Open, Bars[i].Close) <= Math.Max(Bars[i - 1].Open, Bars[i - 1].Close)) && (Math.Min(Bars[i].Open, Bars[i].Close) >= Math.Min(Bars[i - 1].Open, Bars[i - 1].Close))))
                                                        {
                                                            //find the Bullish Pinbar
                                                            var distance = GetDistance(i, false);
                                                            var pbPosition = Bars[i].Low - distance * Symbol.PipValue - NoseLength / 5;
                                                            Chart.DrawIcon("BullishPB_" + i, BullishIcon, i, pbPosition, Color.FromName(BullishColor.ToString()));

                                                            var leftRoomCandles = GetLeftRoomCandle(i, NoseLength, false);

                                                            //if (ShowLabel)
                                                            Chart.DrawText("Label_BullishPB_" + i, leftRoomCandles.ToString(), i - 1, pbPosition - distance * Symbol.PipValue, Color.FromName(BullishColor.ToString()));

                                                            if (AlertMethod == AlertType.Sound)
                                                            {
                                                                Notifications.PlaySound("alert.wav");
                                                            }
                                                            else if (AlertMethod == AlertType.Email && !string.IsNullOrEmpty(AlertEmail))
                                                            {
                                                                Notifications.SendEmail(AlertEmail, AlertEmail, string.Format("Bullish PinBar in {0} {1}", Symbol.Name, TimeFrame), string.Format("There is a bullish PinBar in {0} {1}", Symbol.Name, TimeFrame));
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                #endregion
            }
        }

        private double GetDistance(int index, bool isBearish)
        {
            var high = Bars[index].High;
            var low = Bars[index].Low;

            double h_y = high + offset;
            double h_d_y = h_y + offset * 2.5;

            double l_y = low - offset;
            double l_d_y = l_y - offset * 2.5;


            if (TimeFrame == TimeFrame.Minute)
            {
                h_y = high + offset / 2;
                h_d_y = h_y + offset / 2;

                l_y = low - offset / 2;
                l_d_y = l_y - offset / 2;
            }

            if (TimeFrame == TimeFrame.Minute15)
            {
                h_y = high + offset * 1.5;
                h_d_y = h_y + offset * 1.1;

                l_y = low - offset * 1.5;
                l_d_y = l_y - offset * 1.1;
            }


            if (TimeFrame == TimeFrame.Hour)
            {
                h_y = high + offset * 3;
                h_d_y = h_y + offset * 3;

                l_y = low - offset * 3;
                l_d_y = l_y - offset * 3;
            }

            if (TimeFrame == TimeFrame.Hour4)
            {
                h_y = high + offset * 5;
                h_d_y = h_y + offset * 5;

                l_y = low - offset * 5;
                l_d_y = l_y - offset * 5;
            }

            if (TimeFrame == TimeFrame.Daily)
            {
                h_y = high + offset * 3;
                h_d_y = h_y + offset * 12;

                l_y = low - offset * 12;
                l_d_y = l_y - offset * 12;
            }

            if (TimeFrame == TimeFrame.Weekly)
            {
                h_y = high + offset * 6;
                h_d_y = h_y + offset * 24;

                l_y = low - offset * 24;
                l_d_y = l_y - offset * 24;
            }

            if (TimeFrame == TimeFrame.Monthly)
            {
                h_y = high + offset * 24;
                h_d_y = h_y + offset * 64;

                l_y = low - offset * 64;
                l_d_y = l_y - offset * 64;
            }


            return isBearish ? h_d_y : l_d_y;
        }

        private int GetLeftRoomCandle(int index, double noseLength, bool isBearish)
        {
            int result = 0;

            noseLength = noseLength * (LeftRoomLength / 100);
            //default get 25% length
            if (index > CalLeftRoomCandle)
            {
                var counter = 0;
                for (var i = index - 1; i > 0; i--)
                {
                    double diff = 0;
                    if (isBearish)
                    {
                        diff = Bars[index].High - Bars[i].High;
                    }
                    else
                    {
                        diff = Bars[i].Low - Bars[index].Low;
                    }


                    if (diff > noseLength)
                    {
                        result++;
                    }
                    else
                    {
                        break;
                    }

                    counter++;
                    if (counter >= CalLeftRoomCandle)
                    {
                        break;
                    }
                }
            }

            if (result > 0)
            {
                result++;
            }

            return result;
        }
    }
}


WI
winsonet

Joined on 03.01.2021

  • Distribution: Free
  • Language: C#
  • Trading platform: cTrader Automate
  • File name: PinBarDetector.algo
  • Rating: 5
  • Installs: 2885
  • Modified: 13/10/2021 09:55
Comments
Log in to add a comment.
HO
howyg1 · 3 years ago

Very nice indicator thanks

WI
winsonet · 3 years ago

Hi Symposium, 

Thanks for your suggestion, I have updated the indicator to show the left room candles!  :)

Symposium's avatar
Symposium · 3 years ago

Hi Winsonet, nice bit of coding for a very popular and successful strategy. Is there a possibility you could add a parameter (and logic) to define the amount of "room to the left" (in candles) prior to a Bullish or Bearish signal.

Most Pin Bar/Price Action strategies similar to yours define a clearance (no tail - no body) of somewhere between 4-7 candles prior to signal.... I hope this makes sense? See a link to the description below.

https://www.youtube.com/watch?v=zlYvfZ3XSiA&t=245s

Cheers