簡體   English   中英

如何在 MetaTrader4 終端中獲取當前毫秒數?

[英]How to get current milliseconds in MetaTrader4 Terminal?

如何使用智能交易系統從 MQL4 獲取當前毫秒數。

即:在 Java 中,我們可以使用system.currenttimemillis()獲取當前毫秒數

這個MT4“獲取毫秒”問題已經存在了很長時間。 這是我為解決此問題而創建的一種方法。

//+------------------------------------------------------------------+
//|                                                     timeInMs.mq4 |
//|                                       Copyright 2017, Joseph Lee |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Joseph Lee"
#property link      "https://www.facebook.com/joseph.fhlee"
#property version   "1.00"
#property strict

int     prevSecondTime      = 0;
uint    prevSecondTick      = 0;


int OnInit()    {
    //Create an Event that triggers every 1 millisecond.
    // **NOTE: GetTickCount() is accurate to +-16ms only, so
    // in practice, no need to trigger every 1ms.
    EventSetMillisecondTimer(1);
    return(INIT_SUCCEEDED);
}

void OnTick() {
    Comment( "Now: " + TimeLocal() + " :: " + getCurrentMs() + " ms. +- 16ms accuracy.");
}

int getCurrentMs() {
    return(GetTickCount() - prevSecondTick);
}

//This is an EVENT function that will be called every
// x millisecond(s) [as stated in teh EventSetMillisecondTimer()
// in the OnInit()
void OnTimer() {
    //If a new "second" occurs, record down the GetTickCount()
    if(TimeLocal() > prevSecondTime) {
        prevSecondTick  = GetTickCount();
        prevSecondTime  = TimeLocal();
    }
}

可以有相對[ms]甚至[us]:

要小心,因為兩者都是相對的,但是一個相對於系統啟動,另一個相對於MQL4代碼執行單元啟動。

GetTickCount()函數返回自系統啟動以來經過的毫秒數

uint GetTickCount();

計數器受系統計時器的限制。 時間存儲為無符號整數,因此,如果計算機不間斷地工作,則每49.7天就會溢出一次。


GetMicrosecondCount()函數返回自MQL程序啟動以來經過的微秒數。

ulong GetMicrosecondCount();


可以是絕對[ms]甚至是[us],帶有const(!)絕對錯誤,

在精確的時間測量中不會顯示任何漂移或抖動。

對於FOREX域來說,這不是很好嗎?在這里,毫秒是“充滿事件”的時間,而微秒(在最近的專業級設計中為納秒)很重要?

// -----------------------------------------------------------------
ulong system_currenttimemillis(){
      return(   OnStart_GLOB_MILLISECONDS       // ABS [ms] SYNC-ed OnStart() WITH [s]-EDGE-ALIGNMENT
            + (           GetMicrosecondCount() // + DELTA ------------------
              - OnStart_BASE_MICROSECONDS       //   since SYNC-ing OnStart()
                ) / 1000 // =================== //   DELTA [ms] =============
              );
}
// -----------------------------------------------------------------
static ulong    OnStart_GLOB_MICROSECONDS;
static ulong    OnStart_GLOB_MILLISECONDS;
static ulong    OnStart_EoDY_MICROSECONDS;
static datetime OnStart_EoDY_DATETIME;
static datetime OnStart_BASE_DATETIME;
static uint     OnStart_BASE_MILLISECONDS;
static ulong    OnStart_BASE_MICROSECONDS;
// -----------------------------------------------------------------
void            OnStart(){ /* { SCRIPT | EXPERT ADVISOR | CUSTOM INDICATOR } CALL
                                                                             THIS */
                OnStart_BASE_DATETIME      = TimeLocal();           // .SET int == the number of seconds elapsed since January 01, 1970.
         while( OnStart_BASE_DATETIME     == TimeLocal() ){ // ---- // EDGE-ALIGNMENT -------------------------------------------------------
                OnStart_BASE_MICROSECONDS  = GetMicrosecondCount(); //      .SET ulong, since MQL4 program launch
                OnStart_BASE_MILLISECONDS  = GetTickCount();        //      .SET uint,  since system start
         } // ==[ MAX 1 SECOND ]=============================== NOW // EDGE-ALIGNED TO [s] ==================================================
                OnStart_BASE_DATETIME      = TimeLocal();           // .SET date and time as the number of seconds elapsed since January 01, 1970.
                OnStart_GLOB_MICROSECONDS  = (       (ulong) OnStart_BASE_DATETIME ) * 1000000;
                OnStart_GLOB_MILLISECONDS  = (       (ulong) OnStart_BASE_DATETIME ) * 1000;
                OnStart_EoDY_DATETIME      =                 OnStart_BASE_DATETIME
                                           - (               OnStart_BASE_DATETIME % 86400 );
                OnStart_EoDY_MICROSECONDS  = (   TimeSecond( OnStart_BASE_DATETIME )
                                             + ( TimeMinute( OnStart_BASE_DATETIME )
                                               + TimeHour(   OnStart_BASE_DATETIME ) * 60 ) * 60 ) * 1000000;
}
// -----------------------------------------------------------------
int OnInit()    {
    OnStart();             /*   HACK 4 { EXPERT ADVISOR | CUSTOM INDICATOR } CALL
    ...                                                                      THAT */
    ..
    return( INIT_SUCCEEDED );
}
// -----------------------------------------------------------------
ulong Get_a_Microsecond_of_a_Day(){           // THIS HAS A !!_CONSTANT_!! ONLY ABSOLUTE SYSTEMATIC TIMING ERROR
      return( (   OnStart_EoDY_MICROSECONDS   // EDGE-SYNC OnStart_EoDY + DELTA-SINCE-OnStart-SYNC-ed:
              + (           GetMicrosecondCount()                       // == NOW ( 8B ulong ) ROLL-OVER ~ 213M504 DAYS AFTER THE PROGRAM START, WAY LONGER, THAN WE WILL LIVE UNDER THE SUN
                - OnStart_BASE_MICROSECONDS   //                        //  - OnStart_BASE_MICROSECONDS
                  )
                ) // ================== // SECONDS-EDGE-SYNC-ed DISTANCE FROM EoDY-EDGE
              % 86400000000             // MODULO DAY-LENGTH ROLL-OVER
              );                        // ALL DST-MOVs TAKE PLACE OVER WEEKENDS, SO NOT DURING TRADING-HOURS, SHOULD BE JUST-ENOUGH GOOD SOLUTION :o)
}
// -----------------------------------------------------------------
uint Get_a_Millisecond_of_a_Day(){      // IMMUNE TO A uint ROLL-OVER ~ 49.7 DAYS
     return( Get_a_Microsecond_of_a_Day()
           / 1000
             );
}

+此解決方案可在所有{腳本| 專家顧問| 自定義指標}

像這樣的東西:

ulong time = GetTickCount(); // function(); time = GetTickCount()-time;

dt1 = TimeLocal()+2;
do
{
  dt2 = TimeLocal();
}
while(TimeSecons(dt2) < TimeSecons(dt1));

完成后,您可以從0.000開始計時

只需將值轉換為ulong並確保將TimeGMT()乘以1000

將打印結果轉換為string

ulong time = (ulong) TimeGMT()*1000 - (ulong) GetTickCount() ; 
Print("milliseconds: ",  (string)time);

另一種方法似乎是使用 WinAPI ( kernel32.dll )。 這似乎通過使用#include <WinAPI/windef.mqh>與 MQL5 集成得更好,但也可以通過定義所需的結構與 MQL4 一起使用。

以下片段顯示了如何在 MQL4 中獲取它——在 MQL5 中,您不需要定義結構,因為它們可以包含在內:

// MQL5 seems to have Include/WinAPI/windef.mqh - constants, structures and enumerations
#ifdef __MQL4__
//+------------------------------------------------------------------+
//| MQL4 equivalent of Windows _FILETIME struct: GetSystemTimeAsFileTime().
//| @see: https://learn.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-filetime
//+------------------------------------------------------------------+
struct FILETIME {
  uint dwLowDateTime;
  uint dwHighDateTime;
};

//+------------------------------------------------------------------+
//| MQL4 equivalent of Windows GetSystemTime()/GetLocalTime()/... struct.
//| Credits: https://www.mql5.com/en/forum/146837/page3#comment_3702187
//+------------------------------------------------------------------+
struct SYSTEMTIME {
  ushort wYear;         // 2014 etc
  ushort wMonth;        // 1 - 12
  ushort wDayOfWeek;    // 0 - 6 with 0 = Sunday
  ushort wDay;          // 1 - 31
  ushort wHour;         // 0 - 23
  ushort wMinute;       // 0 - 59
  ushort wSecond;       // 0 - 59
  ushort wMilliseconds; // 0 - 999

  string toString() {
    return StringFormat("%hu-%02hu-%02hu %02hu:%02hu:%02hu.%03hu", wYear, wMonth, wDay, wHour, wMinute, wSecond, wMilliseconds);
  }
};
#endif

#import "kernel32.dll"
  // Millisecond (ms) precision, but limited by Windows timer configuration?? (15-16 ms by default)
  void GetSystemTime(SYSTEMTIME &time); // (struct version)
  void GetLocalTime(SYSTEMTIME &time); // (struct version)
  // Microsecond (us) precision, limited by Windows timer configuration?? (15-16 ms by default)
  void GetSystemTimeAsFileTime(FILETIME& t); // (ulong version) Returns the system time in 100-nsec units
#import

然后你可以定義用戶友好的函數來獲得上述的時間,例如

//+------------------------------------------------------------------+
//| Get the system time (UTC) in milliseconds.
//| Credits: https://www.mql5.com/en/forum/146837/page4#comment_13522420
//+------------------------------------------------------------------+
ulong systemTimeMillis(){
  FILETIME t; // time measured in 100-nano second units
  GetSystemTimeAsFileTime(t);
  ulong time = (long)t.dwHighDateTime << 32 | t.dwLowDateTime;
  ulong diffTo1970 = 11644473600000; // FILETIME starts at January 1, 1601 (UTC)
  return (ulong)(time * 0.0001 - diffTo1970); // 100-ns to ms (divide 10_000)
}

ulong localTimeMillis() {
  return systemTimeMillis() - TimeGMTOffset() * 1000;
}

更多參考資料

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM