Initialize project in MT5 Experts directory
This commit is contained in:
@@ -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__
|
||||
@@ -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__
|
||||
@@ -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__
|
||||
Reference in New Issue
Block a user