Открытие индикатора на нескольких графиках

Я нашел интересный индикатор MT4, который показывает оставшееся время следующего бара на графике. Но это работает для конкретных пар, которые я бы выбрал.

Но я хочу, чтобы эта программа работала/применялась ко всем открытым парам, просто применяя их к любой из открытых пар.

Пожалуйста, проверьте код ниже::::

//--- input parameters
input string LabelFont = "Arial";
input int LabelSize = 15;
input color LabelColor = clrRed;
input int LabelDistance = 15;
const string LabelName = "TimeToNextCandle";
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   EventSetTimer(1);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   EventKillTimer();
   ObjectDelete(0, LabelName);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
//---
   CalcTime();
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
   CalcTime();
  }
//+------------------------------------------------------------------+
void CalcTime(void)
  {
   // checking is there output label. create it if necessary
   if (ObjectFind(LabelName) == -1)
   {
      ObjectCreate(0, LabelName, OBJ_LABEL, 0, 0, 0);
      ObjectSetString(0, LabelName, OBJPROP_FONT, LabelFont);
      ObjectSetInteger(0, LabelName, OBJPROP_FONTSIZE, LabelDistance);
      ObjectSetInteger(0, LabelName, OBJPROP_COLOR, LabelColor);
      ObjectSetInteger(0, LabelName, OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
      ObjectSetInteger(0, LabelName, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
      ObjectSetInteger(0, LabelName, OBJPROP_XDISTANCE, LabelDistance);
      ObjectSetInteger(0, LabelName, OBJPROP_YDISTANCE, LabelDistance);
   }
   // calculating remaining time to next candle
   datetime TimeTo = PeriodSeconds() - (TimeCurrent() - Time[0]);
   // assembling the output string depending on current period on the chart
   string Out = StringFormat("%.2d", TimeSeconds(TimeTo));
   if (TimeTo >= 3600)
   {
      Out = StringFormat("%.2d:%s", TimeMinute(TimeTo), Out);
      if (TimeTo >= 86400)
        Out = StringFormat("%d day(s) %.2d:%s", int(TimeTo / 86400), TimeHour(TimeTo), Out);
      else
        Out = StringFormat("%d:%s", TimeHour(TimeTo), Out);
   }
   else
     Out = StringFormat("%d:%s", TimeMinute(TimeTo), Out);
   ObjectSetString(0, LabelName, OBJPROP_TEXT, StringFormat("%s (%.0f%s)", Out, 100.0 / PeriodSeconds() * TimeTo, "%"));
  }
//+------------------------------------------------------------------+

person user346910    schedule 21.12.2016    source источник


Ответы (1)


Давайте разделим задачу на две части:
Часть I.
Как измерить время.

В архитектуре терминала Metatrader блоки исполнения кода разделены на три основных типа:
- {0|1}-уникальный экспертный тип кода MQL4, согласно MT4.graph
- {0|1|..|n}< /strong> CustomIndicatero-тип MQL4-кода, согласно MT4.graph
- {0|1}-уникальный Script-тип MQL4-кода, согласно MT4.graph

Может показаться интересным использовать все больше и больше CustomIndicators, но есть одна загвоздка.

Поймай XXII.

Все CustomIndicators и все ExpertAdvisors мгновенно исполняются при поступлении сообщения о рыночном событии. Это означает, что всякий раз, когда приходит рыночное событие, все советники и все пользовательские индикаторы подталкиваются к выполнению соответствующей обработки (функция OnTick(){...} вызывается в советнике(ах), функция OnCalculate(){...} вызывается в пользовательских индикаторах). Это все еще звучит разумно. Уловка XXII. скрывается в том факте, что все CustomIndicators должны использовать ОДНУ ПОТОК. Да, ВСЕ !

Это в переводе на простой английский означает: избегайте всего, что может заблокировать из CustomIndicators, и поместите это в другое место, кроме MQL4-кода CustomIndicator.

Использование Новых-MQL4.56789 EventSetTimer()-возможностей не устраняет и без того очевидную проблему, а совсем наоборот, поэтому давайте забудем об использовании OnTimer().


Итак, как безопасно спроектировать такую ​​функцию?

Возможный способ — использовать низкопрофильный сервисный дизайн, развернутый во вспомогательном (неторговом) MT4.graph для такого сервисного сервиса и лучше всего использовать скрипт (поскольку он полностью под вашим контролем, асинхронный с любым событием). запускает выполнение кода EA / CI и работает в целости и сохранности, даже когда рынок закрыт или отсутствует соединение с сервером MetaTrader).

Эти «центральные» часы (устройство синхронизации) обеспечивают уникальное эталонное время и сохраняют его, чтобы оно было доступно любому «потребителю» на других графиках MT4.

// MQL4-Script
double assembleGV( int aTimeNOW,
                   int aPERIOD
                   ){

#define BrokerServerGMToffset 0                 // Yes, Real World isn't perfect :o)

       int aTimeToEoB = PeriodSeconds( aPERIOD ) - ( aTimeNOW - ( iTime( _Symbol, aPERIOD, 0 ) - BrokerServerGMToffset ) );
       return( aTimeToEoB + aTimeToEoB / PeriodSeconds( aPERIOD ) );                                // INT + FRAC ( non-%, but having the value of the remainder )
}

while True{
      Sleep( 250 ); int TimeNow = TimeGMT();
   // -------------------------------------- COOL DOWN CPU-CORE(s)
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=60",       assembleGV( TimeNow, PERIOD_M1  ) ); // for PERIOD_M1
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=300",      assembleGV( TimeNow, PERIOD_M5  ) ); // for PERIOD_M5 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=900",      assembleGV( TimeNow, PERIOD_M15 ) ); // for PERIOD_M15
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=1800",     assembleGV( TimeNow, PERIOD_M30 ) ); // for PERIOD_M30
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=3600",     assembleGV( TimeNow, PERIOD_H1  ) ); // for PERIOD_H1 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=14400",    assembleGV( TimeNow, PERIOD_H4  ) ); // for PERIOD_H4 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=86400",    assembleGV( TimeNow, PERIOD_D1  ) ); // for PERIOD_D1 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=604800",   assembleGV( TimeNow, PERIOD_W1  ) ); // for PERIOD_W1 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=2592000",  assembleGV( TimeNow, PERIOD_MN1 ) ); // for PERIOD_MN1

      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=120",      assembleGV( TimeNow, PERIOD_M2  ) ); // for PERIOD_M2 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=180",      assembleGV( TimeNow, PERIOD_M3  ) ); // for PERIOD_M3 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=240",      assembleGV( TimeNow, PERIOD_M4  ) ); // for PERIOD_M4 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=360",      assembleGV( TimeNow, PERIOD_M6  ) ); // for PERIOD_M6 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=600",      assembleGV( TimeNow, PERIOD_M10 ) ); // for PERIOD_M10
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=720",      assembleGV( TimeNow, PERIOD_M12 ) ); // for PERIOD_M12
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=1200",     assembleGV( TimeNow, PERIOD_M20 ) ); // for PERIOD_M20
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=7200",     assembleGV( TimeNow, PERIOD_H2  ) ); // for PERIOD_H2 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=10800",    assembleGV( TimeNow, PERIOD_H3  ) ); // for PERIOD_H3 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=21600",    assembleGV( TimeNow, PERIOD_H6  ) ); // for PERIOD_H6 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=28800",    assembleGV( TimeNow, PERIOD_H8  ) ); // for PERIOD_H8 
      GlobalVariableSet( "msMOD_TimeSERVICE_4_PERIOD=43200",    assembleGV( TimeNow, PERIOD_H12 ) ); // for PERIOD_H12
}

Часть II.:
Как отображать время на всех графиках MT4.
в максимально облегченном виде?

Учитывая, что центральная служба заботится о соответствующих списках ENUM_TIMEFRAMES ("посещенных" или нет другими MT4.graphs) и публикует предварительно сфабрикованные результаты такого исчисления "временной службы",
любой потенциальный "потребитель"
может просто асинхронно проверять и реагировать на опубликованные значения "службы времени"
в местах, где это возможно и безопасно в соответствующем потоке выполнения кода, а пользователи находятся под полным контролем, чтобы объявить , где может появиться такой облегченный вызов GUI и где все обновления могут извлечь выгоду из (потенциально отложенного) принудительного перерисовки GUI:

/* MQL4-ExpertAdvisor
      or
        other Script
      or even
        a lightweight add-on to a CustomIndicator */

#define LabelNAME          "msMOD_StackOverflowDEMO"

bool    aDeferred_GUI_REPAINT = False;
.
..
RepaintTIME();
..
.
if (  aDeferred_GUI_REPAINT ){
      aDeferred_GUI_REPAINT = False;
      WindowRedraw();
}

void RepaintTIME(){
     static string aGlobalVariableNAME = "msMODmsMOD_TimeSERVICE_4_PERIOD=" + (string)PeriodSeconds();

     ObjectSetString( 0,
                      LabelNAME,            // external responsibility to set/create
                      OBJPROP_TEXT,
                      StringFormat( "%d (%.0f %%)",
                                     int( GlobalVariableGet( aGlobalVariableNAME ) ),                       // SECONDS TILL EoB
                                     (    GlobalVariableGet( aGlobalVariableNAME ) % 1 ) * 100.0 )          // PER CENTO [%] EXPRESSED REMAINDER
                      );
     aDeferred_GUI_REPAINT = True;
}

введите здесь описание изображения

person user3666197    schedule 31.12.2016