Experts: MQL5 Programming for Traders - 책의 소스 코드. 파트 6 - 페이지 2

 
Stanislav Korotky #:
주문, 거래, 포지션은 차트주기와 관련이 없습니다. 뭔가 잘못 이해했거나 표현이 잘못되었습니다.
제가"기간" 을 "날짜 범위"로 오해한 것 같아서 죄송합니다. 예를 들어 2025-10-01 00:00:00 ~ 2025-10-22 23:59:59의 거래와 같이 특정 날짜 범위 내에서 거래된 거래/주문을 선택하고 싶다고 가정해 보겠습니다.
 
pauldic #:
"기간" 이 "날짜 범위"를 의미하는 것 같아서 단어 선택이 헷갈려서 죄송합니다. 예를 들어 2025-10-01 00:00:00 ~ 2025-10-22 23:59:59의 거래와 같이 특정 날짜 범위 내에서 거래된 거래/주문을 선택하려고 한다고 가정해 보겠습니다.

거래 내역의 하위 범위를 분석하려는 경우, 필터링 코드 자체에 영향을 주지 않고 필터링 전에 이 부분만 요청하는 것이 더 효율적인 경우가 있습니다:

input datetime SubrangeFrom = 0;
input datetime SubrangeTo = 0;

...

{
   HistorySelect(SubrangeFrom, SubrangeTo);
   // ... 필터 코드가 여기에 그대로 들어갑니다.
}

어떤 이유로 인해 HistorySelect로 적용한 전체 범위 내에서 (더 좁은) 하위 범위를 선택하려는 경우에도 필터링 코드에서 다음과 같이 할 수 있습니다:

{
      // 일부는 여기로 이동합니다.

      // HistorySelect(0, LONG_MAX);
      // HistorySelectByPosition(PositionID);
      ...
      DealTuple deals[];
      if(SubrangeFrom != SubrangeTo && SubrangeFrom < SubrangeTo)
      {
         filter.let(DEAL_TIME, SubrangeFrom - 1, IS::GREATER).let(DEAL_TIME, SubrangeTo + 1, IS::LESS);
      }
      filter.let(DEAL_POSITION_ID, PositionID).select(deals, true);
      ...
}

노란색 선으로 강조 표시된 부분은 추가 한정자 IS::GREATER 및 IS::LESS를 사용하여 날짜 범위 [SubrangeFrom, SubrangeTo]에 대해 2개의 조건을 설정합니다(기본적으로 다른 let() 호출에서는 지정되지 않으며, 단일 값 필드에는 일반적으로 IS::EQUAL이 사용됨).

날짜 범위별로 하위 필터를 적용하는 이유는 주문의 설정 시간(ORDER_TIME_SETUP)을 위한 것인데, 이는 HistorySelect가 주문의 다른 날짜 시간 속성, 즉 주문 실행 시간(ORDER_TIME_DONE)에 적용되기 때문입니다. 또한 활성 주문이 많은 경우 내역이 아닌 하위 범위의 활성 주문을 필터링하는 것도 흥미로울 수 있습니다.

시작점으로 MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 예제 스크립트를 살펴볼 수 있습니다.
 
Stanislav Korotky #:

거래 내역의 하위 범위를 분석하려는 경우, 필터링 코드 자체에 영향을 주지 않고 필터링 전에 이 부분만 요청하는 것이 더 효율적인 경우가 있습니다:

어떤 이유로 인해 HistorySelect로 적용한 전체 범위 내에서 (더 좁은) 하위 범위를 선택하려는 경우에도 필터링 코드에서 다음과 같이 할 수 있습니다:

노란색 선으로 강조 표시된 부분은 추가 한정자 IS::GREATER 및 IS::LESS를 사용하여 날짜 범위 [SubrangeFrom, SubrangeTo]에 대해 2개의 조건을 설정합니다(기본적으로 다른 let() 호출에서는 지정되지 않으며, 단일 값 필드에는 일반적으로 IS::EQUAL이 사용됨).

날짜 범위별로 하위 필터를 적용하는 이유는 주문의 설정 시간(ORDER_TIME_SETUP)에 대한 것인데, 이는 HistorySelect가 주문의 다른 날짜 시간 속성, 즉 주문 실행 시간(ORDER_TIME_DONE)에 적용되기 때문입니다. 또한 활성 주문이 많은 경우 내역이 아닌 하위 범위의 활성 주문을 필터링하는 것도 흥미로울 수 있습니다.

시작점으로 MQL5/Scripts/MQL5Book/p6/TradeHistoryPrint.mq5 예제 스크립트를 살펴볼 수 있습니다.
스타니슬라프코로트키 다시 한 번 감사드립니다... 저에게는 훌륭한 출발점이며 작업을 시작할 것입니다.
 

MQL5/Include/MQL5Book/TradeUtils.mqh 버그 수정.

   bool Equal(const double v1, const double v2)
   {
      return v1 == v2 || fabs(v1 - v2) < DBL_EPSILON * fmax(1.0, fmax(fabs(v1), fabs(v2)));
   }
파일:
TradeUtils.mqh  12 kb
 
pauldic #:

코드를 삽입할 때는 코드 버튼(Alt-S) 을 사용합니다.

진행자가 잘못 붙여 넣은 코드의 서식을 지정했습니다. 일반적으로 이러한 코드는 제거됩니다.

이 오류를 조사해 주시겠어요? 이전 달에 코드가 수정 없이 작동한다는 것을 알았기 때문에 MT5 업데이트 이후에 시작된 것 같습니다.

매개변수 변환 유형 'long[][2]'에서 'string[][] &'로의 변환은 허용되지 않습니다 SymbolFilter.mqh 199 20

매개변수 변환 유형 'double[][2]'에서 'string[][] &'로의 변환은 허용되지 않습니다 TradeFilter.mqh 332 20
매개변수 변환 유형 'long[][2]'에서 'string[][] &'로의 변환은 허용되지 않음 TradeFilter.mqh 163 17


아래 코드가 이 문제를 재현하는 데 도움이 될 것 같습니다:


안녕하세요 @Paul Dick

배열을 정렬하려면 https://www.mql5.com/ko/code/57233 을 사용해보세요 .

Introsort (Introspective sort) using Function Pointers
Introsort (Introspective sort) using Function Pointers
  • 2025.03.18
  • www.mql5.com
A hybrid sorting algorithm that provide fast performance for sorting arrays of simple types, structures or object pointers.
 

가변 로트의 경우에 대한 계산이 수정된 R2 기반 사용자 지정최적화 기준의 계산 파일 업데이트 버전인 RSquared.mqh를 첨부합니다.

추정 품질이 크게 향상되었습니다. 최적화 결과 표를 보면 회복 계수와 샤프 매개변수의 조합을 얻을 수 있습니다.

사용 예시.

double OnTester()
{
   HistorySelect(0, LONG_MAX);
   
   #define  STAT_PROPS 5
   
   const ENUM_DEAL_PROPERTY_DOUBLE props[STAT_PROPS] =
   {
      DEAL_PROFIT, DEAL_SWAP, DEAL_COMMISSION, DEAL_FEE, DEAL_VOLUME
   };
   double expenses[][STAT_PROPS];
   ulong tickets[]; // 여기서는 '선택' 프로토타입과 일치시킬 때만 사용되지만 디버그에 유용합니다.
   
   DealFilter filter;
   filter.let(DEAL_TYPE, (1 << DEAL_TYPE_BUY) | (1 << DEAL_TYPE_SELL), IS::OR_BITWISE)
      .let(DEAL_ENTRY, (1 << DEAL_ENTRY_OUT) | (1 << DEAL_ENTRY_INOUT) | (1 << DEAL_ENTRY_OUT_BY), IS::OR_BITWISE)
      .select(props, tickets, expenses);

   const int n = ArraySize(tickets);
   
   double balance[];
   double volumes[]; // R2 기준을 사용하기 위해 거래량을 고려합니다.
   
   ArrayResize(balance, n + 1);
   balance[0] = 0;
   ArrayResize(volumes, n + 1);
   volumes[0] = 0;
   
   for(int i = 0; i < n; ++i)
   {
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j)
      {
         result += expenses[i][j];
      }
      // 볼륨을 모델로 사용 - 더 많은 투자 - 더 많은 수익 예상
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef  STAT_PROPS
   
   return r2 * 100;
}
파일:
RSquared.mqh  4 kb
 

최근에 프레임을 배우고 있는데, 여러분의 코드인 FrameTransfer.mq5를 테스트해 보았습니다. 이 줄이 현재 MT5 컴파일러에서 오류를 발생시키고 있습니다. 확인해 주세요: # 속성 tester_set "FrameTransfer.set"(잘못된 테스터 세트 파일 확장자, '*.set' 예상 FrameTransfer.mq5)

성공적으로 컴파일하려면 다음과 같이 변경해야 합니다: #프로퍼티 테스터 세트 "\\Presets\\FrameTransfer.set"

심지어 `#property tester_set "/Presets/FrameTransfer.set"`도 실패합니다.

아마도 알고리즘 책에서 설명을 수정할 수 있을 것입니다:


 
hini #property tester_set "FrameTransfer.set"(잘못된 테스터 세트 파일 확장자, '*.set'는 FrameTransfer.mq5로 예상됨).

성공적인 컴파일을 위해서는 다음과 같이 변경해야 합니다: #속성 테스터_설정 "\\Presets\\FrameTransfer.set"

속성 테스터_설정 "/Presets/FrameTransfer.set"`도 실패합니다.

아마도 알고리즘 책에서 설명을 변경할 수 있을 것입니다:


이것은 명백한 컴파일러 버그입니다. 코드에 "잘못된 테스터 세트 파일 확장자, '*.set'가 예상됩니다"라는 오류를 표시합니다:

#property tester_set "FrameTransfer.set"

파일에 필요한 확장자가 있는 경우입니다. 파일 위치 경로는 이 오류와 아무 관련이 없습니다.

이 버그는 적어도 2024년부터 오랫동안 존재해 왔습니다. 왜 MQ가 이 문제를 해결하지 않는지 모르겠습니다.

책 편집의 경우 이 경우에는 필요하지 않지만 어쨌든 책은 이제 완전히 MQ의 통제하에 있습니다.

 
Stanislav Korotky 통제하에 있습니다.
확인 및 보고했습니다. 수정될지 지켜보겠습니다.
 
Stanislav Korotky #:

이것은 명백한 컴파일러 버그이며 오류가 발생합니다: 코드에 "잘못된 테스터 세트 파일 확장자, '*.set'가 예상됩니다."라는 오류가 발생합니다:

감사합니다, 수정되었습니다!

메타에디터 버전을 계속 사용하려면 파일 이름 끝에 0을 추가하세요: "myset.set\0"