FractFactory/FractFactory.mq5

1031 lines
83 KiB
MQL5
Raw Permalink Normal View History

2025-05-30 14:56:16 +02:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| 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. ">G:0 =0G0;0 >?@545;5=8O C@>2=59 = ",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. ">G:0 =0G0;0 >?@545;5=8O C@>2=59 = ",trend._startTime," c >B<5B:8 = ", trend._start);
}
::Print("*****");
::Print("!8BC0F8O =0 ");
::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);
// 2KE>48< 87 F8:;0 ?@8 A>1;N45=88 40==KE CA;>289
if(expantion == true)
if(hFract._value > 0)
if(extremum > hFract._value || extremum < iClose(_Symbol,tf,hFract._index))
{
// Print("&8:; ?>8A:0 @0AH8@5=8O 2 225@E 7025@H5=");
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. 5@20O A:>1:0 = ", hFract._value);
}
else
if(hFract._value > 0 && extremum < hFract._value)
{
// @>25@O5< 1K;> ;8 @0=55 70D8:A8@>20=> @0AH8@5=85, =0 ?@54<5B ;>6=>3> ?@>1>O, 5A;8 40, ?5@5=>A8< =0 B5:CI89 D@0:B0;
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. ?5@5=>A 70 ;>6=K9 ?@>1>9 = ", hFract._value,", D8:A8@C5< @0AH8@5=85 = ", 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. B>@0O A:>1:0 = ", hFract._value,", D8:A8@C5< @0AH8@5=85 = ", expantion);
// break;
}
else
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = true;
//Print("FractalUp. "@5BLO A:>1:0 = ", hFract._value);
}
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void GetExpantionDn(SFractal &hFract,const ENUM_TIMEFRAMES tf)
{
bool expantion = false;
//45< 23;C1L 8AB>@88 >B B>G:8, =0 :>B>@>9 2>7<>6=> D>@<8@>20=85 D@0:B0;0
for(int i = shift + 1,size = ::iBars(_Symbol,tf);i < size;i++)
{
//A;8 =0H;8 D@0:B0; 2=87
if(FractalDown(i,tf))
{
//0?><8=05< 7=0G5=85 D@0:B0;0
double extremum = ::iLow(_Symbol,tf,i);
// 2KE>48< 87 F8:;0 ?@8 A>1;N45=88 40==KE CA;>289
if(expantion == true)
if(hFract._value > 0)
if(extremum < hFract._value || extremum > iClose(_Symbol,tf,hFract._index))
{
//Print("&8:; ?>8A:0 @0AH8@5=8O 2 =87 7025@H5=");
break;
}
//A;8 4> B>3> =8 >4=>3> D@0:B0;0 =5 =0945=>, 8;8 =0945==K9 (B5:CI89) D@0:B0; =865 @0=55 =0945==>3>
if(hFract._value == 0 || extremum < hFract._value)
{
//0?><8=05< =>2K9 D@0:B0; 8 845< 40;LH5
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
//Print("FractalDn. 5@20O A:>1:0 = ", hFract._value);
}
else
//A;8 B5:CI89 D@0:B0; 2KH5 @0=55 =0945==>3>
if(hFract._value > 0 && extremum > hFract._value)
{
// @>25@O5< 1K;> ;8 @0=55 70D8:A8@>20=> @0AH8@5=85, =0 ?@54<5B ;>6=>3> ?@>1>O, 5A;8 40, ?5@5=>A8< =0 B5:CI89 D@0:B0;
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. ?5@5=>A 70 ;>6=K9 ?@>1>9 = ", hFract._value,", D8:A8@C5< @0AH8@5=85 = ", expantion);
}
//>A<0B@8205< 2A5 A25G8 <564C B5:CI8< D@0:B0;>< 8 @0=55 =0945==K<
//=0 ?@54<5B ?@>18B8O B5;>< A25G8. 0:@KB85 8;8 >B:@KB85 4>;6=> ?@>1820BL
//?@54K4CI89 C@>25=L
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;
//A;8 ?@>18B85 70D8:A8@>20=> - ?@5@K205< @01>BC
//=0G8B B5:CI89 D@0:B0; O2;O5BAO A8;L=K< C@>2=5< 4;O ?>A;54=53> A>E@0=5==>3>
if(close < extremum)
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
expantion = true;
//Print("FractalDn. B>@0O A:>1:0 = ", hFract._value,", D8:A8@C5< @0AH8@5=85 = ", expantion);
// break;
}
//A;8 ?@>18B85 B5;>< =5 70D8:A8@>20==> - 70?><8=05< B5:CI89 D@0:B0;
//8 845< 40;LH5
else
{
hFract._value = extremum;
hFract._index = i;
hFract._time = ::iTime(_Symbol,tf,hFract._index);
hFract._isUp = false;
//Print("FractalDn. "@5BLO A:>1:0 = ", hFract._value);
}
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
void SetHTFLevels(const ENUM_TIMEFRAMES tf,const SDirection &trend, SLevels &global, SLevels &uncor, SLevels &local)
{
int bars = ::iBars(_Symbol,tf);
//+------------------------------------------------------------------+
//| #AB0=02;8205< A8;L=K5 B>G:8 |
//+------------------------------------------------------------------+
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("#AB0=02;8205< A8;L=K5 M:AB@5<C<K. 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("#AB0=02;8205< A8;L=K5 M:AB@5<C<K. 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--)
{
// 20@80=BK 25B2;5=89
// UP + UP + CORRECTION(5@20O 2>;=0 0=0;870).
// DOWN + DOWN + CORRECTION(5@20O 2>;=0 0=0;870) +
// 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(""@5=4 A<5=8;AO =0 =8AE>4OI89");
}
double o = ::iOpen(_Symbol,tf,i);
double c = ::iClose(_Symbol,tf,i);
//+------------------------------------------------------------------+
//| DOWN + CORRECTION(5@20O 2>;=0 0=0;870 @0ABCI53> 42865=8O) |
//| >@@5:F8>==0O 2>;=0 @0ABCI53> 8<?C;LA20 |
//+------------------------------------------------------------------+
if(trend._trend == TENDENTION_DOWN && trend._market_phase == MARKET_PHASE_CORRECTION)
{
//Print("DOWN + CORRECTION(5@20O 2>;=0 0=0;870");
//+------------------------------------------------------------------+
//| #AB0=02;8205< A;01K5 B>G:8 |
//+------------------------------------------------------------------+
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 |
//+------------------------------------------------------------------+
// 0AH8@5=85 3;01>;L=>9 AB@C:BC@K
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("5@20O 2>;=0. 0AH8@5=85 3;>10;L=>9 AB@C:BC@K, A8;L=K9 <0:A8<C< = ", global._strong_max, ", A;01K9 <8=8<C< = ", global._weak_min);
}
// 072>@>B 3;>10;L=>9 AB@C:BC@K
if(c > global._strong_max)
{
RotateStruct(i,tf,global);
global._equator = global.SetEquator(global._strong_min,global._weak_max);
Print("5@20O 2>;=0 >:>=G5=0. 072>@>B 3;01;L=>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", global._strong_min);
}
//+------------------------------------------------------------------+
//| uncorrect struct |
//+------------------------------------------------------------------+
// 0AH8@5=85 2=CB@5==59 AB@C:BC@K
if(c < uncor._weak_min)
{
if(FractalDown(uncor._w_min_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
Print("5@20O 2>;=0. 0AH8@O5< 2=CB@5==NN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A;01K9 <8=8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 2=CB@5==59 AB@C:BC@K, A;01K9 <8=8<C< = ", uncor._weak_min);
}
}
// 072>@>B 2=CB@5==59 AB@C:BC@K
if(c > uncor._strong_max)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_min,uncor._weak_max);
Print("5@20O 2>;=0 >:>=G5=0. 072>@>B 2=CB@5==59 =5 >B:>@@5:B8@>20==>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", uncor._strong_min);
}
//+------------------------------------------------------------------+
//| local struct |
//+------------------------------------------------------------------+
// 0AH8@5=85 ;>:0;L=>9 AB@C:BC@K
if(c < local._weak_min)
{
if(FractalDown(local._w_min_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("5@20O 2>;=0. 0AH8@O5< ;>:0;L=CN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A;01K9 <8=8<C< = ", local._weak_min,"A8;L=K9 <0:A8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 ;>:0;L=>9 AB@C:BC@K, A;01K9 <8=8<C< = ", local._weak_min);
}
}
// 072>@>B ;>:0;L=>9 AB@C:BC@K
if(c > local._strong_max)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_min,local._weak_max);
Print("5@20O 2>;=0 >:>=G5=0. 072>@>B ;>:0;L=>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", local._strong_min);
}
}
}
//+------------------------------------------------------------------+
//| UP + CORRECTION(5@20O 2>;=0 0=0;870 ?040NI53> 42865=8O) |
//| >@@5:F8>==0O 2>;=0 ?040NI53> 8<?C;LA20 |
//+------------------------------------------------------------------+
if(trend._trend == TENDENTION_UP && trend._market_phase == MARKET_PHASE_CORRECTION)
{
Print("!:>1:0 1");
//Print("UP + CORRECTION(5@20O 2>;=0 0=0;870");
//+------------------------------------------------------------------+
//| #AB0=02;8205< A;01K5 B>G:8 |
//+------------------------------------------------------------------+
if(global._strong_min > 0 && global._weak_max == 0)
{
Print("!:>1:0 2");
if(FractalUp(i,1,tf))
{
Print("!:>1:0 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)
{
// 0AH8@5=85 3;01>;L=>9 AB@C:BC@K
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("5@20O 2>;=0. 0AH8@5=85 3;>10;L=>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", global._strong_min, "A;01K9 <0:A8<C< = ", global._weak_max);
}
// 072>@>B 3;>10;L=>9 AB@C:BC@K
if(c < global._strong_min)
{
RotateStruct(i,tf,global);
global._equator = global.SetEquator(global._strong_max,global._weak_min);
//Print("5@20O 2>;=0 >:>=G5=0. 072>@>B 3;01;L=>9 AB@C:BC@K, A8;L=K9 <0:A8<C< = ", global._strong_max, ", A;01K9 <8=8<C< = ", global._weak_min);
}
}
//+------------------------------------------------------------------+
//| uncorrect struct |
//+------------------------------------------------------------------+
if(uncor._tendention == TENDENTION_UP)
{
// 0AH8@5=85 2=CB@5==59 AB@C:BC@K
if(c > uncor._weak_max)
{
if(FractalUp(uncor._w_max_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
//Print("5@20O 2>;=0. 0AH8@O5< 2=CB@5==NN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A;01K9 <0:A8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 2=CB@5==59 AB@C:BC@K, A;01K9 <0:A8<C< = ", uncor._weak_max);
}
}
// 072>@>B 2=CB@5==59 AB@C:BC@K
if(c < uncor._strong_min)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_max,uncor._weak_min);
//Print(" 072>@>B 2=CB@5=5=9 AB@C:BC@K, A8;L=K9 <0:A8<C< = ", uncor._strong_max, ", A;01K9 <8=8<C< = ", uncor._weak_min);
}
}
else
{
if(c < uncor._weak_min)
{
if(FractalDown(uncor._w_min_Index,1,tf))
{
GetNewWeak(i,tf,uncor);
//Print("5@20O 2>;=0. 0AH8@O5< 2=CB@5==NN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A;01K9 <8=8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 2=CB@5==59 AB@C:BC@K, A;01K9 <8=8<C< = ", uncor._weak_min);
}
}
// 072>@>B 2=CB@5==59 AB@C:BC@K
if(c > uncor._strong_max)
{
RotateStruct(i,tf,uncor);
uncor._equator = uncor.SetEquator(uncor._strong_min,uncor._weak_max);
//Print(" 072>@>B 2=CB@5==59 =5 >B:>@@5:B8@>20==>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", uncor._strong_min);
}
}
//+------------------------------------------------------------------+
//| local struct |
//+------------------------------------------------------------------+
if(local._tendention == TENDENTION_UP)
{
// 0AH8@5=85 ;>:0;L=>9 AB@C:BC@K
if(c > local._weak_max)
{
if(FractalUp(local._w_max_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("5@20O 2>;=0. 0AH8@O5< ;>:0;L=CN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A8;L=K9 <8=8<C< = ", local._strong_min,"A;01K9 <0:A8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 ;>:0;L=>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", local._strong_min,"A;01K9 <0:A8<C< = ", local._weak_max);
}
}
// 072>@>B ;>:0;L=>9 AB@C:BC@K
if(c < local._strong_min)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_max,local._weak_min);
Print("5@20O 2>;=0 >:>=G5=0. 072>@>B ;>:0;L=>9 AB@C:BC@K, A8;L=K9 <0:A8<C< = ", local._strong_max, ", A;01K9 <8=8<C< = ", local._weak_min);
}
}
else
{
if(c < local._weak_min)
{
if(FractalDown(local._w_min_Index,1,tf))
{
GetNewWeak(i,tf,local);
Print("5@20O 2>;=0. 0AH8@O5< ;>:0;L=CN AB@C:BC@C A ?@>25@:>9 =0 3;C18=C :>@@5:F88 50%, A8;L=K9 <0:A8<C< = ", local._strong_max,"A;01K9 <8=8<C< = ", 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("5@20O 2>;=0. 0AH8@5=85 ;>:0;L=>9 AB@C:BC@K, A8;L=K9 <0:A8<C< = ", local._strong_max,"A;01K9 <8=8<C< = ", local._weak_min);
}
}
// 072>@>B ;>:0;L=>9 AB@C:BC@K
if(c > local._strong_max)
{
RotateStruct(i,tf,local);
local._equator = uncor.SetEquator(local._strong_min,local._weak_max);
Print(" 072>@>B ;>:0;L=>9 AB@C:BC@K, A8;L=K9 <8=8<C< = ", local._strong_min,"A;01K9 <0:A8<C< = ", 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;
// 0=C;O5< STRONG EXTERNAL MAX
levels._strong_max = 0;
levels._s_max_Index = 0;
levels._s_max_Time = 0;
// 0=C;O5< WEAK EXTERNAL MIN
levels._weak_min = 0;
levels._w_min_Index = 0;
levels._w_min_Time = 0;
// 07=0G05< 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;
// 0=C;O5< STRONG EXTERNAL MIN
levels._strong_min = 0;
levels._s_min_Index = 0;
levels._s_min_Time = 0;
// 0=C;O5< WEAK EXTERNAL MAX
levels._weak_max = 0;
levels._w_max_Index = 0;
levels._w_max_Time = 0;
// 07=0G05< 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);
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| 0AH8@5=85 2=CB@5==59 AB@C:BC@K ?@8 =0;8G88 D@0:B0;0 |
//| 2 B>G:5 @0AH8@5=8O, GB> ?@82>48B : =5>1E>48<>AB8 ?@>25@8BL |
//| 3;C18=C :>@@5:F88 |
//+------------------------------------------------------------------+
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("!:>1:0 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;
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| ?@545;O5< ?>A;54=89 D@0:B0; 2> 2=CB@5==59 AB@C:BC@5 |
//+------------------------------------------------------------------+
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;
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+