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

 

초보자 질문이라 죄송합니다... 그렇다면 코드를 개발하려면 어느 쪽에 집중해야 하나요? 4 또는 5? 이해가 안 되는 것 같은데 거래 기능을 위해 5를 선택해야 하나요? MQL4보다 낫나요?

 
@rrb1002 #: 초보자 질문이라 죄송합니다... 그렇다면 코드를 개발하려면 어느 쪽에 집중해야 하나요? 4 또는 5? 이해가 안 되는 것 같은데 거래 기능을 위해 5를 선택해야 하나요? MQL4보다 낫나요?

글쎄, 선택은 당신의 것이지만, 누군가 나에게 이전 버전이 더 이상 개발되지 않고 모든 최신 개발이 최신 버전에 있다고 말하면 내 선택이 분명하다고 생각할 것입니다 (다른 상황이없는 한).

편집: 그러나 프로필에 미국에 거주한다고 나와 있으므로 어떤 브로커를 사용할 계획인지, 어떤 플랫폼을 제공하는지에 따라 달라질 수도 있습니다.
 

트레이딩, 자동매매 시스템 및 테스트 트레이딩 전략에 관한 포럼

mql5 언어의 특성, 미묘함 및 작업 기술

FXSABER, 2023.01.07 23:01

브로커에는 미국 / 유럽에서 시간을 번역하는 두 가지 유형이 있습니다. 이 때문에 특히 롤오버 시간이 이동합니다.

브로커 유형은 자동으로 결정할 수 있습니다.

// Вычисление типа брокера (USA/Europe).

bool IsEuropeBroker()
{
  MqlCalendarValue Value[1];
  
  CalendarValueHistoryByEvent(840030016, Value, D'2022.11.03', D'2022.11.05');
  
  return(Value[0].time == ChartNewsTime(Value[0].time)); // https://www.mql5.com/ru/forum/357793/page5#comment_44225999
}

void OnStart()
{
  Print(AccountInfoString(ACCOUNT_SERVER) + " - " + (IsEuropeBroker() ? "Europe" : "USA"));
}


일부 브로커에서 실행한 결과입니다.

RannForex-Server - Europe
MetaQuotes-Demo - Europe
FXOpen-MT5 - USA
Alpari-MT5 - Europe
Tickmill-Live - USA
ICMarketsSC-MT5-2 - USA
Darwinex-Live - USA

현재 스크립트는 상당히 다른 결과를 생성합니다. MT5 캘린더의 특성을 완전히 이해할 때까지는 사용하지 않는 것이 좋습니다.

 

MQL5의 매우 간단한 기술인 유형별 포지션/주문 인덱스를 암기하면 백테스트 속도를 무료로 높일 수 있습니다.


이전에 게시한 퀵 코드의 속도를 높인 예시입니다.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

input int inAmountMagics = 50; // Сколько ТС эмулировать

// Для каждой ТС открываем позицию и отложку. MT4-код для лаконичности.
void OnInit()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))  
    for (int i = 0; i < inAmountMagics; i++)
    {
      OrderSend(_Symbol, OP_BUY, 1, Tick.ask, 0, 0, 0, NULL, i);
      
      OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - 1 e4*_Point, 0, 0, 0, NULL, i);
    }
}

#define  MAX_ORDERS 100

// Индексы позиций/ордеров по типам.
struct TYPE_INDEXES
{
  int Index[OP_SELLSTOP + 1][MAX_ORDERS];
  int Amount[OP_SELLSTOP + 1];
  
  // Заполнение индексов.
  void Fill( void )
  {
    ::ArrayInitialize(this.Amount, 0);
    
    for (int i = ::PositionsTotal() - 1; i >= 0; i--)
      if (::PositionGetTicket(i))
      {
        const int Type = (int)PositionGetInteger(POSITION_TYPE);
        
        this.Index[Type][this.Amount[Type]++] = i;
      }

    for (int i = ::OrdersTotal(true) - 1; i >= 0; i--)
      if (::OrderGetTicket(i))
      {
        const int Type = (int)OrderGetInteger(ORDER_TYPE);
        
        this.Index[Type][this.Amount[Type]++] = i;
      }
      
    return;          
  }
};

#undef  MAX_ORDERS

// Сбор информации с нужных позиций/ордеров. Максимально быстрый MT5-код.
double CountOrders( const int Type, const int Magic, const TYPE_INDEXES &TypeIndexes )
{
  double Res = 0;
  
  if (Type <= OP_SELL)
  {
    for (int i = TypeIndexes.Amount[Type] - 1; i >= 0; i--)
      if (PositionGetTicket(TypeIndexes.Index[Type][i]) && PositionGetInteger(POSITION_MAGIC) == Magic)
        Res += PositionGetDouble(POSITION_PRICE_OPEN) + PositionGetDouble(POSITION_PRICE_CURRENT) +
               PositionGetDouble(POSITION_TP) + PositionGetDouble(POSITION_SL);
  }
  else
    for (int i = TypeIndexes.Amount[Type] - 1; i >= 0; i--)
      if (OrderGetTicket(TypeIndexes.Index[Type][i]) && OrderGetInteger(ORDER_MAGIC) == Magic)
        Res += OrderGetDouble(ORDER_PRICE_OPEN) + OrderGetDouble(ORDER_PRICE_CURRENT) +
               OrderGetDouble(ORDER_TP) + OrderGetDouble(ORDER_SL);
        
  return(Res);
}

// Число для контроля корректности альтернативных реализаций.
double OnTesterValue = 0;
double OnTester() { return(OnTesterValue); }

void OnTick()
{
  TYPE_INDEXES TypeIndexes; // Индексы позиций/ордеров по типам.
  
  TypeIndexes.Fill(); // Заполнение индексов.
  
  // Симулируем работу по всем ТС.
  for (int i = 0; i < inAmountMagics; i++)
    OnTesterValue += CountOrders(POSITION_TYPE_BUY, i, TypeIndexes) + 
                     CountOrders(POSITION_TYPE_SELL, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_BUY_LIMIT, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_SELL_LIMIT, i, TypeIndexes);  
}

포지션/주문을 유형별로 분할하는 것이 좋습니다.

 
MQL4 EA를 MQL5로 변환하는 방법은 무엇인가요?
 
더블에 가상의 0이 필요한 경우.
void OnStart()
{
  double d = 1;
  
  Print(d + d * 1 e-17 == d); // true
  Print(d * 1 e-17);
}
 
fxsaber #:
더블에 가상의 0이 필요한 경우.

DBL_EPSILON

1.0+DBL_EPSILON != 1.0 조건이 성립하는 가장 작은 수입니다.

2.2204460492503131e-016

 
Slava #:

DBL_EPSILON

1.0+DBL_EPSILON != 1.0 조건이 만족되는 가장 작은 숫자.

2.2204460492503131e-016

감사합니다!

 

DBL_EPSILON

1.0+DBL_EPSILON != 1.0 조건을 만족하는 가장 작은 숫자

2.2204460492503131e-016


러시아어를 할 줄 몰라 영어로 댓글을 달아 죄송합니다.

이것은 의미합니다:

d * (1 + DBL_EPSILON) != d
d * (1 + 0.5 * DBL_EPSILON) == d

DBL_EPSILON은 상대적 오류율이기 때문입니다. 상대적은 숫자의 크기에 상대적이라는 뜻입니다.

1.0에서 오류율 = 1 * 2 .2204460492503131e-016 (DBL_EPSILON)

d에서 오류율 = d * DBL_EPSILON .

컴퓨터는 d와 d * (1 + 0.5*DBL_EPSILON)을 구분할 수 없으므로 둘 다 동일한 바이너리로 인코딩합니다.
따라서 정확한 (이진) 비교에 대해 참을 얻습니다 ==.
 
Slava #:

DBL_EPSILON

1.0+DBL_EPSILON != 1.0 조건이 만족되는 가장 작은 숫자.

2.2204460492503131e-016

이것은 잘못된 설명입니다.

void OnStart()
{
  double d = 1 e5;
  
  Print(d + d * 0.1 == d * (1 + 0.1)); // false
}