Initialize project in MT5 Experts directory

This commit is contained in:
Huthayfa
2026-05-28 19:06:07 +03:00
commit 7545b842a4
21 changed files with 3213 additions and 0 deletions
+109
View File
@@ -0,0 +1,109 @@
//+------------------------------------------------------------------+
//| Data/PriceEngine.mqh |
//+------------------------------------------------------------------+
#ifndef __PRICE_ENGINE_MQH__
#define __PRICE_ENGINE_MQH__
#include "../Core/Config.mqh"
class CRepaintGuard
{
public:
static bool ValidateShift(int shift, string context)
{
if(shift < 1)
{
Print("[REPAINT_GUARD] BLOCKED in ", context, ": shift=", shift, " < 1.");
return false;
}
return true;
}
};
class CPriceEngine
{
private:
ENUM_TIMEFRAMES m_htf;
ENUM_TIMEFRAMES m_mtf;
ENUM_TIMEFRAMES m_ltf;
MqlRates m_cacheHTF[];
MqlRates m_cacheMTF[];
MqlRates m_cacheLTF[];
datetime m_lastHTFTime;
datetime m_lastMTFTime;
datetime m_lastLTFTime;
int m_cacheSize;
public:
bool Init(ENUM_TIMEFRAMES htf, ENUM_TIMEFRAMES mtf, ENUM_TIMEFRAMES ltf)
{
m_htf = htf; m_mtf = mtf; m_ltf = ltf; m_cacheSize = 100;
ArraySetAsSeries(m_cacheHTF, true);
ArraySetAsSeries(m_cacheMTF, true);
ArraySetAsSeries(m_cacheLTF, true);
m_lastHTFTime = 0; m_lastMTFTime = 0; m_lastLTFTime = 0;
Print("[PriceEngine] Initialized | HTF:", EnumToString(htf), " MTF:", EnumToString(mtf), " LTF:", EnumToString(ltf));
return true;
}
void Release()
{
ArrayFree(m_cacheHTF); ArrayFree(m_cacheMTF); ArrayFree(m_cacheLTF);
}
bool GetClosedBar(ENUM_TIMEFRAMES period, int shift, MqlRates &outRate)
{
if(!CRepaintGuard::ValidateShift(shift, "GetClosedBar")) shift = 1;
MqlRates temp[];
ArraySetAsSeries(temp, true);
int copied = CopyRates(_Symbol, period, 0, shift + 1, temp);
if(copied <= shift || ArraySize(temp) <= shift) return false;
outRate = temp[shift];
return true;
}
bool GetIndicatorBuffer(int handle, int bufferIndex, int shift, int count, double &buffer[])
{
if(handle == INVALID_HANDLE) return false;
if(shift < 1) { CRepaintGuard::ValidateShift(shift, "GetIndicatorBuffer"); shift = 1; }
ArraySetAsSeries(buffer, true);
int copied = CopyBuffer(handle, bufferIndex, shift, count, buffer);
return (copied > 0);
}
bool IsBarClosed(ENUM_TIMEFRAMES period) const
{
datetime currTime = iTime(_Symbol, period, 0);
datetime prevTime = iTime(_Symbol, period, 1);
return (currTime > 0 && prevTime > 0 && currTime != prevTime);
}
void RefreshAll() { RefreshHTF(); RefreshMTF(); RefreshLTF(); }
void RefreshHTF()
{
int copied = CopyRates(_Symbol, m_htf, 0, m_cacheSize, m_cacheHTF);
if(copied > 0) m_lastHTFTime = m_cacheHTF[0].time;
}
void RefreshMTF()
{
int copied = CopyRates(_Symbol, m_mtf, 0, m_cacheSize, m_cacheMTF);
if(copied > 0) m_lastMTFTime = m_cacheMTF[0].time;
}
void RefreshLTF()
{
int copied = CopyRates(_Symbol, m_ltf, 0, m_cacheSize, m_cacheLTF);
if(copied > 0) m_lastLTFTime = m_cacheLTF[0].time;
}
bool GetHTFBar(int shift, MqlRates &rate)
{
if(ArraySize(m_cacheHTF) > shift && shift >= 0) { rate = m_cacheHTF[shift]; return true; }
return GetClosedBar(m_htf, shift, rate);
}
bool GetMTFBar(int shift, MqlRates &rate)
{
if(ArraySize(m_cacheMTF) > shift && shift >= 0) { rate = m_cacheMTF[shift]; return true; }
return GetClosedBar(m_mtf, shift, rate);
}
bool GetLTFBar(int shift, MqlRates &rate)
{
if(ArraySize(m_cacheLTF) > shift && shift >= 0) { rate = m_cacheLTF[shift]; return true; }
return GetClosedBar(m_ltf, shift, rate);
}
};
#endif // __PRICE_ENGINE_MQH__
+78
View File
@@ -0,0 +1,78 @@
//+------------------------------------------------------------------+
//| Data/VWAP_Engine.mqh |
//+------------------------------------------------------------------+
#ifndef __VWAP_ENGINE_MQH__
#define __VWAP_ENGINE_MQH__
#include "../Core/Config.mqh"
#include "../Core/State.mqh"
class CVWAPEngine
{
private:
AssetProfile m_profile;
datetime m_lastSessionStart;
double m_cachedVWAP;
double m_cachedSlope;
public:
bool Init(const AssetProfile &profile)
{
m_profile = profile;
m_lastSessionStart = 0;
m_cachedVWAP = 0;
m_cachedSlope = 0;
return true;
}
void Release() {}
void Calculate(VWAPState &state)
{
datetime sessionStart = g_session.GetSessionStart(m_profile);
if(sessionStart != m_lastSessionStart)
{
m_lastSessionStart = sessionStart;
state.sumPV = 0; state.sumV = 0; state.sessionStart = sessionStart;
m_cachedVWAP = 0; m_cachedSlope = 0;
}
MqlTick ticks[];
int copied = CopyTicksRange(_Symbol, ticks, COPY_TICKS_TRADE, sessionStart, TimeCurrent());
if(copied <= 0) { state.isValid = false; return; }
double sumPV = 0; long sumV = 0;
for(int i = 0; i < copied; i++)
{
double price = (ticks[i].bid + ticks[i].ask) / 2.0;
long volume = (long)ticks[i].volume;
if(volume > 0 && price > 0) { sumPV += price * (double)volume; sumV += volume; }
}
if(sumV > 0)
{
state.vwapValue = sumPV / (double)sumV;
state.sumPV = sumPV; state.sumV = (double)sumV; state.isValid = true;
m_cachedVWAP = state.vwapValue;
CalculateSlope(state);
}
else { state.isValid = false; state.vwapValue = m_cachedVWAP; }
}
private:
void CalculateSlope(VWAPState &state)
{
MqlRates rates[];
ArraySetAsSeries(rates, true);
int copied = CopyRates(_Symbol, PERIOD_M15, 0, VWAP_SLOPE_BARS + 2, rates);
if(copied < VWAP_SLOPE_BARS + 2) { state.vwapSlope = m_cachedSlope; return; }
double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
int n = VWAP_SLOPE_BARS;
for(int i = 1; i <= n; i++)
{
double x = (double)i;
double y = rates[i].close - state.vwapValue;
sumX += x; sumY += y; sumXY += x * y; sumX2 += x * x;
}
double denominator = (n * sumX2 - sumX * sumX);
if(denominator != 0) { state.vwapSlope = (n * sumXY - sumX * sumY) / denominator; m_cachedSlope = state.vwapSlope; }
else { state.vwapSlope = m_cachedSlope; }
}
};
#endif // __VWAP_ENGINE_MQH__
+90
View File
@@ -0,0 +1,90 @@
//+------------------------------------------------------------------+
//| Data/Volatility.mqh |
//+------------------------------------------------------------------+
#ifndef __VOLATILITY_MQH__
#define __VOLATILITY_MQH__
#include "../Core/Config.mqh"
class CVolatility
{
private:
int m_atrPeriod;
int m_atrBaseline;
ENUM_TIMEFRAMES m_htf;
ENUM_TIMEFRAMES m_mtf;
int m_handleATR;
int m_handleADX;
int m_handleBB;
double m_atrCurrent;
double m_atrBaselineValue;
double m_atrRelative;
double m_adxValue;
double m_bbWidth;
public:
bool Init(int atrPeriod, int atrBaseline, ENUM_TIMEFRAMES htf, ENUM_TIMEFRAMES mtf)
{
m_atrPeriod = atrPeriod; m_atrBaseline = atrBaseline; m_htf = htf; m_mtf = mtf;
m_handleATR = iATR(_Symbol, m_mtf, m_atrPeriod);
m_handleADX = iADX(_Symbol, m_mtf, ADX_PERIOD);
m_handleBB = iBands(_Symbol, m_mtf, BB_PERIOD, 0, BB_DEVIATIONS, PRICE_CLOSE);
if(m_handleATR == INVALID_HANDLE || m_handleADX == INVALID_HANDLE || m_handleBB == INVALID_HANDLE)
{
Print("[Volatility] Indicator creation failed");
return false;
}
int warmup = MathMax(atrBaseline, BB_PERIOD) + 10;
double dummy[]; ArraySetAsSeries(dummy, true);
CopyBuffer(m_handleATR, 0, 1, warmup, dummy);
Print("[Volatility] Indicators initialized on ", EnumToString(m_mtf));
return true;
}
void Release()
{
RELEASE_HANDLE(m_handleATR);
RELEASE_HANDLE(m_handleADX);
RELEASE_HANDLE(m_handleBB);
}
void Update()
{
double atrBuf[], adxBuf[], bbUp[], bbLow[], bbMid[];
ArraySetAsSeries(atrBuf, true); ArraySetAsSeries(adxBuf, true);
ArraySetAsSeries(bbUp, true); ArraySetAsSeries(bbLow, true); ArraySetAsSeries(bbMid, true);
if(CopyBuffer(m_handleATR, 0, 1, 1, atrBuf) <= 0) return;
m_atrCurrent = atrBuf[0];
if(CopyBuffer(m_handleADX, 0, 1, 1, adxBuf) <= 0) return;
m_adxValue = adxBuf[0];
if(CopyBuffer(m_handleBB, UPPER_BAND, 1, 1, bbUp) <= 0 ||
CopyBuffer(m_handleBB, LOWER_BAND, 1, 1, bbLow) <= 0 ||
CopyBuffer(m_handleBB, BASE_LINE, 1, 1, bbMid) <= 0) return;
if(bbMid[0] != 0) m_bbWidth = (bbUp[0] - bbLow[0]) / bbMid[0]; else m_bbWidth = 0;
CalculateATRBaseline();
}
double GetRelativeATR() const { return m_atrRelative; }
double GetATR() const { return m_atrCurrent; }
double GetADX() const { return m_adxValue; }
double GetBBWidth() const { return m_bbWidth; }
ENUM_REGIME DetectRegime() const
{
if(m_atrRelative >= ATR_TREND_RATIO && m_adxValue >= ADX_TREND_LEVEL) return REGIME_TREND;
else if(m_atrRelative < ATR_CHOP_RATIO && m_adxValue < ADX_CHOP_LEVEL) return REGIME_CHOP;
else if(m_atrRelative < ATR_TREND_RATIO && m_adxValue < ADX_RANGE_LEVEL) return REGIME_RANGE;
return REGIME_RANGE;
}
private:
void CalculateATRBaseline()
{
double atrValues[]; ArraySetAsSeries(atrValues, true);
if(CopyBuffer(m_handleATR, 0, 1, m_atrBaseline, atrValues) < m_atrBaseline)
{ m_atrRelative = 1.0; return; }
double sum = 0;
for(int i = 0; i < m_atrBaseline; i++) sum += atrValues[i];
m_atrBaselineValue = sum / m_atrBaseline;
if(m_atrBaselineValue > 0) m_atrRelative = m_atrCurrent / m_atrBaselineValue;
else m_atrRelative = 1.0;
}
};
#endif // __VOLATILITY_MQH__