//+------------------------------------------------------------------+ //| AbsorbingFinder.mqh | //| Copyright 2024, Competent Dilettante | //| https://www.youtube.com/@competentdilettante | //+------------------------------------------------------------------+ #property copyright "Copyright 2024, Competent Dilettante" #property link "https://www.youtube.com/@competentdilettante" //+------------------------------------------------------------------+ int DistPrices(double priceA, double priceB, string symbol = NULL) { return (int)(::MathAbs(priceA - priceB) / SymbolInfoDouble(symbol,SYMBOL_POINT)); } //+------------------------------------------------------------------+ bool IsValidData(const int begin,const int end,const int formation) { if(begin <= 0) { ::Print("Все свечи паттерна должны быть полностью сформированы\nТекущая незакрытая свеча не допускается"); return false; } if(begin >= end) { ::Print("Указанные индексы не соответсвуют логике"); return false; } if(::MathAbs(end - begin) + 1 < formation) { //::Print(end," - ",begin," = ",end - begin); ::Print("Нехватает свечей для анализа"); return false; } return true; } //+------------------------------------------------------------------+ bool IsAbsorbingUp(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 1; if(!IsValidData(index,end,2)) return false; double open,close,preOpen,preClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,end); preClose = ::iClose(symbol,tf,end); if(preOpen > preClose && open < close) { if(DistPrices(open,close,symbol) > DistPrices(preOpen,preClose,symbol)) { if(preOpen <= close && preClose >= open) { start = ::iLow(symbol,tf,end); stop = ::iHigh(symbol,tf,index); return true; } } } return false; } //+------------------------------------------------------------------+ bool IsAbsorbingDn(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 1; if(!IsValidData(index,end,2)) return false; double open,close,preOpen,preClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,end); preClose = ::iClose(symbol,tf,end); if(preOpen < preClose && open > close) { if(DistPrices(open,close,symbol) > DistPrices(preOpen,preClose,symbol)) { if(preOpen >= close && preClose <= open) { start = ::iHigh(symbol,tf,end); stop = ::iLow(symbol,tf,index); return true; } } } return false; } //+------------------------------------------------------------------+ bool IsDoubleAbsorbingUp(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 2; if(!IsValidData(index,end,3)) return false; double open,close,preOpen,preClose,signalOpen,signalClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,index + 1); preClose = ::iClose(symbol,tf,index + 1); signalOpen = ::iOpen(symbol,tf,end); signalClose = ::iClose(symbol,tf,end); if(signalOpen > signalClose && preOpen < preClose && open < close && preClose < signalOpen) { if(DistPrices(preOpen,close,symbol) > DistPrices(signalOpen,signalClose,symbol)) { if(signalOpen <= close && signalClose >= preOpen) { start = ::iLow(symbol,tf,end); stop = ::iHigh(symbol,tf,index); return true; } } } return false; } //+------------------------------------------------------------------+ bool IsTripleAbsorbingUp(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 3; if(!IsValidData(index,end,4)) return false; double open,close,preOpen,preClose,signalOpen,signalClose,prePreOpen,prePreClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,index + 1); preClose = ::iClose(symbol,tf,index + 1); prePreOpen = ::iOpen(symbol,tf,index + 2); prePreClose = ::iClose(symbol,tf,index + 2); signalOpen = ::iOpen(symbol,tf,end); signalClose = ::iClose(symbol,tf,end); if(signalOpen > signalClose && preOpen < preClose && prePreOpen < prePreClose && open < close && preClose < signalOpen && prePreClose < signalOpen) { if(DistPrices(prePreOpen,close,symbol) > DistPrices(signalOpen,signalClose,symbol)) { if(signalOpen <= close && signalClose >= preOpen) { start = ::iLow(symbol,tf,end); stop = ::iHigh(symbol,tf,index); return true; } } } return false; } //+------------------------------------------------------------------+ bool IsDoubleAbsorbingDn(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 2; if(!IsValidData(index,end,3)) return false; double open,close,preOpen,preClose,signalOpen,signalClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,index + 1); preClose = ::iClose(symbol,tf,index + 1); signalOpen = ::iOpen(symbol,tf,end); signalClose = ::iClose(symbol,tf,end); if(signalOpen < signalClose && preOpen > preClose && open > close && preClose > signalOpen) { if(DistPrices(preOpen,close,symbol) > DistPrices(signalOpen,signalClose,symbol)) { if(signalOpen >= close && signalClose <= preOpen) { start = ::iHigh(symbol,tf,end); stop = ::iLow(symbol,tf,index); return true; } } } return false; } //+------------------------------------------------------------------+ bool IsTripleAbsorbingDn(const string symbol,const ENUM_TIMEFRAMES tf,const int index,double &start,double &stop) { int end = index + 3; if(!IsValidData(index,end,4)) return false; double open,close,preOpen,preClose,signalOpen,signalClose,prePreOpen,prePreClose; open = ::iOpen(symbol,tf,index); close = ::iClose(symbol,tf,index); preOpen = ::iOpen(symbol,tf,index + 1); preClose = ::iClose(symbol,tf,index + 1); prePreOpen = ::iOpen(symbol,tf,index + 2); prePreClose = ::iClose(symbol,tf,index + 2); signalOpen = ::iOpen(symbol,tf,end); signalClose = ::iClose(symbol,tf,end); if(signalOpen < signalClose && preOpen > preClose && prePreOpen > prePreClose && open > close && preClose > signalOpen && prePreClose > preOpen) { if(DistPrices(prePreOpen,close,symbol) > DistPrices(signalOpen,signalClose,symbol)) { if(signalOpen >= close && signalClose <= preOpen) { start = ::iLow(symbol,tf,end); stop = ::iHigh(symbol,tf,index); return true; } } } return false; }