172 lines
4.9 KiB
MQL5
172 lines
4.9 KiB
MQL5
//+------------------------------------------------------------------+
| |
//| Fractal.mq5 |
| |
//| Copyright 2025, MetaQuotes Ltd. |
| |
//| https://www.mql5.com |
| |
//+------------------------------------------------------------------+
| |
#property copyright "Copyright 2025, MetaQuotes Ltd."
| |
#property link "https://www.mql5.com"
| |
#property version "1.00"
| |
#property indicator_chart_window
| |
#property copyright "2025"
| |
#property version "1.40"
| |
#property indicator_chart_window
| |
#property indicator_plots 2
| |
#property indicator_buffers 2
| |
| |
//--- Swing High
| |
#property indicator_label1 "SwingHigh"
| |
#property indicator_type1 DRAW_ARROW
| |
#property indicator_color1 clrCrimson
| |
#property indicator_width1 1
| |
| |
//--- Swing Low
| |
#property indicator_label2 "SwingLow"
| |
#property indicator_type2 DRAW_ARROW
| |
#property indicator_color2 clrMediumSeaGreen
| |
#property indicator_width2 1
| |
| |
input int InpLeftRightBars = 3; // swing detection size
| |
input int InpLeftRightBars0 = 1; // between-point minimum swing size
| |
| |
input ushort code = 170; // Arrow symbol
| |
| |
double SwingHighBuffer[];
| |
double SwingLowBuffer[];
| |
| |
int lastHighIndex = -1;
| |
int lastLowIndex = -1;
| |
| |
datetime last_bar_time = 0;
| |
| |
//------------------------------------------------------------
| |
inline bool IsSwingHigh_L(const double &high[], int i, int L)
| |
{
| |
for(int j = 1; j <= L; j++)
| |
if(high[i] <= high[i - j] || high[i] <= high[i + j]) return false;
| |
return true;
| |
}
| |
//------------------------------------------------------------
| |
inline bool IsSwingLow_L(const double &low[], int i, int L)
| |
{
| |
for(int j = 1; j <= L; j++)
| |
if(low[i] >= low[i - j] || low[i] >= low[i + j]) return false;
| |
return true;
| |
}
| |
//------------------------------------------------------------
| |
int OnInit()
| |
{
| |
SetIndexBuffer(0, SwingHighBuffer, INDICATOR_DATA);
| |
SetIndexBuffer(1, SwingLowBuffer, INDICATOR_DATA);
| |
| |
ArrayInitialize(SwingHighBuffer, 0.0);
| |
ArrayInitialize(SwingLowBuffer, 0.0);
| |
| |
PlotIndexSetInteger(0, PLOT_ARROW, code);
| |
PlotIndexSetInteger(1, PLOT_ARROW, code);
| |
| |
return(INIT_SUCCEEDED);
| |
}
| |
//------------------------------------------------------------
| |
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[])
| |
{
| |
if(rates_total < InpLeftRightBars*2 + 1)
| |
return 0;
| |
| |
if(rates_total > 0 && time[rates_total - 1] == last_bar_time)
| |
return rates_total;
| |
| |
ArrayInitialize(SwingHighBuffer, 0.0);
| |
ArrayInitialize(SwingLowBuffer, 0.0);
| |
| |
lastHighIndex = -1;
| |
lastLowIndex = -1;
| |
| |
int start = InpLeftRightBars;
| |
int end = rates_total - 1 - InpLeftRightBars;
| |
| |
for(int i = start; i <= end; i++)
| |
{
| |
bool isHigh = IsSwingHigh_L(high, i, InpLeftRightBars);
| |
bool isLow = IsSwingLow_L(low, i, InpLeftRightBars);
| |
| |
// --- Swing High ---
| |
if(isHigh)
| |
{
| |
SwingHighBuffer[i] = high[i];
| |
| |
if(lastHighIndex != -1 && lastHighIndex > lastLowIndex)
| |
{
| |
int a = lastHighIndex;
| |
int b = i;
| |
if(a > b) { int tmp = a; a = b; b = tmp; }
| |
| |
double minVal = DBL_MAX;
| |
int minIndex = -1;
| |
| |
for(int k = a + 1; k < b; k++)
| |
{
| |
// only consider swing lows with L = InpLeftRightBars0
| |
if(IsSwingLow_L(low, k, InpLeftRightBars0))
| |
{
| |
if(low[k] < minVal)
| |
{
| |
minVal = low[k];
| |
minIndex = k;
| |
}
| |
}
| |
}
| |
| |
if(minIndex != -1)
| |
SwingLowBuffer[minIndex] = minVal; // draw in SwingLowBuffer
| |
}
| |
| |
lastHighIndex = i;
| |
}
| |
| |
// --- Swing Low ---
| |
if(isLow)
| |
{
| |
SwingLowBuffer[i] = low[i];
| |
| |
if(lastLowIndex != -1 && lastLowIndex > lastHighIndex)
| |
{
| |
int a = lastLowIndex;
| |
int b = i;
| |
if(a > b) { int tmp = a; a = b; b = tmp; }
| |
| |
double maxVal = -DBL_MAX;
| |
int maxIndex = -1;
| |
| |
for(int k = a + 1; k < b; k++)
| |
{
| |
// only consider swing highs with L = InpLeftRightBars0
| |
if(IsSwingHigh_L(high, k, InpLeftRightBars0))
| |
{
| |
if(high[k] > maxVal)
| |
{
| |
maxVal = high[k];
| |
maxIndex = k;
| |
}
| |
}
| |
}
| |
| |
if(maxIndex != -1)
| |
SwingHighBuffer[maxIndex] = maxVal; // draw in SwingHighBuffer
| |
}
| |
| |
lastLowIndex = i;
| |
}
| |
}
| |
| |
last_bar_time = time[rates_total - 1];
| |
return rates_total;
| |
}
|