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

 
hini 속성 tester_set "FrameTransfer.set"(잘못된 테스터 세트 파일 확장자, '*.set' 예상 FrameTransfer.mq5)

성공적으로 컴파일하려면 다음과 같이 변경해야 합니다: #속성 tester_set "\\Presets\\FrameTransfer.set"

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

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


5506 빌드에서 수정되었습니다.
 
Alain Verleyen #:
5506 빌드에서 수정되었습니다.
감사합니다.
 
Stanislav Korotky 최적화 기준 계산 파일( RSquared.mqh)의 업데이트 버전을 첨부합니다.

최적화 결과 표를 보면 복구 계수와 샤프 매개 변수의 조합이 얻어지는 등 추정 품질이 크게 개선되었습니다.

사용 예시.

주의! 다른 종목이 거래되는 경우 거래량을 적절하게 추정하려면 랏에서 예금 통화 가치로 변환해야 합니다(예: 단순화된 변형 중 하나):

#include <MQL5Book/DealFilter.mqh>
#include <MQL5Book/RSquared.mqh>

template<typename T>
union Type2Bytes
{
   T d;
   uchar bytes[sizeof(T)];
};

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;

   MapArray<ulong,double> sym2value; // 심볼 해시를 1 로트 값으로
   
   for(int i = 0; i < n; ++i)
   {
      const string s = HistoryDealGetString(tickets[i], DEAL_SYMBOL);

      double value = 1;
      Type2Bytes<ulong> sym;
      ArrayInitialize(sym.bytes, 0);
      StringToCharArray(s, sym.bytes);
      int idx = sym2value.find(sym.d);
      if(idx == -1) // 로트당 심볼 값에 대한 기록이 아직 없습니다.
      {
         const double price = SymbolInfoDouble(s, SYMBOL_ASK);
         const double pt = SymbolInfoDouble(s, SYMBOL_POINT);
         double profit = 1;
         ResetLastError();
         if(!OrderCalcProfit(ORDER_TYPE_BUY, s, 1, price, price + pt, profit)) // 참고: 계정 통화는 현재 환율을 사용하므로 대략적인 추정치입니다.
         {
            // WARN(StringFormat("OrderCalcProfit Error: %s %d ", s, _LastError));
         }
         value = profit * (price / pt); // 참고: 여기에는 레버리지가 적용되지 않습니다.
         idx = sym2value.put(sym.d, value);
      }
      else
      {
         value = sym2value.getValue(idx);
      }
   
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j) // 거래량을 제외한 모든 요청된 소품을 반복합니다.
      {
         result += expenses[i][j];
      }
      // 볼륨을 모델로 사용 - 더 많은 투자 - 더 많은 수익 예상
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] * value + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef   STAT_PROPS
   
   return r2 * 100;
}

노란색은 하나의 심볼을 거래할 때의 계산과 비교하여 추가해야 하는 것을 표시합니다(이전 예시에서).

 
Stanislav Korotky #:

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

또 다른 관련 버그 수정( NormalizeLot 메서드에서):

const double newLotsRounded = MathFloor(nlot * (1 + DBL_EPSILON) / stepLot) * stepLot;
파일:
TradeUtils.mqh  12 kb