#property indicator_chart_window
#property indicator_buffers 3
#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrDodgerBlue
#property indicator_color3 clrDodgerBlue
#property indicator_style1 STYLE_SOLID
#property indicator_style2 STYLE_SOLID
#property indicator_style3 STYLE_DOT
// Input parameters of indicator
extern ENUM_TIMEFRAMES i_tf = PERIOD_D1; // Older TF / Старший ТФ
extern uint i_maPeriod = 3; // MA period / Период МА
extern int i_maShift = 0; // MA shift / Смещение МА
extern ENUM_MA_METHOD i_maMethod = MODE_EMA; // МА method / Метод МА
extern ENUM_APPLIED_PRICE i_maPrice = PRICE_TYPICAL; // MA price / Цена МА
extern int i_indBarsCount = 1000; // Show bars amount / Кол-во баров отображения
// Other global variables of indicator
bool g_activate; // Sign of successful initialization of indicator
string g_strTF;
double g_upEnvelope[];
double g_dnEnvelope[];
double g_mdEnvelope[];
double g_olderTFResValues[];
double g_olderTFSuppValues[];
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator initialization function |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnInit()
{
g_activate = false;
if (i_tf < (ENUM_TIMEFRAMES)Period())
{
Print("индикатор не работает на таймфреймах, не являющимися старшими по отношению к текущему таймфрейму.");
return INIT_SUCCEEDED;
}
if (!IsTuningParametersCorrect())
return INIT_FAILED;
if(!BuffersBind())
return INIT_FAILED;
g_strTF = TFToString(i_tf) + "_";
g_activate = true;
return INIT_SUCCEEDED;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Checking the correctness of input parameters |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTuningParametersCorrect()
{
string name = MQLInfoString(MQL_PROGRAM_NAME);
if (ArrayResize(g_olderTFResValues, i_maPeriod) < 0)
{
Alert(name, ": не удалось распределить память для массива. Индикатор отключен.");
return false;
}
if (ArrayResize(g_olderTFSuppValues, i_maPeriod) < 0)
{
Alert(name, ": не удалось распределить память для массива. Индикатор отключен.");
return false;
}
ArraySetAsSeries(g_olderTFResValues, true);
ArraySetAsSeries(g_olderTFSuppValues, true);
return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Bind the arrays with indicators buffers |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool BuffersBind()
{
string name = MQLInfoString(MQL_PROGRAM_NAME);
bool isRussianLang = (TerminalInfoString(TERMINAL_LANGUAGE) == "Russian");
if (!SetIndexBuffer(0, g_upEnvelope) ||
!SetIndexBuffer(1, g_dnEnvelope) ||
!SetIndexBuffer(2, g_mdEnvelope))
{
Alert(name,(isRussianLang)? ": ошибка связывания массивов с буферами индикатора. Ошибка №"+IntegerToString(GetLastError()) :
": error of binding of the arrays and the indicator buffers. Error N"+IntegerToString(GetLastError()));
return false;
}
//--- Set the type of indicator's buffer
for (int i = 0; i < 3; i++)
SetIndexStyle(i, DRAW_LINE);
SetIndexLabel(0, "Upper line");
SetIndexLabel(1, "Lower line");
SetIndexLabel(2, "Middley line");
return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Cast the timeframe value to the string |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
string TFToString(int tf)
{
switch(tf)
{
case PERIOD_M1: return "M1";
case PERIOD_M5: return "M5";
case PERIOD_M15: return "M15";
case PERIOD_M30: return "M30";
case PERIOD_H1: return "H1";
case PERIOD_H4: return "H4";
case PERIOD_D1: return "D1";
case PERIOD_W1: return "W1";
case PERIOD_MN1: return "MN1";
}
if (tf % PERIOD_MN1 == 0)
return "MN" + IntegerToString(tf / PERIOD_MN1);
if (tf % PERIOD_W1 == 0)
return "W" + IntegerToString(tf / PERIOD_W1);
if (tf % PERIOD_D1 == 0)
return "D" + IntegerToString(tf / PERIOD_D1);
if (tf % PERIOD_H1 == 0)
return "H" + IntegerToString(tf / PERIOD_H1);
return "M" + IntegerToString(tf / 60);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void OnDeinit(const int reason)
{
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Support the tf data in actual state |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool IsTFDataReady(ENUM_TIMEFRAMES tf)
{
iTime(NULL, tf, 1);
return GetLastError() == ERR_NO_ERROR;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Determination of bar index which needed to recalculate |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int GetRecalcIndex(int& total, const int ratesTotal, const int prevCalculated)
{
total = ratesTotal - 1;
if (i_indBarsCount > 0 && i_indBarsCount < total)
total = MathMin(i_indBarsCount, total);
if (prevCalculated < ratesTotal - 1)
{
InitializeBuffers();
return (total);
}
return (MathMin(ratesTotal - prevCalculated, total));
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Initialize of all indicator buffers |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void InitializeBuffers()
{
ArrayInitialize(g_upEnvelope, EMPTY_VALUE);
ArrayInitialize(g_dnEnvelope, EMPTY_VALUE);
ArrayInitialize(g_mdEnvelope, EMPTY_VALUE);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Process specified bar index |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
void ProcessBar(int barIndex)
{
int olderTFBarIndex = iBarShift(NULL, i_tf, iTime(NULL, 0, barIndex));
double typeValue = 0.0;
for (int i = (int)i_maPeriod - 1; i >= 0; i--)
{
int tfIndex = i + olderTFBarIndex;
typeValue = ((iHigh(NULL, i_tf, tfIndex) + iLow(NULL, i_tf, tfIndex) + iClose(NULL, i_tf, tfIndex)) * 2) / 3;
g_olderTFSuppValues[i] = typeValue - iHigh(NULL, i_tf, tfIndex);
g_olderTFResValues[i] = typeValue - iLow(NULL, i_tf, tfIndex);
}
g_upEnvelope[barIndex] = iMAOnArray(g_olderTFResValues, 0, i_maPeriod, i_maShift, i_maMethod, 0);
g_mdEnvelope[barIndex] = iMA(NULL, i_tf, i_maPeriod, i_maShift, i_maMethod, i_maPrice, olderTFBarIndex);
g_dnEnvelope[barIndex] = iMAOnArray(g_olderTFSuppValues, 0, i_maPeriod, i_maShift, i_maMethod, 0);
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Displaying of indicators values |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
bool ShowIndicatorData(int limit, int total)
{
int olderTFBarIndex = iBarShift(NULL, i_tf, iTime(NULL, 0, limit));
limit = iBarShift(NULL, 0, iTime(NULL, i_tf, olderTFBarIndex));
// Обработка новых баров
for (int i = limit; i >= 0; i--)
ProcessBar(i);
return true;
}
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
//| Custom indicator iteration function |
//+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime& time[],
const double& open[],
const double& high[],
const double& low[],
const double& close[],
const long& tick_volume[],
const long& volume[],
const int& spread[])
{
if (!g_activate)
return rates_total;
if (!IsTFDataReady(i_tf))
return rates_total;
int total;
int limit = GetRecalcIndex(total, rates_total, prev_calculated);
if (!ShowIndicatorData(limit, total))
g_activate = false;
return rates_total;
}
写法娴熟,可供借鉴
发表评论