//+------------------------------------------------------------------+
//| pine_sample_div.mq5 |
//| Copyright 2022, MetaQuotes Ltd. |
//| https://www.mql5.com |
//| Author: Yashar Seyyedin |
//| Web Address: https://www.mql5.com/en/users/yashar.seyyedin |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 9
#property indicator_plots 2
//--- plot regular_bearish_div
#property indicator_label1 "regular_bearish_div"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrOrangeRed
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- plot regular_bullish_div
#property indicator_label2 "regular_bullish_div"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrLimeGreen
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//---input parameters
input int stoch_len = 5;
//--- indicator buffers
double regular_bearish_divBuffer[];
double regular_bullish_divBuffer[];
double stochBuffer[];
double fractal_topBuffer[];
double fractal_botBuffer[];
double high_prevBuffer[];
double high_priceBuffer[];
double low_prevBuffer[];
double low_priceBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,regular_bearish_divBuffer,INDICATOR_DATA);
SetIndexBuffer(1,regular_bullish_divBuffer,INDICATOR_DATA);
SetIndexBuffer(2,stochBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,fractal_topBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,fractal_botBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(5,high_prevBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(6,high_priceBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(7,low_prevBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(8,low_priceBuffer,INDICATOR_CALCULATIONS);
PlotIndexSetInteger(0, PLOT_ARROW, 159);
PlotIndexSetInteger(1, PLOT_ARROW, 159);
PlotIndexSetInteger(0, PLOT_SHIFT, -2);
PlotIndexSetInteger(1, PLOT_SHIFT, -2);
ArraySetAsSeries(regular_bearish_divBuffer,true);
ArraySetAsSeries(regular_bullish_divBuffer,true);
ArraySetAsSeries(stochBuffer,true);
ArraySetAsSeries(fractal_topBuffer,true);
ArraySetAsSeries(fractal_botBuffer,true);
ArraySetAsSeries(high_prevBuffer,true);
ArraySetAsSeries(high_priceBuffer,true);
ArraySetAsSeries(low_prevBuffer,true);
ArraySetAsSeries(low_priceBuffer,true);
//---
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[])
{
//---
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(time, true);
int BARS=MathMax(rates_total-prev_calculated-stoch_len,1);
for(int i=BARS;i>=0;i--)
{
stochBuffer[i] = pine_stoch(close, high, low, stoch_len, i);
fractal_topBuffer[i] = f_fractalize(stochBuffer, i) > 0 ? stochBuffer[i+2] : EMPTY_VALUE;
fractal_botBuffer[i] = f_fractalize(stochBuffer, i) < 0 ? stochBuffer[i+2] : EMPTY_VALUE;
int prev_top_index=0;
int prev_bot_index=0;
high_prevBuffer[i] = pine_valuewhen(fractal_topBuffer, stochBuffer, 1, i, rates_total, prev_top_index);
high_priceBuffer[i] = pine_valuewhen(fractal_topBuffer, high, 1, i, rates_total, prev_top_index);
low_prevBuffer[i] = pine_valuewhen(fractal_botBuffer, stochBuffer, 1, i, rates_total, prev_bot_index);
low_priceBuffer[i] = pine_valuewhen(fractal_botBuffer, low, 1, i, rates_total, prev_bot_index);
regular_bearish_divBuffer[i] = (fractal_topBuffer[i]!=EMPTY_VALUE && high[i+2] > high_priceBuffer[i] && stochBuffer[i+2] < high_prevBuffer[i])?high[i+2]:EMPTY_VALUE;
regular_bullish_divBuffer[i] = (fractal_botBuffer[i]!=EMPTY_VALUE && low[i+2] < low_priceBuffer[i] && stochBuffer[i+2] > low_prevBuffer[i])?low[i+2]:EMPTY_VALUE;
if(regular_bearish_divBuffer[i]!=EMPTY_VALUE)
{
PlotText(time[i+2], high[i+2], "R", clrOrangeRed, ANCHOR_LOWER);
PlotLine(time[prev_top_index+2], time[i+2], high[prev_top_index+2], high[i+2], clrOrangeRed);
}
if(regular_bullish_divBuffer[i]!=EMPTY_VALUE)
{
PlotText(time[i+2], low[i+2], "R", clrLimeGreen, ANCHOR_UPPER);
PlotLine(time[prev_bot_index+2], time[i+2], low[prev_bot_index+2], low[i+2], clrLimeGreen);
}
}
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double pine_stoch(const double &source[], const double &high[], const double &low[], int length, int index)
{
return 100 * (source[index] - pine_lowest(low, length, index)) / (pine_highest(high, length, index) - pine_lowest(low, length, index));
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double pine_highest(const double &_src[], int len, int i)
{
return _src[ArrayMaximum(_src, i, len)];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double pine_lowest(const double &_src[], int len, int i)
{
return _src[ArrayMinimum(_src, i, len)];
}
//+------------------------------------------------------------------+
// || Functions:
bool f_top_fractal(double &_src[], int index)
{
return _src[index+4] < _src[index+2] && _src[index+3] < _src[index+2] && _src[index+2] > _src[index+1] &&
_src[index+2] > _src[index+0];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool f_bot_fractal(double &_src[], int index)
{
return _src[index+4] > _src[index+2] && _src[index+3] > _src[index+2] && _src[index+2] < _src[index+1] &&
_src[index+2] < _src[index+0];
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double f_fractalize(double &_src[], int index)
{
bool f_bot_fractal__1 = f_bot_fractal(_src, index);
return f_top_fractal(_src, index) ? 1 : f_bot_fractal__1 ? -1 : 0;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
double pine_valuewhen(double &condition[], const double &source[], int occurence, int index, const int rates_total, int &out_index)
{
int counter=-1;
out_index=-1;
for(int i=index;i<rates_total;i++)
{
if(condition[i]!=EMPTY_VALUE)
counter++;
if(counter==occurence)
{
out_index=i;
return source[i+2];
}
}
return EMPTY_VALUE;
}
string prefix="Div_";
void PlotText(datetime time, double price, string text, color col, ENUM_ANCHOR_POINT anchor)
{
string name = prefix +TimeToString(time);
ObjectCreate(0, name, OBJ_TEXT, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetString(0, name, OBJPROP_TEXT, text);
ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 14);
ObjectSetInteger(0, name, OBJPROP_ANCHOR, anchor);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void PlotLine(datetime time1, datetime time2, double prev, double price, color col)
{
string name = prefix +"_LINE_"+TimeToString(time1);
ObjectCreate(0, name, OBJ_TREND, 0, time1, prev, time2, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, col);
ObjectSetInteger(0, name, OBJPROP_RAY_RIGHT, false);
ObjectSetInteger(0, name, OBJPROP_RAY_LEFT, false);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
ObjectsDeleteAll(0, prefix);
}
//+------------------------------------------------------------------+
Comments