172 строки
4,9 КиБ
MQL5
172 строки
4,9 КиБ
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;
| |||
}
|