FractFactory/FractFactory.mq5
super.admin 74d076ce2a convert
2025-05-30 14:56:16 +02:00

1030 lines
83 KiB
MQL5

//+------------------------------------------------------------------+
//| FractFactory.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include "Structures.mqh"
enum ENUM_FRACTAL_CANDELS
{
FRACTAL_CANDELS_THREE = 3,
FRACTAL_CANDELS_FIVE = 5
};
input ENUM_TIMEFRAMES inGlobalFrame = PERIOD_H4;
input ENUM_TIMEFRAMES inLocalFrame = PERIOD_M15;
input ENUM_FRACTAL_CANDELS inLevelFractal = FRACTAL_CANDELS_FIVE;
input ENUM_FRACTAL_CANDELS inBackFractal = FRACTAL_CANDELS_FIVE;
SLevels htf_global,htf_uncor, htf_local;
SFractal globalPreInternal;
datetime globalT = 0,localT = 0;
const int shift = 2;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
if(inGlobalFrame <= inLocalFrame)
{
::Alert("Global and Local timeframes have to be different");
return INIT_PARAMETERS_INCORRECT;
}
SDirection trend;
SetStartPoint(PERIOD_W1,trend);
SetHTFLevels(inGlobalFrame,trend,htf_global, htf_uncor, htf_local);
//::Print("*****");
//::Print("М15");
//double point = globalLevels._strongExternal;
//ENUM_TENDENTION direction = globalLevels._tendentionExternal;
//SetLevels(inLocalFrame,point,direction,localLevels);
/*trend._end = globalLevels._strongInternal;
trend._endIndex = globalLevels._siIndex;
trend._endTime = globalLevels._siTime;
trend._start = globalLevels._weakInternal;
trend._startIndex = globalLevels._wiIndex;
trend._startTime = globalLevels._wiTime;
if(globalLevels._tendentionInternal == TENDENTION_UP)
trend._trend = TENDENTION_DOWN;
else
trend._trend = TENDENTION_UP;*/
//ZeroMemory(trend);
//SetStartPoint(inGlobalFrame,trend);
//SetLevels(inLocalFrame,trend,localLevels);
// SetLTFLevels(inLocalFrame,localLevels);
localT = ::iTime(_Symbol,inLocalFrame,0);
globalT = ::iTime(_Symbol,inGlobalFrame,0);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
if(globalT == ::iTime(_Symbol,inGlobalFrame,0))
return;
globalT = ::iTime(_Symbol,inGlobalFrame,0);
//-------------------------------------------------------
if(localT == ::iTime(_Symbol,inLocalFrame,0))
return;
localT = ::iTime(_Symbol,inLocalFrame,0);
//---
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SetStartPoint(const ENUM_TIMEFRAMES tf,SDirection &trend)
{
SFractal hFract,lFract;
//ENUM_TIMEFRAMES tf = PERIOD_W1;
GetExpantionUp(hFract,tf);
GetExpantionDn(lFract,tf);
if(hFract._index < lFract._index)
{
trend._trend = TENDENTION_DOWN;
trend._market_phase = MARKET_PHASE_CORRECTION;
trend._start = hFract._value;
trend._startIndex = hFract._index;
trend._startTime = hFract._time;
Print("EXT_TREND_DOWN. Точка начала определения уровней = ",trend._startTime);
}
else
if(hFract._index > lFract._index)
{
trend._trend = TENDENTION_UP;
trend._market_phase = MARKET_PHASE_CORRECTION;
trend._start = lFract._value;
trend._startIndex = lFract._index;
trend._startTime = lFract._time;
Print("EXT_TREND_UP. Точка начала определения уровней = ",trend._startTime," c отметки = ", trend._start);
}
::Print("*****");
::Print("Ситуация на ");
::Print(EnumToString(tf));
::Print(":");
trend.Print(_Digits);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool FractalDown(const int index,const ENUM_TIMEFRAMES tf)
{
double ctrl_low = ::iLow(_Symbol,tf,index);
for(int i = index + 1;i <= index + shift;i++)
if(::iLow(_Symbol,tf,i) <= ctrl_low)
return false;
for(int i = index - 1;i >= index - shift;i--)
if(::iLow(_Symbol,tf,i) <= ctrl_low)
return false;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool FractalUp(const int index,const ENUM_TIMEFRAMES tf)
{
double ctrl_high = ::iHigh(_Symbol,tf,index);
for(int i = index + 1;i <= index + shift;i++)
if(::iHigh(_Symbol,tf,i) >= ctrl_high)
return false;
for(int i = index - 1;i >= index - shift;i--)
if(::iHigh(_Symbol,tf,i) >= ctrl_high)
return false;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool FractalDown(const int index,const int t_shift,const ENUM_TIMEFRAMES tf)
{
double ctrl_low = ::iLow(_Symbol,tf,index);
for(int i = index + 1;i <= index + t_shift;i++)
if(::iLow(_Symbol,tf,i) <= ctrl_low)
return false;
for(int i = index - 1;i >= index - t_shift;i--)
if(::iLow(_Symbol,tf,i) <= ctrl_low)
return false;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool FractalUp(const int index,const int t_shift,const ENUM_TIMEFRAMES tf)
{
double ctrl_high = ::iHigh(_Symbol,tf,index);
for(int i = index + 1;i <= index + t_shift;i++)
if(::iHigh(_Symbol,tf,i) >= ctrl_high)
return false;
for(int i = index - 1;i >= index - t_shift;i--)
if(::iHigh(_Symbol,tf,i) >= ctrl_high)
return false;
return true;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void GetExpantionUp(SFractal &hFract,const ENUM_TIMEFRAMES tf)
{
bool expantion = false;
for(int i = shift + 1;i < iBars(_Symbol,tf);i++)
{
if(FractalUp(i,tf))
{
double extremum = ::iHigh(_Symbol,tf,i);
// выходим из цикла при соблюдении данных условий
if(expantion == true)
if(hFract._value > 0)
if(extremum > hFract._value || extremum < iClose(_Symbol,tf,hFract._index))
{
// Print("Цикл поиска расширения в вверх завершен");
break;
}
if(hFract._value == 0 || extremum > hFract._value)
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = true;
//Print("FractalUp. Первая скобка = ", hFract._value);
}
else
if(hFract._value > 0 && extremum < hFract._value)
{
// Проверяем было ли ранее зафиксировано расширение, на предмет ложного пробоя, если да, переносим на текущий фрактал
if(expantion == true && extremum > iClose(_Symbol,tf,hFract._index))
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
expantion = true;
//Print("FractalUp. перенос за ложный пробой = ", hFract._value,", фиксируем расширение = ", expantion);
}
int range = ::MathAbs(i - hFract._index);
int index;
double close;
int opIndex = ::iHighest(_Symbol,tf,MODE_OPEN,range,hFract._index - shift);
int clIndex = ::iHighest(_Symbol,tf,MODE_CLOSE,range,hFract._index - shift);
index = ::MathMax(opIndex,clIndex);
if(index == clIndex)
close = ::iClose(_Symbol,tf,index);
else
close = ::iOpen(_Symbol,tf,index);
if(index <= 0)
continue;
if(close > extremum)
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = true;
expantion = true;
//Print("FractalUp. Вторая скобка = ", hFract._value,", фиксируем расширение = ", expantion);
// break;
}
else
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = true;
//Print("FractalUp. Третья скобка = ", hFract._value);
}
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void GetExpantionDn(SFractal &hFract,const ENUM_TIMEFRAMES tf)
{
bool expantion = false;
//Идем вглубь истории от точки, на которой возможно формирование фрактала
for(int i = shift + 1,size = ::iBars(_Symbol,tf);i < size;i++)
{
//Если нашли фрактал вниз
if(FractalDown(i,tf))
{
//Запоминаем значение фрактала
double extremum = ::iLow(_Symbol,tf,i);
// выходим из цикла при соблюдении данных условий
if(expantion == true)
if(hFract._value > 0)
if(extremum < hFract._value || extremum > iClose(_Symbol,tf,hFract._index))
{
//Print("Цикл поиска расширения в низ завершен");
break;
}
//Если до того ни одного фрактала не найдено, или найденный (текущий) фрактал ниже ранее найденного
if(hFract._value == 0 || extremum < hFract._value)
{
//Запоминаем новый фрактал и идем дальше
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
//Print("FractalDn. Первая скобка = ", hFract._value);
}
else
//Если текущий фрактал выше ранее найденного
if(hFract._value > 0 && extremum > hFract._value)
{
// Проверяем было ли ранее зафиксировано расширение, на предмет ложного пробоя, если да, переносим на текущий фрактал
if(expantion == true && extremum < iClose(_Symbol,tf,hFract._index))
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
expantion = true;
//Print("FractalDn. перенос за ложный пробой = ", hFract._value,", фиксируем расширение = ", expantion);
}
//Посматриваем все свечи между текущим фракталом и ранее найденным
//на предмет пробития телом свечи. Закрытие или открытие должно пробивать
//предыдущий уровень
int range = ::MathAbs(i - hFract._index);
int index;
double close;
int opIndex = ::iLowest(_Symbol,tf,MODE_OPEN,range,hFract._index - shift);
int clIndex = ::iLowest(_Symbol,tf,MODE_CLOSE,range,hFract._index - shift);
index = ::MathMin(opIndex,clIndex);
if(index == clIndex)
close = ::iClose(_Symbol,tf,index);
else
close = ::iOpen(_Symbol,tf,index);
if(index <= 0)
continue;
//Если пробитие зафиксировано - прерываем работу
//Значит текущий фрактал является сильным уровнем для последнего сохраненного
if(close < extremum)
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
expantion = true;
//Print("FractalDn. Вторая скобка = ", hFract._value,", фиксируем расширение = ", expantion);
// break;
}
//Если пробитие телом не зафиксированно - запоминаем текущий фрактал
//и идем дальше
else
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
//Print("FractalDn. Третья скобка = ", hFract._value);
}
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SetHTFLevels(const ENUM_TIMEFRAMES tf,const SDirection &trend, SLevels &global, SLevels &uncor, SLevels &local)
{
int bars = ::iBars(_Symbol,tf);
//+------------------------------------------------------------------+
//| Устанавливаем сильные точки |
//+------------------------------------------------------------------+
for(int i = 0;i < bars;i++)
{
double h = ::iHigh(_Symbol,tf,i);
double l = ::iLow(_Symbol,tf,i);
if(trend._trend == TENDENTION_UP)
{
if(l / _Point == trend._start / _Point)
{
global._strong_min = l;
uncor._strong_min = global._strong_min;
local._strong_min = global._strong_min;
global._s_min_Index = i;
uncor._s_min_Index = global._s_min_Index;
local._s_min_Index = global._s_min_Index;
global._s_min_Time = ::iTime(_Symbol,tf,i);
uncor._s_min_Time = global._s_min_Time;
local._s_min_Time = global._s_min_Time;
global._tendention= TENDENTION_UP;
uncor._tendention= TENDENTION_UP;
local._tendention= TENDENTION_UP;
Print("Устанавливаем сильные экстремумы. TREND UP, global str min = ",global._strong_min, ", uncor str min= ", uncor._strong_min, ", local str min= ", local._strong_min);
break;
}
}
if(trend._trend == TENDENTION_DOWN)
{
if(h / _Point == trend._start / _Point)
{
global._strong_max = h;
uncor._strong_max = global._strong_max;
local._strong_max = global._strong_max;
global._s_max_Index = i;
uncor._s_max_Index = global._s_max_Index;
local._s_max_Index = global._s_max_Index;
global._s_max_Time = ::iTime(_Symbol,tf,i);
uncor._s_max_Time = global._s_max_Time;
local._s_max_Time = global._s_max_Time;
global._tendention= TENDENTION_DOWN;
uncor._tendention= TENDENTION_DOWN;
local._tendention= TENDENTION_DOWN;
Print("Устанавливаем сильные экстремумы. TREND DOWN, global str max = ",global._strong_max, ", uncor str max= ", uncor._strong_max, ", local str max = ", local._strong_max);
break;
}
}
}
int start_index = 0;
if(global._tendention == TENDENTION_DOWN)
start_index = global._s_max_Index;
if(global._tendention == TENDENTION_UP)
start_index = global._s_min_Index;
Print("start_index = ",start_index);
for(int i = start_index - 1; i >= 1; i--)
{
// варианты ветвлений
// UP + UP + CORRECTION(Первая волна анализа).
// DOWN + DOWN + CORRECTION(Первая волна анализа) +
// UP + DOWN + СORRECTION
// DOWN + UP + СORRECTION
// DOWN + DOWN + INMPULS
// UP + UP + IMPULS
if(global._tendention == TENDENTION_DOWN)
if(uncor._tendention == TENDENTION_DOWN)
if(local._tendention == TENDENTION_DOWN)
{
//trend._trend = TENDENTION_DOWN;
//trend._market_phase = MARKET_PHASE_IMPULSE;
Print("Тренд сменился на нисходящий");
}
double o = ::iOpen(_Symbol,tf,i);
double c = ::iClose(_Symbol,tf,i);
//+------------------------------------------------------------------+
//| DOWN + CORRECTION(Первая волна анализа растущего движения) |
//| Коррекционная волна растущего импульсва |
//+------------------------------------------------------------------+
if(trend._trend == TENDENTION_DOWN && trend._market_phase == MARKET_PHASE_CORRECTION)
{
//Print("DOWN + CORRECTION(Первая волна анализа");
//+------------------------------------------------------------------+
//| Устанавливаем слабые точки |
//+------------------------------------------------------------------+
if(global._strong_max > 0 && global._weak_min == 0)
{
if(FractalDown(i,1,tf))
{
global._weak_min = ::iLow(_Symbol,tf,i);
uncor._weak_min = global._weak_min;
local._weak_min = global._weak_min;
global._w_min_Index = i;
global._w_min_Time = ::iTime(_Symbol,tf,i);
uncor._w_min_Index = global._w_min_Index;
uncor._w_min_Time = global._w_min_Time;
local._w_min_Index = global._w_min_Index;
local._w_min_Time = global._w_min_Time;
uncor._equator = uncor.SetEquator(uncor._strong_max,uncor._weak_min);
local._equator = local.SetEquator(local._strong_max,local._weak_min);
Print("Trend DOWN. Set weak point. Global weak min = ",global._weak_min, ", uncor weak min = ", uncor._weak_min, ", local weak min = ", local._weak_min);
continue;
}
}
else
{
//+------------------------------------------------------------------+
//| global struct |
//+------------------------------------------------------------------+
// Расширение глабольной структуры
if(c < global._weak_min)
{
global._weak_min = ::iLow(_Symbol,tf,i);
global._w_min_Index = i;
global._w_min_Time = ::iTime(_Symbol,tf,i);
Print("Первая волна. Расширение глобальной структуры, сильный максимум = ", global._strong_max, ", слабый минимум = ", global._weak_min);
}
// Разворот глобальной структуры
if(c > global._strong_max)
{
RotateStruct(i,tf,global);
global._equator = global.SetEquator(global._strong_min,global._weak_max);
Print("Первая волна окончена. Разворот глабльной структуры, сильный минимум = ", global._strong_min);
}
//+------------------------------------------------------------------+
//| uncorrect struct |
//+------------------------------------------------------------------+
// Расширение внутренней структуры
if(c < uncor._weak_min)
{
if(FractalDown(uncor._w_min_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
Print("Первая волна. Расширяем внутреннюю структуру с проверкой на глубину коррекции 50%, слабый минимум = ", uncor._weak_min);
}
else
{
uncor._weak_min = ::iLow(_Symbol,tf,i);
uncor._w_min_Index = i;
uncor._w_min_Time = ::iTime(_Symbol,tf,i);
Print("Первая волна. Расширение внутренней структуры, слабый минимум = ", uncor._weak_min);
}
}
// Разворот внутренней структуры
if(c > uncor._strong_max)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_min,uncor._weak_max);
Print("Первая волна окончена. Разворот внутренней не откорректированной структуры, сильный минимум = ", uncor._strong_min);
}
//+------------------------------------------------------------------+
//| local struct |
//+------------------------------------------------------------------+
// Расширение локальной структуры
if(c < local._weak_min)
{
if(FractalDown(local._w_min_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("Первая волна. Расширяем локальную структуру с проверкой на глубину коррекции 50%, слабый минимум = ", local._weak_min,"сильный максимум = ", local._strong_max);
}
else
{
local._weak_min = ::iLow(_Symbol,tf,i);
local._w_min_Index = i;
local._w_min_Time = ::iTime(_Symbol,tf,i);
Print("Первая волна. Расширение локальной структуры, слабый минимум = ", local._weak_min);
}
}
// Разворот локальной структуры
if(c > local._strong_max)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_min,local._weak_max);
Print("Первая волна окончена. Разворот локальной структуры, сильный минимум = ", local._strong_min);
}
}
}
//+------------------------------------------------------------------+
//| UP + CORRECTION(Первая волна анализа падающего движения) |
//| Коррекционная волна падающего импульсва |
//+------------------------------------------------------------------+
if(trend._trend == TENDENTION_UP && trend._market_phase == MARKET_PHASE_CORRECTION)
{
Print("Скобка 1");
//Print("UP + CORRECTION(Первая волна анализа");
//+------------------------------------------------------------------+
//| Устанавливаем слабые точки |
//+------------------------------------------------------------------+
if(global._strong_min > 0 && global._weak_max == 0)
{
Print("Скобка 2");
if(FractalUp(i,1,tf))
{
Print("Скобка 3");
global._weak_max = ::iHigh(_Symbol,tf,i);
uncor._weak_max = global._weak_max;
local._weak_max = global._weak_max;
global._w_max_Index = i;
global._w_max_Time = ::iTime(_Symbol,tf,i);
uncor._w_max_Index = global._w_max_Index;
uncor._w_max_Time = global._w_max_Time;
local._w_max_Index = global._w_max_Index;
local._w_max_Time = global._w_max_Time;
uncor._equator = uncor.SetEquator(uncor._strong_min,uncor._weak_max);
local._equator = local.SetEquator(local._strong_min,local._weak_max);
Print("Trend UP. Set weak point. Global weak max = ",global._weak_max, ", uncor weak max = ", uncor._weak_max, ", local weak max = ", local._weak_max);
Print("local._equator = ", local._equator);
continue;
}
}
//+------------------------------------------------------------------+
//| global struct |
//+------------------------------------------------------------------+
if(global._tendention == TENDENTION_UP)
{
// Расширение глабольной структуры
if(c > global._weak_max)
{
global._weak_max = ::iLow(_Symbol,tf,i);
global._w_max_Index = i;
global._w_max_Time = ::iTime(_Symbol,tf,i);
//Print("Первая волна. Расширение глобальной структуры, сильный минимум = ", global._strong_min, "слабый максимум = ", global._weak_max);
}
// Разворот глобальной структуры
if(c < global._strong_min)
{
RotateStruct(i,tf,global);
global._equator = global.SetEquator(global._strong_max,global._weak_min);
//Print("Первая волна окончена. Разворот глабльной структуры, сильный максимум = ", global._strong_max, ", слабый минимум = ", global._weak_min);
}
}
//+------------------------------------------------------------------+
//| uncorrect struct |
//+------------------------------------------------------------------+
if(uncor._tendention == TENDENTION_UP)
{
// Расширение внутренней структуры
if(c > uncor._weak_max)
{
if(FractalUp(uncor._w_max_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
//Print("Первая волна. Расширяем внутреннюю структуру с проверкой на глубину коррекции 50%, слабый максимум = ", uncor._weak_max);
}
else
{
uncor._weak_max = ::iLow(_Symbol,tf,i);
uncor._w_max_Index = i;
uncor._w_max_Time = ::iTime(_Symbol,tf,i);
//Print("Первая волна. Расширение внутренней структуры, слабый максимум = ", uncor._weak_max);
}
}
// Разворот внутренней структуры
if(c < uncor._strong_min)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_max,uncor._weak_min);
//Print("Разворот внутрененй структуры, сильный максимум = ", uncor._strong_max, ", слабый минимум = ", uncor._weak_min);
}
}
else
{
if(c < uncor._weak_min)
{
if(FractalDown(uncor._w_min_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
//Print("Первая волна. Расширяем внутреннюю структуру с проверкой на глубину коррекции 50%, слабый минимум = ", uncor._weak_min);
}
else
{
uncor._weak_min = ::iLow(_Symbol,tf,i);
uncor._w_min_Index = i;
uncor._w_min_Time = ::iTime(_Symbol,tf,i);
//Print("Первая волна. Расширение внутренней структуры, слабый минимум = ", uncor._weak_min);
}
}
// Разворот внутренней структуры
if(c > uncor._strong_max)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_min,uncor._weak_max);
//Print("Разворот внутренней не откорректированной структуры, сильный минимум = ", uncor._strong_min);
}
}
//+------------------------------------------------------------------+
//| local struct |
//+------------------------------------------------------------------+
if(local._tendention == TENDENTION_UP)
{
// Расширение локальной структуры
if(c > local._weak_max)
{
if(FractalUp(local._w_max_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("Первая волна. Расширяем локальную структуру с проверкой на глубину коррекции 50%, сильный минимум = ", local._strong_min,"слабый максимум = ", local._weak_max);
}
else
{
local._weak_max = ::iHigh(_Symbol,tf,i);
local._w_max_Index = i;
local._w_max_Time = ::iTime(_Symbol,tf,i);
Print("Первая волна. Расширение локальной структуры, сильный минимум = ", local._strong_min,"слабый максимум = ", local._weak_max);
}
}
// Разворот локальной структуры
if(c < local._strong_min)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_max,local._weak_min);
Print("Первая волна окончена. Разворот локальной структуры, сильный максимум = ", local._strong_max, ", слабый минимум = ", local._weak_min);
}
}
else
{
if(c < local._weak_min)
{
if(FractalDown(local._w_min_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("Первая волна. Расширяем локальную структуру с проверкой на глубину коррекции 50%, сильный максимум = ", local._strong_max,"слабый минимум = ", local._weak_min);
}
else
{
local._weak_min = ::iLow(_Symbol,tf,i);
local._w_min_Index = i;
local._w_min_Time = ::iTime(_Symbol,tf,i);
Print("Первая волна. Расширение локальной структуры, сильный максимум = ", local._strong_max,"слабый минимум = ", local._weak_min);
}
}
// Разворот локальной структуры
if(c > local._strong_max)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_min,local._weak_max);
Print("Разворот локальной структуры, сильный минимум = ", local._strong_min,"слабый максимум = ", local._weak_max);
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
global.Print(tf,_Digits,_Point);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline void RotateStruct(const int start_index,
const ENUM_TIMEFRAMES tf,
SLevels &levels)
{
if(levels._tendention == TENDENTION_DOWN)
{
int index = GetExtremumMin(start_index,levels._s_max_Index,tf);
double extremum = ::iLow(_Symbol,tf,index);
if(extremum < levels._weak_min)
{
levels._weak_min = extremum;
levels._w_min_Index = index;
levels._w_min_Time = ::iTime(_Symbol,tf,index);
}
levels._strong_min = levels._weak_min;
levels._s_min_Index = levels._w_min_Index;
levels._s_min_Time = levels._w_min_Time;
// Зануляем STRONG EXTERNAL MAX
levels._strong_max = 0;
levels._s_max_Index = 0;
levels._s_max_Time = 0;
// Зануляем WEAK EXTERNAL MIN
levels._weak_min = 0;
levels._w_min_Index = 0;
levels._w_min_Time = 0;
// Назначаем WEAK EXTERNAL MAX
levels._weak_max = ::iHigh(_Symbol,tf,start_index);
levels._w_max_Index = start_index;
levels._w_max_Time = ::iTime(_Symbol,tf,start_index);
levels._tendention = TENDENTION_UP;
Print(" Rotate struct down to up, strong min = ", levels._strong_min," , weak max = ", levels._weak_max,", TENDENTION = ", levels._tendention);
}
else
{
int index = GetExtremumMax(start_index,levels._s_min_Index,tf);
double extremum = ::iHigh(_Symbol,tf,index);
if(extremum > levels._weak_max)
{
levels._weak_max = extremum;
levels._w_max_Index = index;
levels._w_max_Time = ::iTime(_Symbol,tf,index);
}
levels._strong_max= levels._weak_max;
levels._s_max_Index = levels._w_max_Index;
levels._s_max_Time = levels._w_max_Time;
// Зануляем STRONG EXTERNAL MIN
levels._strong_min = 0;
levels._s_min_Index = 0;
levels._s_min_Time = 0;
// Зануляем WEAK EXTERNAL MAX
levels._weak_max = 0;
levels._w_max_Index = 0;
levels._w_max_Time = 0;
// Назначаем WEAK EXTERNAL MIN
levels._weak_min = ::iLow(_Symbol,tf,start_index);
levels._w_min_Index = start_index;
levels._w_min_Time = ::iTime(_Symbol,tf,start_index);
levels._tendention = TENDENTION_DOWN;
Print(" Rotate struct up to down, strong max = ", levels._strong_max," , weak min = ", levels._weak_min,", TENDENTION = ", levels._tendention);
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Расширение внутренней структуры при наличии фрактала |
//| в точке расширения, что приводит к необходимости проверить |
//| глубину коррекции |
//+------------------------------------------------------------------+
void GetNewWeak(const int start_index,const ENUM_TIMEFRAMES tf,SLevels &levels)
{
if(levels._tendention == TENDENTION_UP)
{
double extremum = ::iHigh(_Symbol,tf,start_index);
int ext_index = start_index;
datetime ext_time = ::iTime(_Symbol,tf,start_index);
int index = GetExtremumMin(ext_index,levels._w_max_Index,tf);
double price = ::iLow(_Symbol,tf,index);
Print("price = ", price,", equator = ",levels._equator);
if(price < levels._equator)
{
levels._strong_min = price;
levels._s_min_Index = index;
levels._s_min_Time = ::iTime(_Symbol,tf,index);
}
levels._weak_max = extremum;
levels._w_max_Index = ext_index;
levels._w_max_Time = ext_time;
//Print(" EXP_EXT_STR_UP. Weak Internal max = ", levels._weak_External_max,", Strong External min = ", levels._strong_External_min);
}
else
{
Print("Скобка 2");
double extremum = ::iLow(_Symbol,tf,start_index);
int ext_index = start_index;
datetime ext_time = ::iTime(_Symbol,tf,start_index);
int index = GetExtremumMax(ext_index,levels._w_min_Index,tf);
double price = ::iHigh(_Symbol,tf,index);
if(price > levels._equator)
{
levels._strong_max = price;
levels._s_max_Index = index;
levels._s_max_Time = ::iTime(_Symbol,tf,index);
}
levels._weak_min = extremum;
levels._w_min_Index = ext_index;
levels._w_min_Time = ext_time;
//Print(" EXP_EXT_STR_DOWN. Weak Internal min = ", levels._weak_Internal_min,", Strong External max = ", levels._strong_External_max);
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline int GetExtremumMax(const int start,const int end,const ENUM_TIMEFRAMES tf)
{
int index = start;
double ext = ::iHigh(_Symbol,tf,start);
for(int i = start;i < end;i++)
{
if(::iHigh(_Symbol,tf,i) > ext)
{
ext = ::iHigh(_Symbol,tf,i);
index = i;
}
}
return index;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline int GetExtremumMin(const int start,const int end,const ENUM_TIMEFRAMES tf)
{
int index = start;
double ext = ::iLow(_Symbol,tf,start);
for(int i = start;i < end;i++)
{
if(::iLow(_Symbol,tf,i) < ext)
{
ext = ::iLow(_Symbol,tf,i);
index = i;
}
}
return index;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline bool GetMinBody(const int start,
const int end,
const double level,
const ENUM_TIMEFRAMES tf)
{
for(int i = start;i <= end;i++)
{
if(::iOpen(_Symbol,tf,i) < level || ::iClose(_Symbol,tf,i) < level)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
inline bool GetMaxBody(const int start,
const int end,
const double level,
const ENUM_TIMEFRAMES tf)
{
for(int i = start;i <= end;i++)
{
if(::iOpen(_Symbol,tf,i) > level || ::iClose(_Symbol,tf,i) > level)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Определяем последний фрактал во внутренней структуре |
//+------------------------------------------------------------------+
void SetLastInternalFractal(const ENUM_TIMEFRAMES tf,SLevels &levels)
{
if(levels._tendention == TENDENTION_UP)
{
int start_point = levels._s_min_Index;
int end_point = levels._w_max_Index;
int t_shift = (SetFractCount(inBackFractal) / 2);
for(int i = start_point + t_shift;i < end_point;i++)
{
if(FractalDown(i,t_shift,tf))
{
levels._BackFractal = ::iLow(_Symbol,tf,i);
levels._ibIndex = i;
levels._ibTime = ::iTime(_Symbol,tf,i);
return;
}
}
}
if(levels._tendention == TENDENTION_DOWN)
{
int start_point = levels._s_max_Index;
int end_point = levels._w_min_Index;
int t_shift = (SetFractCount(inBackFractal) / 2);
for(int i = start_point + t_shift;i < end_point;i++)
{
if(FractalUp(i,t_shift,tf))
{
levels._BackFractal = ::iHigh(_Symbol,tf,i);
levels._ibIndex = i;
levels._ibTime = ::iTime(_Symbol,tf,i);
return;
}
}
}
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int SetFractCount(const ENUM_FRACTAL_CANDELS count)
{
switch(count)
{
case FRACTAL_CANDELS_FIVE:
return (int)FRACTAL_CANDELS_FIVE;
default:
return (int)FRACTAL_CANDELS_THREE;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+