//+------------------------------------------------------------------+ //| 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; } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //+------------------------------------------------------------------+