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.
- CustomNoseBodyPosition (default = 0.4) — Nose body should be positioned in the top (bottom for bearish pattern) part of the Nose bar.
- CustomLeftEyeOppositeDirection (default = true) — tells the indicator that the Left Eye bar should be bearish for bullish Pinbar, and bullish for bearish Pinbar.
- CustomNoseSameDirection (default = true) — tells the indicator that the Nose bar should be of the same direction as the pattern itself.
- CustomNoseBodyInsideLeftEyeBody (default = false) — tells the indicator that the Nose body should be inside the Left Eye body.
- CustomLeftEyeMinBodySize (default = 0.1) — minimum size of the Left Eye body relative to the bar length.
- CustomNoseProtruding (default = 0.5) — minimum protrusion of the Nose bar relative to the bar length.
- CustomNoseBodyToLeftEyeBody (default = 1) — maximum size of the Nose body relative to the Left eye body.
- CustomNoseLengthToLeftEyeLength (default = 0) — minimum Nose length relative to the Left Eye 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.
===================================
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;
}
}
}
winsonet
Joined on 03.01.2021
- Distribution: Free
- Language: C#
- Trading platform: cTrader Automate
- File name: PinBarDetector.algo
- Rating: 5
- Installs: 2840
- Modified: 13/10/2021 09:55
Comments
Hi Symposium,
Thanks for your suggestion, I have updated the indicator to show the left room candles! :)
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
Very nice indicator thanks