在多个图表中打开指标

时间:2016-12-21 13:27:16

标签: indicator algorithmic-trading metatrader4 mt4 metatrader5

我发现了一个有趣的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, "%"));
  }
//+------------------------------------------------------------------+

1 个答案:

答案 0 :(得分:0)

让我们将任务分成两部分:
第一部分:如何衡量时间。

Metatrader终端架构已将代码执行单元分为三种主要类型:
- {0|1} - 独特的ExpertAdvisor类型的MQL4代码,每MT4.graph
- {0|1|..|n} CustomIndicatero类型的MQL4代码,每MT4.graph
- {0|1} - 唯一的脚本类型的MQL4代码,每MT4.graph

使用越来越多的CustomIndicators听起来很有趣,但有一个问题。

Catch XXII。

所有CustomIndicators和所有ExpertAdvisors都会在市场活动消息到达时响应执行。这意味着,每当市场事件到来时,所有ExpertAdvisors和所有CustomIndicator都会被推送执行各自的处理(在ExpertAdvisor中调用OnTick(){...}函数,在CustomIndicator中调用OnCalculate(){...}函数)。这听起来仍然合理。 Catch XXII。隐藏在这一事实中,所有CustomIndicators 共享一条单线。是,全部!

这翻译成简单的英语意味着,避免一切可能阻止CustomIndicators并将其放在别处的东西,但是CustomIndicator MQL4代码。

使用 - MQL4.56789 EventSetTimer() - 设施并没有改善已经很明显的问题,只是恰恰相反,所以让我们来看看。忘记使用 OnTimer()

那么,如何安全地设计这样的功能?

可能的方法是使用低调的服务设计,部署在帮助 - (非交易)-MT4.graph中,以实现此类公用事业服务并最好地使用脚本(因为它绝对是在一个人的手中)控制,与任何事件触发的EA / CI代码执行异步,即使在市场关闭或与MetaTrader服务器的连接关闭期间也能安全可靠地工作。

这个"中央"时钟(时间设施)提供一个独特的参考时间并存储它,以便任何"消费者"在其他MT4.graphs。

// 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
}

第二部分。:如何以最轻量级的形式显示所有MT4.graphs中的时间?

鉴于中央服务部门负责列出相应的 ENUM_TIMEFRAMES (被其他MT4.graphs访问"访问"或未被其他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;
}

enter image description here