79 lines
2.6 KiB
Plaintext
79 lines
2.6 KiB
Plaintext
//+------------------------------------------------------------------+
|
|
//| 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__
|