struct MA_HANDLE
{
string symbol;
ENUM_TIMEFRAMES tf;
int period;
int shift;
ENUM_MA_METHOD method;
ENUM_APPLIED_PRICE price;
int handle;
};
MA_HANDLE MAHandles[];
//MA Handle
int GetMAHandle(string sy, ENUM_TIMEFRAMES tf,
int period, int ma_shift,
ENUM_MA_METHOD method,
ENUM_APPLIED_PRICE price)
{
for(int i=0;i<ArraySize(MAHandles);i++)
{
if(MAHandles[i].symbol==sy &&
MAHandles[i].tf==tf &&
MAHandles[i].period==period &&
MAHandles[i].shift==ma_shift &&
MAHandles[i].method==method &&
MAHandles[i].price==price)
{
return MAHandles[i].handle;
}
}
int h = iMA(sy, tf, period, ma_shift, method, price);
if(h == INVALID_HANDLE)
return INVALID_HANDLE;
int n = ArraySize(MAHandles);
ArrayResize(MAHandles, n+1);
MAHandles[n].symbol = sy;
MAHandles[n].tf = tf;
MAHandles[n].period = period;
MAHandles[n].shift = ma_shift;
MAHandles[n].method = method;
MAHandles[n].price = price;
MAHandles[n].handle = h;
return h;
}
//MA Value
double fMA(string sy, ENUM_TIMEFRAMES tf,
int period, int ma_shift,
ENUM_MA_METHOD method,
ENUM_APPLIED_PRICE price,
int shift)
{
// Step 1: force price data
if(!ForceRates(sy, tf))
return 0;
// Step 2: ensure series is synchronized
if(!IsSeriesReady(sy, tf))
return 0;
int h = GetMAHandle(sy, tf, period, ma_shift, method, price);
if(h == INVALID_HANDLE)
return 0;
// Step 3: ensure indicator is calculated
if(BarsCalculated(h) <= shift)
return 0;
double buf[];
ArraySetAsSeries(buf, true);
// Step 4: Copy safely
int copied = CopyBuffer(h, 0, shift, 1, buf);
if(copied != 1)
return 0;
return buf[0];
}
//Series check
bool IsSeriesReady(string sy, ENUM_TIMEFRAMES tf)
{
long sync = 0;
if(!SeriesInfoInteger(sy, tf, SERIES_SYNCHRONIZED, sync))
return false;
return (sync == 1);
}
//force rate
bool ForceRates(string sy, ENUM_TIMEFRAMES tf)
{
MqlRates rates[];
ArraySetAsSeries(rates, true);
int copied = CopyRates(sy, tf, 0, 10, rates);
return (copied > 0);
}