mql5 언어의 특징, 미묘함 및 작업 방법 - 페이지 209

 

이전에 게시된 다른 하나 ( 하나 ,   2 ) 무역 서버의 GMT 오프셋을 결정하는 방법.

 #define HOUR 3600
#define DAY ( 24 * HOUR)
#define WEEK 7

bool GetWeekSession( const string Symb, datetime &From, datetime &To )
{
   datetime Tmp;
  
  From = 0 ;
  To = 0 ;
  
   for ( int i = 0 ; i < 7 ; i++)
     if (:: SymbolInfoSessionQuote (Symb, ( ENUM_DAY_OF_WEEK )i, 0 , From, Tmp) && (From != Tmp))
    {
      From += (i + WEEK - 1 ) * DAY;
      
       break ;
    }

   for ( int i = 6 ; i >= 0 ; i--)
     if (:: SymbolInfoSessionQuote (Symb, ( ENUM_DAY_OF_WEEK )i, 0 , Tmp, To) && (To != Tmp))
    {
      To += ((i + WEEK - 1 ) % WEEK) * DAY;
      
       break ;
    }
  
   return (From != To);
}

// Аналог по серверному времени - https://www.mql5.com/ru/docs/dateandtime/timegmtoffset
// Работает для FOREX-символов.
int TimeServerGMTOffset( void )
{
   const datetime Sunday = (WEEK - 1 ) * DAY;
  
   datetime From;
   datetime To;        
  
   return (GetWeekSession( _Symbol , From, To) ? (( int ):: MathRound (( double ):: MathMin (Sunday - DAY - To, Sunday + DAY - From) / HOUR) - 3 ) * HOUR : 0 );
}

세 가지 방법 모두의 공생은 올바른 결과를 얻을 수 있는 매우 높은 확률을 제공합니다.

 

롤오버 테마의 연속. M1 기록에서 롤오버 시간을 식별하려고 합니다.

 #define HOUR 3600
#define HOURS 24
#define DAY (HOURS * HOUR)
#define WEEK 7
#define MINUTE 60

ENUM_DAY_OF_WEEK TimeDayOfWeek( const datetime time )
{
   return (( ENUM_DAY_OF_WEEK )((time / DAY + THURSDAY ) % WEEK));
}

datetime GetTimeDayOfWeek( const datetime time, const ENUM_DAY_OF_WEEK Day = SUNDAY )
{
   const datetime Res = time / DAY * DAY;
  
   return (Res - (((WEEK + (TimeDayOfWeek(Res) - Day)) % WEEK)) * DAY);
}

#define GETHOUR(A) ( int )((A.time / HOUR) % HOURS)
#define GETMINUTE(A) ( int )((A.time / MINUTE) % MINUTE)

int GetTimePos( const MqlRates &Rates[], const datetime time )
{
   int Left = 0 ;
   int Right = ArraySize (Rates) - 1 ;  
      
   while (Right > Left)
  {            
     const int Middle = (Left + Right) >> 1 ;  
        
     if (Rates[Middle].time < time)
      Left = Middle + 1 ;
     else
      Right = Middle - 1 ;
  }
  
   return (Left);
}

int GetRolloverInterval( const MqlRates &Rates[], const datetime From, const datetime To, const bool MQL4Method = false )
{
   double Hours[HOURS];  
   ArrayInitialize (Hours, 0 );
        
   const int FromPos = GetTimePos(Rates, From);
   const int ToPos = GetTimePos(Rates, To);
  
   for ( int i = FromPos; i < ToPos; i++)
  {
   const int HourNow = GETHOUR(Rates[i]);
  
   #ifdef __MQL5__
     if (!MQL4Method) // Битые баровые спреды - проблема.
      Hours[HourNow] += (((HourNow != GETHOUR(Rates[i - 1 ])) ? GETMINUTE(Rates[i]) : 0 ) +
                         ((HourNow != GETHOUR(Rates[i + 1 ])) ? MINUTE : GETMINUTE(Rates[i + 1 ])) -
                         GETMINUTE(Rates[i])) * Rates[i].spread;
     else
   #endif // #ifdef __MQL5__
    Hours[HourNow] += (Rates[i].high - Rates[i].low) / Rates[i].tick_volume;            
  }
  
   return ( ArrayMaximum (Hours));
  
}

// Возвращает время ролловера FOREX-символа на указанной неделе (кроме текущей).
datetime RolloverTime( const datetime time, const string Symb = NULL , const bool MQL4Method = false )
{  
   int Hours[HOURS];
   ArrayInitialize (Hours, 0 );  
  
   MqlRates Rates[];    

   datetime From = GetTimeDayOfWeek(time);
   datetime To = GetTimeDayOfWeek(time) + WEEK * DAY - 1 ;

   if ( CopyRates (Symb, PERIOD_M1 , From, To, Rates) > 0 )
  {
   #define OFFSET 3
    From = (Rates[ 0 ].time / HOUR - OFFSET) * HOUR;
    To = From + ((OFFSET << 1 ) - 1 ) * HOUR;
   #undef OFFSET
    
     for ( int Count = 0 ; Count < 4 ; Count++)
      Hours[GetRolloverInterval(Rates, From += DAY, To += DAY, MQL4Method)]++;
  }
                                    
   return ( ArrayMaximum (Hours) * HOUR);
}

#undef GETMINUTE
#undef GETHOUR


애플리케이션.

 // Через Тестер выводит по неделям данные по времени ролловера.
const bool Init = EventSetTimer (WEEK * DAY);

void OnTimer ()
{
   const datetime time = TimeTradeServer () - WEEK * DAY;
   const datetime From = GetTimeDayOfWeek(time, MONDAY );
  
   Print (( string ) TimeToString (From, TIME_DATE ) + " - " + ( string ) TimeToString (From + WEEK * DAY - 1 , TIME_DATE ) +
         ": RolloverTime = " + TimeToString ( RolloverTime(time) , TIME_MINUTES ));
}


결과.

 2021.03 . 01 - 2021.03 . 07 : RolloverTime = 00 : 00
2021.03 . 08 - 2021.03 . 14 : RolloverTime = 00 : 00
2021.03 . 15 - 2021.03 . 21 : RolloverTime = 23 : 00
2021.03 . 22 - 2021.03 . 28 : RolloverTime = 23 : 00
2021.03 . 29 - 2021.04 . 04 : RolloverTime = 00 : 00
2021.04 . 05 - 2021.04 . 11 : RolloverTime = 00 : 00
 

최소 계산의 특징. 많은.

 double NormalizeDouble ( const double Value, const double Step )
{
   return ( NormalizeDouble (Step ? ( int )(Value / Step + 0.1 ) * Step : Value, 8 ));
}

// Минимальный лот с учетом требования мин. объема.
double GetMinLot( const string Symb, const double MinValue = 0 )
{
   const double MinLot = SymbolInfoDouble (Symb, SYMBOL_VOLUME_MIN )       ;
   double Res = MinLot;
  
   if (MinValue)
  {
     const double Diff = SymbolInfoDouble (Symb, SYMBOL_ASK ) * SymbolInfoDouble (Symb, SYMBOL_TRADE_TICK_VALUE );
    
    Res = Diff ? MinValue * SymbolInfoDouble (Symb, SYMBOL_TRADE_TICK_SIZE ) / Diff : 0 ;
    
     if (Res <= MinLot)
      Res = MinLot;
     else
    {
       double StepLot = SymbolInfoDouble (Symb, SYMBOL_VOLUME_STEP );      
      
       if (!StepLot)
        StepLot = MinLot;
      
       const double NormRes = NormalizeDouble (Res, StepLot);
      
      Res = (NormRes < Res) ? NormalizeDouble (NormRes + StepLot, 8 ) : NormRes;                                                                  
    }
  }             

   return (Res);
}


예(RannForex -Binance_futures ).

 void OnStart ()
{
   for ( int i = SymbolsTotal ( true ) - 1 ; i >= 0 ; i--)
  {
     const string Symb = SymbolName (i, true );
    
     Print (Symb + ", MinLot =  " + ( string ) GetMinLot(Symb, 5 ) );
  }
}


XMRUSDT.fut, MinLot =   0.019
XRPUSDT.fut, MinLot =   4.7
TRXUSDT.fut, MinLot =   51.0
LTCUSDT.fut, MinLot =   0.027
FTMUSDT.fut, MinLot =   2.0
ETHUSDT.fut, MinLot =   0.002
EOSUSDT.fut, MinLot =   1.1
BNBUSDT.fut, MinLot =   0.02
BCHUSDT.fut, MinLot =   0.008
BTCUSDT.fut, MinLot =   0.001
Спецификации фьючерсных контрактов USDⓈ-Margined | Binance
Спецификации фьючерсных контрактов USDⓈ-Margined | Binance
  • www.binance.com
Фьючерсные контракты USDT-margined не являются инверсными. Это линейные фьючерсные продукты, которые котируются и рассчитываются в BUSD или USDT – стейблкоинах, привязанных к доллару США. Одним из ...
 

이것은 MQL5의 기능입니까 아니면 버그입니까?

 void OnStart ()
{     
   uchar ArrayDst1[];
   uchar ArraySrc1[];
  
   ArrayCopy (ArrayDst1, ArraySrc1, 10 );
   Print ( ArraySize (ArrayDst1)); // MQL4 - 10, MQL5 - 0

   uchar ArrayDst2[];
   uchar ArraySrc2[ 1 ];

   ArrayCopy (ArrayDst2, ArraySrc2, 10 );
   Print ( ArraySize (ArrayDst2)); // 11
      
   return ;
}
 

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

mql5 언어의 특징, 미묘함 및 작업 방법

A100 , 2021.05.20 13:43

차이점은 일반 함수(오른쪽에서 왼쪽으로)와 인라인 함수(불확정 순서)가 있다는 것입니다.

인라인 함수는 전혀 함수가 아닙니다. 그들은 주소가 없습니다. 이러한 관점에서 보면 표준과 사용자 함수 사이에는 차이가 없습니다. 따라서 예를 들어 가장 단순한 사용자 함수(본질적으로 인라인임)가 항상 오른쪽에서 왼쪽으로 인수를 계산하는 이유는 명확하지 않습니다. 앞으로 인라인 함수의 순서가 변경될 수 있다는 점을 배제하지 않습니다. 따라서

계산 순서를 안전하게 사용하기 위해 인라인 키워드를 도입할 것을 제안한 적이 있습니다.


현재 MQL5에서 특정 기능에 대한 인라인을 비활성화할 수 있습니까?

 
안녕 왜 그래

 
MqlTick Ticks[4] = {}; // Обнуление статического массива.
 
fxsaber # :

다음과 같은 이유로 의미가 없습니다.

 struct X {
    int i;
};
void OnStart ()
{
    X x[ 200000 ] = {};
}

F5가 멈춥니다. 또한 이것은 논란 의 여지가 있는 생성자 우회입니다.

 
A100 # :

다음과 같은 이유로 의미가 없습니다.

F5가 멈춥니다.

이해하지 못했습니다. 영점 조정은 유용한 것이므로 의미가 있습니다.