2

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

1 回答 1

0

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

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

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

抓住二十二。

所有 CustomIndicators 和所有 ExpertAdvisor 都会在市场事件消息到达时响应地执行。这意味着,每当市场事件到达时,所有 ExpertAdvisor 和所有 CustomIndicator 都会被推送以执行它们各自的处理(OnTick(){...}在 ExpertAdvisor(s)OnCalculate(){...}中调用函数,在 CustomIndicator 中调用函数)。这听起来还是有道理的。渔获二十二。隐藏在所有 CustomIndicators共享一个单一线程的事实中。是的,所有!

这翻译成简单的英语意味着,避免所有可能阻止 CustomIndicators 并将其放在其他地方的东西,但 CustomIndicator MQL4 代码除外。

使用New --facilities并没有改善已经很明显的问题,恰恰相反,所以让我们忘记使用.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
}

Part II.:
如何以
最轻量级的形式在所有MT4.graphs中显示时间?

鉴于中央服务负责处理各个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;
}

在此处输入图像描述

于 2016-12-31T19:13:44.293 回答