我发现了一个有趣的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, "%"));
}
//+------------------------------------------------------------------+
答案 0 :(得分:0)
Metatrader终端架构已将代码执行单元分为三种主要类型:
- {0|1}
- 独特的ExpertAdvisor类型的MQL4代码,每MT4.graph
- {0|1|..|n}
CustomIndicatero类型的MQL4代码,每MT4.graph
- {0|1}
- 唯一的脚本类型的MQL4代码,每MT4.graph
使用越来越多的CustomIndicators听起来很有趣,但有一个问题。
所有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
}
鉴于中央服务部门负责列出相应的 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;
}