1030 lines
83 KiB
MQL5
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;
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
//+------------------------------------------------------------------+
|