mql5/Experts/AnotherTriBible/AbstractChapter.mqh
younglubah-gmail 540d58914e
2026-03-15 02:46:38 +02:00

417 lines
No EOL
10 KiB
MQL5

//+------------------------------------------------------------------+
//| AbstractChapter.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"
#property strict
#include "Inducators.mqh"
class CAbstractChapter {
protected:
ENUM_TIMEFRAMES timeframe;
string symbol;
CBarsbydate bar;
Swing swing;
CNewBar newBar;
CChartDebug debug;
protected:
//========================
// Life cycle
//========================
bool OnNewBar() {
return newBar.CheckNewBar(symbol, timeframe);
}
void UpdateBars(int monthsBack = 3) {
bar.UpdateFromMonthsBack(symbol, timeframe, monthsBack);
}
//========================
// Bar info
//========================
int Bars() {
return bar.Size();
}
bool HasBars(int count) {
return bar.Size() >= count;
}
bool IsValidIndex(int index) {
return (index >= 0 && index < bar.Size());
}
datetime TimeAt(int index) {
return bar.Time(index);
}
double OpenAt(int index) {
return bar.Open(index);
}
double HighAt(int index) {
return bar.High(index);
}
double LowAt(int index) {
return bar.Low(index);
}
double CloseAt(int index) {
return bar.Close(index);
}
double RangeAt(int index) {
return bar.High(index) - bar.Low(index);
}
double BodyTop(int index) {
return MathMax(bar.Open(index), bar.Close(index));
}
double BodyBottom(int index) {
return MathMin(bar.Open(index), bar.Close(index));
}
double BodySize(int index) {
return MathAbs(bar.Close(index) - bar.Open(index));
}
double UpperWick(int index) {
return bar.High(index) - BodyTop(index);
}
double LowerWick(int index) {
return BodyBottom(index) - bar.Low(index);
}
double MidPrice(double a, double b) {
return (a + b) * 0.5;
}
double CandleMid(int index) {
return MidPrice(bar.High(index), bar.Low(index));
}
//========================
// 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);
}
//========================
// Swing helpers
//========================
bool IsValidSwingValue(double value) {
return swing.IsValidValue(value);
}
bool IsSwingHigh(int index) {
if(!IsValidIndex(index)) return false;
return swing.IsValidValue(swing.HighAt(index));
}
bool IsSwingLow(int index) {
if(!IsValidIndex(index)) return false;
return swing.IsValidValue(swing.LowAt(index));
}
int PrevSwingHighIndex(int anchor, int n = 1) {
int found = -1;
for(int i = anchor; i >= 0; i--) {
if(IsSwingHigh(i)) {
found++;
if(found == n)
return i;
}
}
return -1;
}
int PrevSwingLowIndex(int anchor, int n = 1) {
int found = -1;
for(int i = anchor; i >= 0; i--) {
if(IsSwingLow(i)) {
found++;
if(found == n)
return i;
}
}
return -1;
}
int NextSwingHighIndex(int anchor, int n = 1) {
int found = 0;
for(int i = anchor; i < bar.Size(); i++) {
if(IsSwingHigh(i)) {
found++;
if(found == n)
return i;
}
}
return -1;
}
int NextSwingLowIndex(int anchor, int n = 1) {
int found = 0;
for(int i = anchor; i < bar.Size(); i++) {
if(IsSwingLow(i)) {
found++;
if(found == n)
return i;
}
}
return -1;
}
//========================
// Break helpers
//========================
bool BreakAboveHigh(int refIndex, int barIndex) {
if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex)) return false;
return bar.Close(barIndex) > bar.High(refIndex);
}
bool BreakBelowLow(int refIndex, int barIndex) {
if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex)) return false;
return bar.Close(barIndex) < bar.Low(refIndex);
}
bool WickAboveHigh(int refIndex, int barIndex) {
if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex)) return false;
return bar.High(barIndex) > bar.High(refIndex);
}
bool WickBelowLow(int refIndex, int barIndex) {
if(!IsValidIndex(refIndex) || !IsValidIndex(barIndex)) return false;
return bar.Low(barIndex) < bar.Low(refIndex);
}
//========================
// Candle state
//========================
bool IsBullishCandle(int index) {
if(!IsValidIndex(index)) return false;
return bar.Close(index) > bar.Open(index);
}
bool IsBearishCandle(int index) {
if(!IsValidIndex(index)) return false;
return bar.Close(index) < bar.Open(index);
}
bool IsDojiCandle(int index, 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, 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, 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, int toIndex, 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, int toIndex, 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;
}
//========================
// Zone helpers for Chapter 4
//========================
double ZoneMid(double top, double bottom) {
return (top + bottom) * 0.5;
}
double ZoneHeight(double top, double bottom) {
return MathAbs(top - bottom);
}
bool PriceTouchesZone(int index, double top, double bottom) {
if(!IsValidIndex(index)) return false;
double zTop = MathMax(top, bottom);
double zBot = MathMin(top, bottom);
return bar.Low(index) <= zTop && bar.High(index) >= zBot;
}
bool PriceClosesInsideZone(int index, double top, double bottom) {
if(!IsValidIndex(index)) return false;
double zTop = MathMax(top, bottom);
double zBot = MathMin(top, bottom);
double c = bar.Close(index);
return c <= zTop && c >= zBot;
}
bool PriceClosesBeyondSupply(int index, double top) {
if(!IsValidIndex(index)) return false;
return bar.Close(index) > top;
}
bool PriceClosesBeyondDemand(int index, double bottom) {
if(!IsValidIndex(index)) return false;
return bar.Close(index) < bottom;
}
//========================
// Drawing helpers
//========================
void DrawLevel(string key,
int fromIndex,
int toIndex,
double price,
string text,
color col = clrChartreuse,
int style = 1) {
if(!IsValidIndex(fromIndex) || !IsValidIndex(toIndex))
return;
debug.LineWithCenteredText(
key,
bar.Time(fromIndex), price,
bar.Time(toIndex), price,
text,
style,
col
);
}
void DrawZone(string key,
int leftIndex,
int rightIndex,
double top,
double bottom,
string text,
color col,
double insetFrac = 0.06,
int fontSize = 6,
bool drawOnTop = false) {
if(!IsValidIndex(leftIndex) || !IsValidIndex(rightIndex))
return;
debug.RectWithCenteredText(
symbol,
key,
bar.Time(leftIndex), top,
bar.Time(rightIndex), bottom,
text,
col,
insetFrac,
fontSize,
drawOnTop
);
}
public:
CAbstractChapter(void) {
timeframe = PERIOD_CURRENT;
symbol = _Symbol;
}
virtual ~CAbstractChapter() {}
virtual int OnInit(string s, ENUM_TIMEFRAMES tf_, int lr = 3, int look = 1) {
timeframe = tf_;
symbol = s;
debug.Init(0, __FILE__, true);
if(swing.Init("Fractal", s, tf_, lr, look) == -1) {
Print("Error creating Swing Indicator: ", GetLastError());
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
virtual void OnCalculate() {}
};
//+------------------------------------------------------------------+