MQL5Book/Indicators/p5/UseWPRFractals.mq5
super.admin 1c8e83ce31 convert
2025-05-30 16:09:41 +02:00

182 lines
5.8 KiB
MQL5

//+------------------------------------------------------------------+
//| UseWPRFractals.mq5 |
//| Copyright 2021, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots 3
// drawing settings
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrRed
#property indicator_width1 1
#property indicator_label1 "Sell"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrBlue
#property indicator_width2 1
#property indicator_label2 "Buy"
#property indicator_type3 DRAW_NONE
#property indicator_color3 clrGreen
#property indicator_width3 1
#property indicator_label3 "Filter"
// inputs
input int PeriodWPR = 11;
input int PeriodEMA = 5;
input int FractalOrder = 1;
input int Offset = 0;
input double Threshold = 0.2;
// indicator buffers
double UpBuffer[]; // up side means overbought, hence sell
double DownBuffer[]; // down side means oversold, hence buy
double Filter[]; // direction filter according to fractals
// global variables for subordinate indicators
int handleWPR, handleEMA3, handleFractals;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
if(Offset < 0 || Offset > 1)
{
Alert("Offset should take index for signal bar: 0 or 1");
return INIT_PARAMETERS_INCORRECT;
}
// indicator buffers mapping
SetIndexBuffer(0, UpBuffer);
SetIndexBuffer(1, DownBuffer);
SetIndexBuffer(2, Filter, INDICATOR_DATA); // could be INDICATOR_CALCULATIONS
ArraySetAsSeries(UpBuffer, true);
ArraySetAsSeries(DownBuffer, true);
ArraySetAsSeries(Filter, true);
// set bullets
PlotIndexSetInteger(0, PLOT_ARROW, 234);
PlotIndexSetInteger(1, PLOT_ARROW, 233);
// subordinate indicators
handleWPR = iCustom(_Symbol, _Period, "IndWPR", PeriodWPR);
handleEMA3 = iCustom(_Symbol, _Period, "IndTripleEMA", PeriodEMA, 0, handleWPR);
handleFractals = iCustom(_Symbol, _Period, "IndFractals", FractalOrder);
if(handleWPR == INVALID_HANDLE
|| handleEMA3 == INVALID_HANDLE
|| handleFractals == INVALID_HANDLE)
{
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Read indicator buffers and make decision for trade signals |
//+------------------------------------------------------------------+
int MarkSignals(const int bar, const int offset, const double &data[])
{
double wpr[2];
double peaks[1], hollows[1];
if(CopyBuffer(handleEMA3, 0, bar + offset, 2, wpr) == 2
&& CopyBuffer(handleFractals, 0, bar + offset + FractalOrder, 1, peaks) == 1
&& CopyBuffer(handleFractals, 1, bar + offset + FractalOrder, 1, hollows) == 1)
{
int filterdirection = (int)Filter[bar + 1]; // pick up previous direction
// take latest fractal as indication of beginning of opposite movement
if(peaks[0] != EMPTY_VALUE)
{
filterdirection = -1; // sell
}
if(hollows[0] != EMPTY_VALUE)
{
filterdirection = +1; // buy
}
Filter[bar] = filterdirection; // remember new direction
// convert 2 last values from WPR into [-1,+1] range
const double old = (wpr[0] + 50) / 50; // +1.0 -1.0
const double last = (wpr[1] + 50) / 50; // +1.0 -1.0
// bumps from up back to middle
if(filterdirection == -1
&& old >= 1.0 - Threshold && last <= 1.0 - Threshold)
{
UpBuffer[bar] = data[bar];
return -1; // sell
}
else
{
UpBuffer[bar] = EMPTY_VALUE;
}
// bumps from down back to middle
if(filterdirection == +1
&& old <= -1.0 + Threshold && last >= -1.0 + Threshold)
{
DownBuffer[bar] = data[bar];
return +1; // buy
}
else
{
DownBuffer[bar] = EMPTY_VALUE;
}
}
return 0; // no signal
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const int begin,
const double &data[])
{
// wait until the subindicators are calculated for all bars
if(BarsCalculated(handleEMA3) != rates_total
|| BarsCalculated(handleFractals) != rates_total)
{
return prev_calculated;
}
ArraySetAsSeries(data, true);
if(prev_calculated == 0)
{
ArrayInitialize(UpBuffer, EMPTY_VALUE);
ArrayInitialize(DownBuffer, EMPTY_VALUE);
ArrayInitialize(Filter, 0);
// find signals on history
for(int i = rates_total - FractalOrder - 1; i >= 0; --i)
{
MarkSignals(i, Offset, data);
}
}
else
{
for(int i = 0; i < rates_total - prev_calculated; ++i)
{
UpBuffer[i] = EMPTY_VALUE;
DownBuffer[i] = EMPTY_VALUE;
Filter[i] = 0;
}
// find signals on new bar or on every tick (if Offset == 0)
if(rates_total != prev_calculated
|| Offset == 0)
{
// copy data from subordinate indicators into our buffer
MarkSignals(0, Offset, data);
}
}
return rates_total;
}
//+------------------------------------------------------------------+