2026-06-09 05:44:15 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| CommonHelper.mqh |
|
| | | //| Copyright 2025, MetaQuotes Ltd. |
|
| | | //| https://www.mql5.com |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2025, MetaQuotes Ltd."
|
| | | #property link "https://www.mql5.com"
|
| | | #property version "1.00"
|
| | |
|
| | | #include <Mql5Book\Barsbydate.mqh>
|
| | | #include <Mql5Book\Timer.mqh>
|
| | | #include "Indicator.mqh"
|
| | |
|
2026-06-23 21:44:37 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class StructureLevels
|
| | | {
|
| | | public:
|
| | | TimePrice protectedHigh;
|
| | | TimePrice protectedLow;
|
| | |
|
| | | TimePrice bullNoBos;
|
| | | TimePrice bearNoBos;
|
| | |
|
| | | TimePrice bullConfirmedLow;
|
| | | TimePrice bearConfirmedHigh;
|
| | |
|
| | | int direction;
|
| | | };
|
2026-06-09 05:44:15 +02:00 | | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | class CommonHelper
|
| | | {
|
| | | private:
|
| | | ENUM_TIMEFRAMES timeframe;
|
| | | string symbol;
|
| | |
|
| | | CBarsbydate bar;
|
| | | CNewBar newBar;
|
| | |
|
| | |
|
| | | public:
|
| | | CommonHelper();
|
| | | ~CommonHelper();
|
| | | Swing swing;
|
| | | void UpdateBars(ENUM_TIMEFRAMES timefrme, string symbl, bool useMonths = false, int monthsBack = 100)
|
| | | {
|
| | | timeframe = timefrme;
|
| | | symbol = symbl;
|
| | | bar.UpdateFromMonthsBack(symbol, timeframe, monthsBack, useMonths);
|
| | |
|
| | | swing.UpdateFromMonthsBack(monthsBack, useMonths);
|
| | | }
|
| | | int OnInit(string s, ENUM_TIMEFRAMES tf, int lr = 3, int look = 1)
|
| | | {
|
| | | symbol = s;
|
| | | timeframe = tf;
|
| | | bar.SetAsSeries(false);
|
| | | swing.SetAsSeries(false);
|
| | |
|
| | | if(swing.Init("Fractal", s, tf, lr, look) == -1)
|
| | | {
|
| | | Print("Error creating Swing Indicator: ", GetLastError());
|
| | | return INIT_FAILED;
|
| | | }
|
| | | return INIT_SUCCEEDED;
|
| | | }
|
| | |
|
| | | void SetAsSeries(bool isAsSeries)
|
| | | {
|
| | | bar.SetAsSeries(isAsSeries);
|
| | | }
|
| | | bool OnNewBar()
|
| | | {
|
| | | return newBar.CheckNewBar(symbol, timeframe);
|
| | | }
|
| | | int Bars()
|
| | | {
|
| | | return bar.Size();
|
| | | }
|
| | | int LastBar()
|
| | | {
|
| | | return bar.Size() - 1;
|
| | | }
|
| | |
|
| | | bool HasBars(int count)
|
| | | {
|
| | | return bar.Size() >= count;
|
| | | }
|
| | |
|
| | | bool IsValidIndex(int index = 0)
|
| | | {
|
| | | return (index >= 0 && index < bar.Size());
|
| | | }
|
| | |
|
| | | datetime TimeAt(int index = 0)
|
| | | {
|
| | | return bar.Time(index);
|
| | | }
|
| | |
|
| | | double OpenAt(int index = 0)
|
| | | {
|
| | | return bar.Open(index);
|
| | | }
|
| | |
|
| | | double HighAt(int index = 0)
|
| | | {
|
| | | return bar.High(index);
|
| | | }
|
| | |
|
| | | double LowAt(int index = 0)
|
| | | {
|
| | | return bar.Low(index);
|
| | | }
|
| | |
|
| | | double CloseAt(int index = 0)
|
| | | {
|
| | | return bar.Close(index);
|
| | | }
|
| | |
|
| | | double RangeAt(int index = 0)
|
| | | {
|
| | | return bar.High(index) - bar.Low(index);
|
| | | }
|
| | |
|
| | | double BodyTop(int index = 0)
|
| | | {
|
| | | return MathMax(bar.Open(index), bar.Close(index));
|
| | | }
|
| | |
|
| | | double BodyBottom(int index = 0)
|
| | | {
|
| | | return MathMin(bar.Open(index), bar.Close(index));
|
| | | }
|
| | |
|
| | | double BodySize(int index = 0)
|
| | | {
|
| | | return MathAbs(bar.Close(index) - bar.Open(index));
|
| | | }
|
| | |
|
| | | double UpperWick(int index = 0)
|
| | | {
|
| | | return bar.High(index) - BodyTop(index);
|
| | | }
|
| | |
|
| | | double LowerWick(int index = 0)
|
| | | {
|
| | | return BodyBottom(index) - bar.Low(index);
|
| | | }
|
| | |
|
| | | double MidPrice(double a, double b)
|
| | | {
|
| | | return (a + b) * 0.5;
|
| | | }
|
| | |
|
| | | double CandleMid(int index = 0)
|
| | | {
|
| | | return MidPrice(bar.High(index), bar.Low(index));
|
| | | }
|
| | | int TimeIndex(datetime t)
|
| | | {
|
| | | if(t <= 0)
|
| | | return -1;
|
| | | return bar.IndexByTime(t);
|
| | | }
|
| | |
|
| | | //========================
|
| | | // Price helpers
|
| | | //========================
|
| | | double PointValue()
|
| | | {
|
| | | return bar.Point();
|
| | | }
|
| | |
|
| | | double PointsToPrice(int points)
|
| | | {
|
| | | return points * PointValue();
|
| | | }
|
| | |
|
| | | bool NearPrice(double a, double b, int tolerancePoints)
|
| | | {
|
| | | return MathAbs(a - b) <= PointsToPrice(tolerancePoints);
|
| | | }
|
| | |
|
| | | //========================
|
| | | // Break helpers
|
| | | //========================
|
| | | bool BreakAboveHigh(int refIndex = 0, int barIndex = 0)
|
| | | {
|
| | | if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex))
|
| | | return false;
|
| | | return bar.Close(barIndex) > bar.High(refIndex);
|
| | | }
|
| | |
|
| | | bool BreakBelowLow(int refIndex = 0, int barIndex = 0)
|
| | | {
|
| | | if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex))
|
| | | return false;
|
| | | return bar.Close(barIndex) < bar.Low(refIndex);
|
| | | }
|
| | |
|
| | | bool WickAboveHigh(int refIndex = 0, int barIndex = 0)
|
| | | {
|
| | | if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex))
|
| | | return false;
|
| | | return bar.High(barIndex) > bar.High(refIndex);
|
| | | }
|
| | |
|
| | | bool WickBelowLow(int refIndex = 0, int barIndex = 0)
|
| | | {
|
| | | if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex))
|
| | | return false;
|
| | | return bar.Low(barIndex) < bar.Low(refIndex);
|
| | | }
|
| | |
|
| | | //========================
|
| | | // Candle state
|
| | | //========================
|
| | | bool IsBullishCandle(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | | return bar.Close(index) > bar.Open(index);
|
| | | }
|
| | |
|
| | | bool IsBearishCandle(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | | return bar.Close(index) < bar.Open(index);
|
| | | }
|
| | |
|
| | | bool IsDojiCandle(int index = 0, double maxBodyToRange = 0.10)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | |
|
| | | double range = RangeAt(index);
|
| | | if(range <= 0.0)
|
| | | return false;
|
| | |
|
| | | return (BodySize(index) / range) <= maxBodyToRange;
|
| | | }
|
| | |
|
| | | bool IsSellToBuyCandle(int index = 0, double wickToBodyRatio = 1.2)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | |
|
| | | double body = BodySize(index);
|
| | | if(body <= 0.0)
|
| | | body = _Point;
|
| | |
|
| | | return LowerWick(index) >= body * wickToBodyRatio;
|
| | | }
|
| | |
|
| | | bool IsBuyToSellCandle(int index = 0, double wickToBodyRatio = 1.2)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | |
|
| | | double body = BodySize(index);
|
| | | if(body <= 0.0)
|
| | | body = _Point;
|
| | |
|
| | | return UpperWick(index) >= body * wickToBodyRatio;
|
| | | }
|
| | |
|
| | | //========================
|
| | | // Extremes in range
|
| | | //========================
|
| | | int FindLowestIndex(int fromIndex = 0, int toIndex = 0, bool inclusive = false)
|
| | | {
|
| | | if(fromIndex > toIndex)
|
| | | {
|
| | | int temp = fromIndex;
|
| | | fromIndex = toIndex;
|
| | | toIndex = temp;
|
| | | }
|
| | |
|
| | | int start = (inclusive ? fromIndex : fromIndex + 1);
|
| | | int end = (inclusive ? toIndex : toIndex - 1);
|
| | |
|
| | | if(start > end)
|
| | | return -1;
|
| | |
|
| | | int lowestIndex = -1;
|
| | |
|
| | | for(int i = start; i <= end; i++)
|
| | | {
|
| | | if(!IsValidIndex(i))
|
| | | continue;
|
| | |
|
| | | if(lowestIndex == -1 || bar.Low(i) < bar.Low(lowestIndex))
|
| | | lowestIndex = i;
|
| | | }
|
| | |
|
| | | return lowestIndex;
|
| | | }
|
| | |
|
| | | int FindHighestIndex(int fromIndex = 0, int toIndex = 0, bool inclusive = false)
|
| | | {
|
| | | if(fromIndex > toIndex)
|
| | | {
|
| | | int temp = fromIndex;
|
| | | fromIndex = toIndex;
|
| | | toIndex = temp;
|
| | | }
|
| | |
|
| | | int start = (inclusive ? fromIndex : fromIndex + 1);
|
| | | int end = (inclusive ? toIndex : toIndex - 1);
|
| | |
|
| | | if(start > end)
|
| | | return -1;
|
| | |
|
| | | int highestIndex = -1;
|
| | |
|
| | | for(int i = start; i <= end; i++)
|
| | | {
|
| | | if(!IsValidIndex(i))
|
| | | continue;
|
| | |
|
| | | if(highestIndex == -1 || bar.High(i) > bar.High(highestIndex))
|
| | | highestIndex = i;
|
| | | }
|
| | |
|
| | | return highestIndex;
|
| | | }
|
| | | //========================
|
| | | // Swing helpers
|
| | | //========================
|
| | | bool IsValidSwingValue(double value)
|
| | | {
|
| | | return swing.IsValidValue(value);
|
| | | }
|
| | |
|
| | | bool IsSwingHigh(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | | return swing.IsValidValue(swing.FullHigh(index));
|
| | | }
|
| | |
|
| | | bool IsSwingLow(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | | return swing.IsValidValue(swing.FullLow(index));
|
| | | }
|
| | | double SwingHigh(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return 0;
|
| | | if(!swing.IsValidValue(swing.FullHigh(index)))
|
| | | return 0;
|
| | | return swing.High(index);
|
| | | }
|
| | |
|
| | | double SwingLow(int index = 0)
|
| | | {
|
| | | if(!IsValidIndex(index))
|
| | | return false;
|
| | | if(!swing.IsValidValue(swing.FullLow(index)))
|
| | | return false;
|
| | | return swing.Low(index);
|
| | | }
|
| | | int PrevSwingHighIndex(int anchor = 0, int n = 1)
|
| | | {
|
| | | int found = -1;
|
| | |
|
| | | for(int i = anchor; i >= 0; i--)
|
| | | {
|
| | | if(IsSwingHigh(i))
|
| | | {
|
| | | found++;
|
| | | if(found == n)
|
| | | return i;
|
| | | }
|
| | | }
|
| | |
|
| | | return -1;
|
| | | }
|
| | | bool HasValidTime(datetime t)
|
| | | {
|
| | | return t > 0;
|
| | | }
|
| | |
|
| | | bool IsOlderTime(datetime olderTime, datetime newerTime)
|
| | | {
|
| | | if(!HasValidTime(olderTime) || !HasValidTime(newerTime))
|
| | | return false;
|
| | | return olderTime < newerTime;
|
| | | }
|
| | |
|
| | | bool IsOlderOrSameTime(datetime olderTime, datetime newerTime)
|
| | | {
|
| | | if(!HasValidTime(olderTime) || !HasValidTime(newerTime))
|
| | | return false;
|
| | | return olderTime <= newerTime;
|
| | | }
|
| | |
|
| | | int CountClosedBarsAfterTime(datetime anchorTime, datetime currentTime)
|
| | | {
|
| | | if(!IsOlderTime(anchorTime, currentTime))
|
| | | return -1;
|
| | |
|
| | | int anchorIndex = TimeIndex(anchorTime);
|
| | | int currentIndex = TimeIndex(currentTime);
|
| | |
|
| | | if(!IsValidIndex(anchorIndex) || !IsValidIndex(currentIndex))
|
| | | return -1;
|
| | | if(currentIndex <= anchorIndex)
|
| | | return -1;
|
| | |
|
| | | return (currentIndex - anchorIndex - 1);
|
| | | }
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+---------------------------j---------------------------------------+
|
| | | bool AnchorIsMatureForBreak(int minCandles, datetime anchorTime, datetime currentTime)
|
| | | {
|
| | | int closedBars = MathAbs(TimeIndex(anchorTime) - TimeIndex(currentTime));
|
| | | Print(closedBars);
|
| | | return closedBars >= minCandles;
|
| | | }
|
| | |
|
| | | void SyncIndexFromTime(TimePrice &tp)
|
| | | {
|
| | | if(tp.x == 0)
|
| | | {
|
| | | tp.i = -1;
|
| | | return;
|
| | | }
|
| | |
|
| | | tp.i = TimeIndex(tp.x);
|
| | | }
|
2026-06-10 18:31:08 +02:00 | | |
|
| | | int TimeframeMinutes()
|
| | | {
|
| | |
|
| | | return PeriodSeconds(timeframe) / 60;
|
| | | }
|
2026-06-09 05:44:15 +02:00 | | | };
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | CommonHelper::CommonHelper()
|
| | | {
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | CommonHelper::~CommonHelper()
|
| | | {
|
| | | }
|
| | | //+------------------------------------------------------------------+
|