pin
Download scriptThis script is designed to identify specific types of candlestick patterns known as "Pin Bars" on a trading chart. It automatically scans historical price data and places visual markers (arrows) on the chart to highlight these potential trading signals for users.
Core Functionality
The tool focuses on identifying price action where the "tail" or "wick" of a candle is significantly longer than the "body." It looks for two distinct types of movement:
- Bearish Rejection (PinUp): These are identified when a price moves upward but fails to sustain that momentum, resulting in a long upper wick and a small body near the bottom of the candle's range. The script marks these with red arrows.
- Bullish Rejection (PinDown): These are identified when a price moves downward but is pushed back up, leaving a long lower wick and a small body near the top of the candle's range. The script marks these with blue arrows.
How the Logic Works
To filter out noise and ensure only high-quality patterns are shown, the script uses several specific rules:
1. Proportional Depth Rather than looking for any wick, the script calculates a "Depth" percentage. It measures the total size of the candle (High to Low) and ensures that the rejection wick constitutes a significant portion of that total range. You can customize this percentage in the settings.
2. Range Constraints To avoid reacting to tiny, insignificant price movements or massive, erratic spikes, the script allows you to set a "Minimum Range" and a "Maximum Range." It will only highlight candles that fall within these specific size boundaries.
3. Extremum Detection (Optional) The script includes a smart filter that can be toggled on or off. When enabled, it checks if the price reached a "Daily High" or "Daily Low." This means the script will prioritize identifying rejection patterns that happen at the very edges of the day's trading range, which are often considered stronger signals by traders.
4. Visual Output Once a candle meets all the criteria (correct depth, within size limits, and optionally at an extreme price point), the script automatically draws an arrow on the chart:
- Sell Arrows (Red): Placed at the high of a bearish rejection candle.
- Buy Arrows (Blue): Placed at the low of a bullish rejection candle.
Summary for the User
This tool automates the tedious process of manually scanning charts for rejection candles. By using your predefined settings for depth and range, it filters the market history to point out specific moments where price action suggests a potential reversal, making it easier to spot high-probability setups at a glance.
//+------------------------------------------------------------------+
//| Pin.mq4 |
//| Copyright 2015, mrak297. |
//| https://www.mql5.com/ru/users/mrak297 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, mrak297."
#property link "https://www.mql5.com/ru/users/mrak297"
#property version "15.08"
#property strict
#property indicator_chart_window
//--- input parameters
input int Depth = 40; //Depth of pinbars in percents
input int MaxRange = 100; //Maximum range
input int MinRange = 20; //Minimum range
input bool Extremum = true; //Only extremum
double Pp;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if (Point() == 0.0001 || Point() == 0.00001) Pp = 0.0001;
if (Point() == 0.01 || Point() == 0.001) Pp = 0.01;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
//---
string name = " ";
for (int i = 1; i < Bars-1; i++)
{
if (PinUp(time[i], open[i], high[i], low[i], close[i], Depth))
{
name = "PinUp"+TimeToString(time[i], TIME_DATE|TIME_MINUTES);
ArrowSellCreate(name, time[i], high[i]);
}
if (PinDown(time[i], open[i], high[i], low[i], close[i], Depth))
{
name = "PinDown"+TimeToString(time[i], TIME_DATE|TIME_MINUTES);
ArrowBuyCreate(name, time[i], low[i]);
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, -1, OBJ_ARROW);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool PinUp(datetime time, double open, double high, double low, double close, int depth)
{
int range = (int)MathRound((high - low)/Pp);
int zone = (int)MathRound(range * depth * 0.01); //////////////////////////////////////
int shift = iBarShift(_Symbol, PERIOD_D1, time, true); // //
double dayHidh = iHigh(_Symbol, PERIOD_D1, shift); // | --| //
double level = NormalizeDouble(low + zone * Pp, _Digits); // | | //
bool check = false; // | | //
// | | //
if (range > MinRange && range < MaxRange) // | | //
{ // | |- range //
if ((Extremum && high == dayHidh) || !Extremum) // | | //
check = true; // --- --|- level | //
if (open <= level && close <= level && check) // | | | | //
{ // | | |-- zone | //
return(true); // --- | | //
} // | --| --| //
} // //
//////////////////////////////////////
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool PinDown(datetime time, double open, double high, double low, double close, int depth)
{
int range = (int)MathRound((high - low)/Pp);
int zone = (int)MathRound(range * depth * 0.01); //////////////////////////////////////
int shift = iBarShift(_Symbol, PERIOD_D1, time, true); // //
double dayLow = iLow(_Symbol, PERIOD_D1, shift); // | --| --| //
double level = NormalizeDouble(high - zone * Pp, _Digits); // --- | | //
bool check = false; // | | |-- zone | //
// | | | | //
if (range > MinRange && range < MaxRange) // --- --|- level | //
{ // | | //
if ((Extremum && low == dayLow) || !Extremum) // | |- range //
check = true; // | | //
if (open >= level && close >= level && check) // | | //
{ // | | //
return(true); // | | //
} // | --| //
} // //
//////////////////////////////////////
return(false);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ArrowSellCreate(string name, datetime time, double price)
{
ResetLastError();
if(ObjectCreate(0,name,OBJ_ARROW_SELL,0,time,price))
{
ObjectSetInteger(0,name,OBJPROP_COLOR,clrTomato);
ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
ObjectSetInteger(0,name,OBJPROP_BACK,true);
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
ObjectSetInteger(0,name,OBJPROP_ZORDER,0);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void ArrowBuyCreate(string name, datetime time, double price)
{
ResetLastError();
if(ObjectCreate(0,name,OBJ_ARROW_BUY,0,time,price))
{
ObjectSetInteger(0,name,OBJPROP_COLOR,clrDodgerBlue);
ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID);
ObjectSetInteger(0,name,OBJPROP_WIDTH,1);
ObjectSetInteger(0,name,OBJPROP_BACK,true);
ObjectSetInteger(0,name,OBJPROP_SELECTABLE,false);
ObjectSetInteger(0,name,OBJPROP_HIDDEN,true);
ObjectSetInteger(0,name,OBJPROP_ZORDER,0);
}
}
//+-----------------------------------------------------------------+
Comments