English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
적응형 거래 시스템과 MetaTrader 5 클라이언트 터미널에서의 사용

적응형 거래 시스템과 MetaTrader 5 클라이언트 터미널에서의 사용

MetaTrader 5트레이딩 시스템 | 18 8월 2021, 09:47
197 0
MetaQuotes
MetaQuotes


소개

전 세계 수십만 명의 트레이더가 MetaQuotes Software Corp에서 개발한 거래 플랫폼을 사용합니다. 다년간의 경험을 바탕으로 한 기술력과 최고의 소프트웨어 솔루션이 성공의 열쇠입니다.

많은 사람들이 이미 새로운 MQL5 언어로 제공되는 새로운 기회를 예상했습니다. 주요 기능은 고성능과 객체 지향 프로그래밍 사용 가능성입니다. 그 외에도 MetaTrader 5 클라이언트 터미널에 다중 통화 전략 테스터가 등장하면서 많은 trader들이 복잡한 거래 시스템을 개발, 학습 및 사용하기 위한 고유한 도구를 획득했습니다.

Automated Trading Championship 2010이 올 가을에 시작됩니다. MQL5로 작성된 수천 대의 거래 로봇이 참여할 예정입니다. 대회 기간 동안 최대한의 수익을 올린 Expert Advisor가 승리합니다. 그러나 어떤 전략이 가장 효과적일까요?

MetaTrader 5 터미널의 전략 테스터는 시스템이 지정된 기간 동안 최대 수익을 얻는 데 사용하는 최적의 매개변수 집합을 찾을 수 있습니다. 근데 실시간으로 가능할까요? Expert Advisor에서 여러 전략을 사용하는 가상 거래에 대한 아이디어는 MQL4에 구현된 내용이 포함된 "Contest of Expert Advisors inside Expert Advisor" 글에서 고려되었습니다. 

이 글에서는 객체 지향 프로그래밍, 데이터 및 표준 라이브러리의 거래 클래스의 작업을 위한 클래스의 사용으로 인해 MQL5에서 적응형 전략의 생성 및 분석이 훨씬 더 쉬워졌음을 보여줄 것입니다.


1. 적응형 거래 전략

시장은 끊임없이 변화합니다. 거래 전략은 현재 시장 상황에 적응해야 합니다.

최적화를 사용하지 않고도 전략의 최대 수익성을 제공하는 매개변수의 값은 매개변수의 순차적 변경과 테스트 결과 분석을 통해 찾을 수 있습니다. 

그림 1은 10명의 Expert Advisors(MA_3,...MA_93)에 대한 주식 곡선을 보여줍니다. 각각은 이동 평균 전략으로 거래되지만 기간은 다릅니다(3,13,..93). 테스트는 EURUSD H1에서 수행되었으며 테스트 기간은 2010년 4월 1일-2010년 8월입니다.

그림 1. 해당 계정에 있는 10명의 Expert Advisors의 주식 곡선 다이어그램

그림 1. 해당 계정에 있는 10명의 Expert Advisors의 주식 곡선 다이어그램

그림 1에서 볼 수 있듯이 Expert Advisors는 작업 첫 2주 동안 거의 동일한 결과를 얻었지만 점점 더 수익이 크게 달라지기 시작했습니다. 테스트 기간이 끝날 때 Expert Advisors는 기간 63, 53 및 43에서 최고의 거래 결과를 보여주었습니다.

시장은 최고의 것을 선택했습니다. 왜 우리는 그 선택을 따라야 합니까? 하나의 Expert Advisor에서 10가지 전략을 모두 결합하고 각 전략에 대해 "가상" 거래의 가능성을 제공하고 주기적으로(예: 각각의 새로운 바가 시작될 때) 신호에 따라 실제 거래 및 거래를 위한 최상의 전략을 결정하면 어떻게 될까요?

획득한 적응 전략의 결과는 그림 2에 나와 있습니다. 적응형 거래 계정의 자기자본 곡선은 빨간색으로 표시됩니다. 기간의 절반 이상 동안 적응형 전략에 대한 자기자본 곡선의 형태는 MA_63 전략과 동일하며 마침내 승자로 나타났습니다.

그림 2. 10가지 거래 시스템의 신호를 사용하는 적응 전략이 있는 계정의 주가 곡선

그림 2. 10가지 거래 시스템의 신호를 사용하는 적응 전략이 있는 계정의 주가 곡선

균형 곡선은 유사한 역학을 가지고 있습니다(그림 3).

그림 3. 10가지 거래 시스템의 신호를 사용하는 적응 전략의 균형 곡선

그림 3. 10가지 거래 시스템의 신호를 사용하는 적응 전략의 균형 곡선

어떤 전략도 현재 수익성이 없다면 적응형 시스템은 거래 작업을 수행하지 않아야 합니다. 그러한 경우의 예가 그림 4에 나와 있습니다 (2010년 1월 4일부터 22일까지 기간).

그림 4. 적응형 전략이 수익성 있는 전략의 부재로 인해 새로운 포지션을 열지 못하게 된 기간

그림 4. 적응형 전략이 수익성 있는 전략의 부재로 인해 새로운 포지션을 열지 못하게 된 기간

2010년 1월부터 MA_3 전략이 최고의 효율성을 보여줍니다. MA_3(파란색)은 그 순간 최대 수익을 올렸으므로 적응형 전략(빨간색)은 신호를 따랐습니다. 1월 8일부터 20일까지의 기간 동안 고려된 모든 전략이 부정적인 결과를 얻었으므로 적응 전략이 새로운 거래 포지션을 열지 못했습니다. 

모든 전략이 부정적인 결과를 가져오면 거래를 멀리하는 것이 좋습니다. 이것은 수익성이 없는 거래를 중단하고 돈을 절약할 수 있게 해주는 중요한 것입니다.


2. 적응형 거래 전략의 구현

이 섹션에서는 여러 거래 전략을 동시에 사용하여 "가상" 거래를 수행하고 신호에 따라 실제 거래에 가장 수익성이 높은 것을 선택하는 적응 전략의 구조를 고려할 것입니다. 객체 지향 접근 방식을 사용하면 이 문제를 훨씬 쉽게 해결할 수 있습니다.

먼저 적응형 Expert Advisor의 코드를 조사한 다음 적응형 시스템의 기능이 구현된 CAdaptiveStrategy에 대해 자세히 살펴본 다음 가상 거래 기능이 구현되는 거래 전략의 기본 클래스인 CSampleStrategy 클래스의 구조를 보여줍니다.

또한 이동 평균과 확률적 오실레이터에 의한 거래 전략을 나타내는 CStrategyMACStrategyStoch 클래스의 두 하위 코드를 고려할 것입니다. 구조를 분석한 후 전략을 실현하는 클래스를 쉽게 작성하고 추가할 수 있습니다.

2.1. Expert Advisor 코드

Expert Advisor의 코드는 매우 간단해 보입니다.

//+------------------------------------------------------------------+
//|                                       Adaptive_Expert_Sample.mq5 |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <CAdaptiveStrategy.mqh>

CAdaptiveStrategy Adaptive_Expert;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(Adaptive_Expert.Expert_OnInit());
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Adaptive_Expert.Expert_OnDeInit(reason);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   Adaptive_Expert.Expert_OnTick();
  }
//+------------------------------------------------------------------+

처음 세 줄은 프로그램의 속성을 정의한 다음 전처리기에 CAdaptiveStrategy.mqh 파일을 포함하도록 지시하는 #include 지시문이 나옵니다. 꺾쇠 괄호는 파일이 표준 디렉토리(일반적으로 terminal_folder\MQL5\Include임)에서 가져와야 함을 지정합니다.

다음 줄에는 Adaptive_Expert 개체의 선언이 포함되어 있습니다(CAdaptiveStrategy 클래스의 인스턴스). 그리고 Expert Advisor의 OnInit, OnDeinitOnTick 함수의 코드는 Expert_OnInit, Expert_OnDeInit 및 Expert_OnTick과 Adaptive_Expert 개체의 해당 함수 호출로 구성됩니다.

2.2. CAAdaptiveStrategy 클래스

적응형 Expert Advisor의 클래스(CAdaptiveStrategy 클래스)는 CAdaptiveStrategy.mqh 파일에 있습니다. 포함 파일부터 시작하겠습니다.

#include <Arrays\ArrayObj.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <CStrategyMA.mqh>
#include <CStrategyStoch.mqh>

ArrayObj.mqh 파일을 포함하는 이유는 기본 CObject 클래스와 그 자식에 의해 생성된 클래스 인스턴스에 대한 포인터의 동적 배열을 나타내는 CArrayObj 클래스의 개체를 사용하여 다양한 전략의 클래스로 작업할 수 있는 편의성 때문입니다. 이 개체는 m_all_strategies 배열이 되며 거래 전략의 "컨테이너"로 사용됩니다.

각 전략은 클래스로 표시됩니다. 이 경우 이동 평균에 의한 거래와 스토캐스틱 오실레이터에 의한 거래 전략을 나타내는 CStrategyMACStrategyStoch 클래스가 포함된 파일을 포함했습니다.

현재 포지션의 속성을 요청하고 거래 작업을 수행하기 위해 표준 라이브러리의 CPositionInfoCTrade 클래스를 사용하므로 PositionInfo.mqh 및 Trade.mqh 파일를 포함합니다.

CAdaptiveStrategy 클래스의 구조를 살펴보겠습니다.

//+------------------------------------------------------------------+
//| Class CAdaptiveStrategy                                          |
//+------------------------------------------------------------------+
class CAdaptiveStrategy
  {
protected:
   CArrayObj        *m_all_strategies;   // objects of trade strategies

   void              ProceedSignalReal(int state,double trade_volume);
   int               RealPositionDirection();

public:
   // initialization of the adaptive strategy
   int               Expert_OnInit();
   // deinitialization of the adaptive strategy
   int               Expert_OnDeInit(const int reason);
   // check of trade conditions and opening of virtual positions
   void              Expert_OnTick();
  };

다른 클래스의 개체에 대한 통합된 접근 방식을 구현하기 위해 거래 전략(또는 해당 클래스의 인스턴스)이 동적 배열 m_all_strategies(CArrayObj 유형의), 전략 클래스의 "컨테이너"로 사용됩니다. 이것이 SampleStrategy 거래 전략 클래스가 CObject 클래스에서 생성되는 이유입니다.

ProceedSignalReal 함수는 실제 포지션의 방향과 볼륨을 주어진 방향과 볼륨으로 "동기화"를 구현합니다.

//+------------------------------------------------------------------+
//| This method is intended for "synchronization" of current         |
//| real trade position with the value of the 'state' state          |
//+------------------------------------------------------------------+
void CAdaptiveStrategy::ProceedSignalReal(int state,double trade_volume)
  {
   CPositionInfo posinfo;
   CTrade trade;

   bool buy_opened=false;
   bool sell_opened=false;

   if(posinfo.Select(_Symbol)) // if there are open positions
     {
      if(posinfo.Type()==POSITION_TYPE_BUY) buy_opened=true;    // a buy position is opened
      if(posinfo.Type()==POSITION_TYPE_SELL) sell_opened=true;  // a sell position is opened

      // if state = 0, then we need to close open positions
      if((state==POSITION_NEUTRAL) && (buy_opened || sell_opened))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
        }
      //reverse: closing buy position and opening sell position
      if((state==POSITION_SHORT) && (buy_opened))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,trade_volume,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0))
            Print(trade.ResultRetcodeDescription());
        }
      //reverse: close sell position and open buy position
      if(((state==POSITION_LONG) && (sell_opened)))
        {
         if(!trade.PositionClose(_Symbol,200))
            Print(trade.ResultRetcodeDescription());
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,trade_volume,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0))
            Print(trade.ResultRetcodeDescription());
        }
     }
   else // if there are no open positions
     {
      // open a buy position
      if(state==POSITION_LONG)
        {
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0))
            Print(trade.ResultRetcodeDescription());
        }
      // open a sell position
      if(state==POSITION_SHORT)
        {
         if(!trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,0.1,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0))
            Print(trade.ResultRetcodeDescription());
        }
     }
  }

트레이드 클래스를 사용하여 트레이드 포지션으로 작업하는 것이 더 쉽습니다. CPositionInfoCTrade 클래스의 개체를 각각 시장 포지션 속성을 요청하고 거래 작업을 수행하는 데 사용했습니다.

RealPositionDirection 함수는 실제 열린 포지션의 매개변수를 요청하고 방향을 반환합니다.

//+------------------------------------------------------------------+
//| Returns direction (0,+1,-1) of the current real position         |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::RealPositionDirection()
  {
   int direction=POSITION_NEUTRAL;
   CPositionInfo posinfo;

   if(posinfo.Select(_Symbol)) // if there are open positions
     {
      if(posinfo.Type()==POSITION_TYPE_BUY) direction=POSITION_LONG;    // a buy position is opened
      if(posinfo.Type()==POSITION_TYPE_SELL) direction=POSITION_SHORT;  // a short position is opened
     }
   return(direction);
  }

이제 СAdaptiveStrategy 클래스의 주요 기능을 살펴보겠습니다.

Expert_OnInit: 함수부터 시작하겠습니다.

//+------------------------------------------------------------------+
//| Function of initialization of the Adaptive Expert Advisor        |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::Expert_OnInit()
  {
//--- Create array of objects m_all_strategies
//--- we will put our object with strategies in it 
   m_all_strategies=new CArrayObj;
   if(m_all_strategies==NULL)
     {
      Print("Error of creation of the object m_all_strategies"); return(-1);
     }

// create 10 trading strategies CStrategyMA (trading by moving averages)
// initialize them, set parameters
// and add to the m_all_strategies container 
   for(int i=0; i<10; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialize strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //t_StrategyMA.Set_Stops(3500,1000);

      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      CSampleStrategy *t_SampleStrategy;
      t_SampleStrategy=m_all_strategies.At(i);
      Print(i," Strategy name:",t_SampleStrategy.StrategyName(),
              " Strategy ID:",t_SampleStrategy.StrategyID(),
              " Virtual trading:",t_SampleStrategy.IsVirtualTradeAllowed());
     }
//---
   return(0);
  }

거래 전략 세트는 Expert_OnInit 기능에서 준비됩니다. 먼저 m_all_strategies 동적 배열의 객체를 생성합니다.

이 경우 CStrategyMA 클래스의 10개 인스턴스를 만들었습니다. 각각은 초기화 기능을 사용하여 초기화되었습니다(이 경우 서로 다른 기간을 설정하고 "가상" 거래를 허용함).

그런 다음 SetStrategyInfo 기능을 사용하여 금융 상품, 전략 이름 및 설명을 설정합니다.

필요한 경우 Set_Stops(TP,SL) 기능을 사용하여 "가상" 거래 중에 실행될 이익실현 및 손절매 값(포인트)을 지정할 수 있습니다. 우리는 이 줄에 주석을 달았습니다.

전략 클래스가 생성되고 조정되면 m_all_strategies 컨테이너에 추가합니다.

모든 종류의 거래 전략에는 거래 조건을 확인하는 CheckTradeConditions() 함수가 있어야 합니다. 적응 전략의 클래스에서 이 함수는 각각의 새로운 바의 시작 부분에서 호출되므로 전략에 지표의 값을 확인하고 "가상" 거래 작업을 할 수 있는 가능성을 제공합니다.

10개의 지정된 이동 평균(3, 13, 23...93) 대신 수백 개의 이동 평균을 추가할 수 있습니다(예: CStrategyMA 클래스인 경우).

  for(int i=0; i<100; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialization of strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

또는 확률적 오실레이터의 신호(CStrategyStoch 클래스의 인스턴스)에 의해 작동하는 전략 클래스를 추가할 수 있습니다.

  for(int i=0; i<5; i++)
     {
      CStrategyStoch *t_StrategyStoch;
      t_StrategyStoch=new CStrategyStoch;
      if(t_StrategyStoch==NULL)
        {
         delete m_all_strategies;
         printf("Error of creation of object of the CStrategyStoch type");
         return(-1);
        }
      //set period for each strategy
      int Kperiod=2+i*5;
      int Dperiod=2+i*5;
      int Slowing=3+i;
      // initialization of strategy
      t_StrategyStoch.Initialization(Kperiod,Dperiod,Slowing,true);
      // set details of the strategy
      string s=IntegerToString(Kperiod)+"/"+IntegerToString(Dperiod)+"/"+IntegerToString(Slowing);
      t_StrategyStoch.SetStrategyInfo(_Symbol,"[Stoch_"+s+"]",100+i," Stochastic "+s);
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyStoch);
     }

이 경우 컨테이너에는 이동 평균의 10가지 전략과 스토캐스틱 오실레이터의 5가지 전략이 포함됩니다.

거래 전략 클래스의 인스턴스는 CObject 클래스의 자식이어야 하며 CheckTradeConditions() 함수를 포함해야 합니다. CSampleStrategy 클래스에서 상속하는 것이 좋습니다. 거래 전략을 구현하는 클래스는 다를 수 있으며 그 수는 제한되지 않습니다.

Expert_OnInit 함수는 m_all_strategies 컨테이너에 있는 전략 목록으로 끝납니다. 컨테이너의 모든 전략은 CSampleStrategy 클래스의 자식으로 간주됩니다. 거래 전략 클래스 CStrategyMA 및 CStrategyStoch도 하위 항목입니다.

Expert_OnDeInit 함수에서도 동일한 트릭이 사용됩니다. 컨테이너에서 각 전략에 대해 SaveVirtualDeals 함수를 호출합니다. 그것은 수행된 가상 거래의 이력을 저장합니다.

매개변수로 전달되는 파일 이름에 대해 전략 이름을 사용합니다. 그런 다음 Deinitialization() 함수를 호출하고 m_all_strategies 컨테이너를 삭제하여 전략을 초기화 해제합니다.

//+------------------------------------------------------------------+
//| Function of deinitialization the adaptive Expert Advisor         |
//+------------------------------------------------------------------+
int CAdaptiveStrategy::Expert_OnDeInit(const int reason)
  {
   // deinitialize all strategies
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      CSampleStrategy *t_Strategy;
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.SaveVirtualDeals(t_Strategy.StrategyName()+"_deals.txt");
      t_Strategy.Deinitialization();
     }
   //delete the array of object with strategies 
   delete m_all_strategies;
   return(0);
  }

전략에 의해 수행된 가상 거래에 대해 알 필요가 없는 경우 tStrategy.SaveVirtualDeals가 호출되는 행을 제거하십시오. 전략 테스터를 사용할 때 파일은 /tester_directory/Files/ 디렉토리에 저장됩니다.

새 틱이 올 때마다 호출되는 CAdaptiveStrategy 클래스의 Expert_OnTick 함수를 살펴보겠습니다.

//+------------------------------------------------------------------+
//| Function of processing ticks of the adaptive strategy            |
//+------------------------------------------------------------------+
void CAdaptiveStrategy::Expert_OnTick()
  {
   CSampleStrategy *t_Strategy;

   // recalculate the information about positions for all strategies
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.UpdatePositionData();
     }

   // the expert advisor should check the conditions of making trade operations only when a new bar comes
   if(IsNewBar()==false) { return; }

   // check trading conditions for all strategies 
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      t_Strategy.CheckTradeConditions();
     }

   //search for the best position
   //prepare the array performance[] 
   double performance[];
   ArrayResize(performance,m_all_strategies.Total());
   
   //request the current effectiveness for each strategy,
   //each strategy returns it in the Strategyperformance() function
   for(int i=0; i<m_all_strategies.Total(); i++)
     {
      t_Strategy=m_all_strategies.At(i);
      performance[i]=t_Strategy.StrategyPerformance();
     }
   //find the strategy (or rather its index in the m_all_strategies container)
   //with maximum value of Strategyperformance()
   int best_strategy_index=ArrayMaximum(performance,0,WHOLE_ARRAY);

   //this strategy is - t_Strategy
   t_Strategy=m_all_strategies.At(best_strategy_index);
   //request the direction of its current position
   int best_direction=t_Strategy.PositionDirection();

   string s=s+" "+t_Strategy.StrategyName()+" "+DoubleToString(t_Strategy.GetVirtualEquity())+" "+IntegerToString(best_direction);
   Print(TimeCurrent()," TOTAL=",m_all_strategies.Total(),
                       " BEST IND=",best_strategy_index,
                       " BEST STRATEGY="," ",t_Strategy.StrategyName(),
                       " BEST=",performance[best_strategy_index],"  =",
                       " BEST DIRECTION=",best_direction,
                       " Performance=",t_Strategy.StrategyPerformance());

   //if the best strategy has a negative result and doesn't have open positions, it's better to stay away from trading
   if((performance[best_strategy_index]<0) && (RealPositionDirection()==POSITION_NEUTRAL)) {return;}

   if(best_direction!=RealPositionDirection())
     {
      ProceedSignalReal(best_direction,t_Strategy.GetCurrentLotSize());
     }
  }

코드는 매우 간단합니다. 컨테이너에 있는 각 전략은 현재 가격을 사용하여 가상 포지션의 현재 재무 결과를 다시 계산할 수 있어야 합니다. UpdatePositionData() 함수를 호출하여 수행됩니다. 여기서 다시 한 번 우리는 전략을 CSampleStrategy 클래스의 상속자라고 부릅니다.

모든 거래 작업은 새 바의 시작 부분에서 수행됩니다(IsNewBar() 함수를 사용하면 이 순간과 새 바를 확인하는 다른 방법을 결정할 수 있습니다). 이 경우 바 형성이 종료된다는 것은 이전 바의 모든 데이터(가격 및 지표 값)가 더 이상 변경되지 않음을 의미하므로 거래 조건에 대응하여 분석할 수 있습니다. 모든 전략에 대해 이러한 확인을 수행하고 CheckTradeConditions 함수를 호출하여 가상 거래 작업을 수행할 수 있는 기회를 제공합니다.

이제 m_all_strategies 배열의 모든 전략 중에서 가장 성공적인 전략을 찾아야 합니다. 이를 수행하기 위해 Performance[] 배열을 사용했으며 각 전략의 StrategyPerformance() 함수에서 반환된 값이 이 배열에 배치됩니다. 기본 클래스 CSampleStrategy에는 "가상" Equity와 Balance의 현재 값 간의 차이로 이 함수가 포함되어 있습니다.

가장 성공적인 전략의 인덱스 검색은 ArrayMaximum 함수를 사용하여 수행됩니다. 최선의 전략이 현재 마이너스 이익이 있고 실제 오픈 포지션이 없다면 거래하지 않는 것이 좋습니다. 이것이 우리가 기능을 종료하는 이유입니다(섹션 1 참조).

또한 이 전략의 가상 포지션 방향(best_direction)을 요청합니다. 실제 포지션의 현재 방향과 다른 경우 best_direction 방향에 따라 실제 포지션의 현재 방향이 수정됩니다( ProceedSignalReal 함수 사용).

2.3. 클래스 CSampleStrategy

m_all_strategies 컨테이너에 배치된 전략은 CSampleStrategy 클래스의 상속자로 간주되었습니다.

이 클래스는 거래 전략의 기본 클래스입니다. 그것은 가상 거래의 구현을 포함합니다. 이 글에서는 가상 거래 구현의 단순화된 사례를 고려할 것이며 스왑은 고려되지 않습니다. 거래 전략 클래스는 CSampleStrategy 클래스에서 상속되어야 합니다.

이 클래스의 구조를 보여줍시다.

//+------------------------------------------------------------------+
//|                                              CSampleStrategy.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <Object.mqh>

#define POSITION_NEUTRAL   0     // no position
#define POSITION_LONG      1     // long position
#define POSITION_SHORT    -1     // short position

#define SIGNAL_OPEN_LONG    10   // signal to open a long position
#define SIGNAL_OPEN_SHORT  -10   // signal to open a short position
#define SIGNAL_CLOSE_LONG   -1   // signal to close a long position
#define SIGNAL_CLOSE_SHORT   1   // signal to close a short position
//+------------------------------------------------------------------+
//| Structure for storing the parameters of virtual position         |
//+------------------------------------------------------------------+
struct virtual_position
  {
   string            symbol;            // symbol
   int               direction;         // direction of the virtual position (0-no open position,+1 long,-1 short)
   double            volume;            // volume of the position in lots
   double            profit;            // current profit of the virtual position on points
   double            stop_loss;         // Stop Loss of the virtual position
   double            take_profit;       // Take Profit of the virtual position
   datetime          time_open;         // date and time of opening the virtual position
   datetime          time_close;        // date and time of closing the virtual position
   double            price_open;        // open price of the virtual position
   double            price_close;       // close price of the virtual position
   double            price_highest;     // maximum price during the life of the position
   double            price_lowest;      // minimal price during the lift of the position
   double            entry_eff;         // effectiveness of entering
   double            exit_eff;          // effectiveness of exiting
   double            trade_eff;         // effectiveness of deal
  };
//+------------------------------------------------------------------+
//| Class CSampleStrategy                                            |
//+------------------------------------------------------------------+
class CSampleStrategy: public CObject
  {
protected:
   int               m_strategy_id;            // Strategy ID
   string            m_strategy_symbol;        // Symbol 
   string            m_strategy_name;          // Strategy name
   string            m_strategy_comment;       // Comment

   MqlTick           m_price_last;             // Last price
   MqlRates          m_rates[];                // Array for current quotes
   bool              m_virtual_trade_allowed;  // Flag of allowing virtual trading 
   int               m_current_signal_state;   // Current state of strategy
   double            m_current_trade_volume;   // Number of lots for trading
   double            m_initial_balance;        // Initial balance (set in the constructor, default value is 10000)
   int               m_sl_points;              // Stop Loss
   int               m_tp_points;              // Take Profit

   virtual_position  m_position;               // Virtual position
   virtual_position  m_deals_history[];        // Array of deals
   int               m_virtual_deals_total;    // Total number of deals

   double            m_virtual_balance;           // "Virtual" balance
   double            m_virtual_equity;            // "Virtual" equity
   double            m_virtual_cumulative_profit; // cumulative "virtual" profit
   double            m_virtual_profit;            // profit of the current open "virtual" position

   //checks and closes the virtual position by stop levels if it is necessary
   bool              CheckVirtual_Stops(virtual_position &position);
   // recalculation of position and balance
   void              RecalcPositionProperties(virtual_position &position);
   // recalculation of open virtual position in accordance with the current prices 
   void              Position_RefreshInfo(virtual_position &position);
   // open virtual short position
   void              Position_OpenShort(virtual_position &position);
   // closes virtual short position  
   void              Position_CloseShort(virtual_position &position);
   // opens virtual long position
   void              Position_OpenLong(virtual_position &position);
   // closes the virtual long position
   void              Position_CloseLong(virtual_position &position);
   // closes open virtual position  
   void              Position_CloseOpenedPosition(virtual_position &position);
   // adds closed position to the m_deals_history[] array (history of deals)
   void              AddDealToHistory(virtual_position &position);
   //calculates and returns the recommended volume that will be used in trading
   virtual double    MoneyManagement_CalculateLots(double trade_volume);
public:
   // constructor
   void              CSampleStrategy();
   // destructor
   void             ~CSampleStrategy();

   //returns the current size of virtual balance
   double            GetVirtualBalance() { return(m_virtual_balance); }
   //returns the current size of virtual equity
   double            GetVirtualEquity() { return(m_virtual_equity); }
   //returns the current size of virtual profit of open position
   double            GetVirtualProfit() { return(m_virtual_profit); }

   //sets Stop Loss and Take Profit in points
   void              Set_Stops(int tp,int sl) {m_tp_points=tp; m_sl_points=sl;};
   //sets the current volume in lots
   void              SetLots(double trade_volume) {m_current_trade_volume=trade_volume;};
   //returns the current volume in lots
   double            GetCurrentLots() { return(m_current_trade_volume); }

   // returns strategy name
   string            StrategyName() { return(m_strategy_name); }
   // returns strategy ID
   int               StrategyID() { return(m_strategy_id); }
   // returns the comment of strategy
   string            StrategyComment() { return(m_strategy_comment); }
   // sets the details of strategy (symbol, name and ID of strategy)
   void              SetStrategyInfo(string symbol,string name,int id,string comment);

   // set the flag of virtual trading (allowed or not)
   void              SetVirtualTradeFlag(bool pFlag) { m_virtual_trade_allowed=pFlag; };
   // returns flag of allowing virtual trading
   bool              IsVirtualTradeAllowed() { return(m_virtual_trade_allowed); };

   // returns the current state of strategy
   int               GetSignalState();
   // sets the current state of strategy (changes virtual position if necessary)
   void              SetSignalState(int state);
   // changes virtual position in accordance with the current state 
   void              ProceedSignalState(virtual_position &position);

   // sets the value of cumulative "virtual" profit
   void              SetVirtualCumulativeProfit(double cumulative_profit) { m_virtual_cumulative_profit=cumulative_profit; };

   //returns the effectiveness of strategy ()
   double            StrategyPerformance();

   //updates position data
   void              UpdatePositionData();
   //closes open virtual position
   void              CloseVirtualPosition();
   //returns the direction of the current virtual position
   int               PositionDirection();
   //virtual function of initialization
   virtual int       Initialization() {return(0);};
   //virtual function of checking trade conditions
   virtual bool      CheckTradeConditions() {return(false);};
   //virtual function of deinitialization
   virtual int       Deinitialization() {return(0);};

   //saves virtual deals to a file
   void              SaveVirtualDeals(string file_name);
  };

자세한 설명은 분석하지 않겠습니다. 추가 정보는 CSampleStrategy.mqh 파일에서 찾을 수 있습니다. 거기에서 새 바를 확인하는 기능인 IsNewBar도 찾을 수 있습니다.


3. 거래 전략의 클래스

이 섹션은 적응형 Expert Advisor에서 사용되는 거래 전략 클래스의 구조에 대해 설명합니다.

3.1. 클래스 CStrategyMA - 이동 평균에 의한 거래 전략

//+------------------------------------------------------------------+
//|                                                  CStrategyMA.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <CSampleStrategy.mqh>
//+------------------------------------------------------------------+
//| Class CStrategyMA for implementation of virtual trading          |
//| by the strategy based on moving average                          |
//+------------------------------------------------------------------+
class CStrategyMA : public CSampleStrategy
  {
protected:
   int               m_handle;     // handle of the Moving Average (iMA) indicator
   int               m_period;     // period of the Moving Average indicator
   double            m_values[];   // array for storing values of the indicator
public:
   // initialization of the strategy
   int               Initialization(int period,bool virtual_trade_flag);
   // deinitialization of the strategy
   int               Deinitialization();
   // checking trading conditions and opening virtual positions
   bool              CheckTradeConditions();
  };

CStrategyMA 클래스는 가상 거래의 전체 기능이 구현되는 CSampleStrategy 클래스의 자식입니다.

보호된 섹션에는 전략 클래스에서 사용할 내부 변수가 포함됩니다. m_handle - iMA 표시기의 핸들, m_period - 이동 평균의 기간, m_values[] - 현재 값을 가져오기 위해 CheckTradeConditions 함수에서 사용할 배열 지표의.

공개 섹션에는 거래 전략의 구현을 제공하는 세 가지 기능이 있습니다.

  • 함수 초기화. 전략은 여기에서 초기화됩니다. 지표를 생성해야 하는 경우 여기에서 생성합니다.
  • 함수 초기화 해제. 여기에서 전략이 초기화 해제됩니다. 표시기의 핸들은 여기에서 해제됩니다.
  • 기능 CheckTradeConditions. 여기에서 전략은 거래 조건을 확인하고 가상 거래에 사용되는 거래 신호를 생성합니다. 가상 거래 작업을 수행하기 위해 CStrategy 부모 클래스의 SetSignalState 함수가 호출됩니다. 다음 거래 신호 중 네 가지 중 하나가 전달됩니다.
  1. 롱 포지션 오픈 시그널(SIGNAL_OPEN_LONG)
  2. 숏 포지션 오픈 시그널(SIGNAL_OPEN_SHORT)
  3. 롱 포지션 청산 신호(SIGNAL_CLOSE_LONG)
  4. 매도 포지션 청산 신호(SIGNAL_CLOSE_SHORT)
//+------------------------------------------------------------------+
//| Strategy Initialization Method                                   |
//+------------------------------------------------------------------+
int CStrategyMA::Initialization(int period,bool virtual_trade_flag)
  {
   // set period of the moving average
   m_period=period;
   // set specified flag of virtual trading
   SetVirtualTradeFlag(virtual_trade_flag);

   //set indexation of arrays like the one of timeseries
   ArraySetAsSeries(m_rates,true);
   ArraySetAsSeries(m_values,true);
   
   //create handle of the indicator
   m_handle=iMA(_Symbol,_Period,m_period,0,MODE_EMA,PRICE_CLOSE);
   if(m_handle<0)
     {
      Alert("Error of creation of the MA indicator - error number: ",GetLastError(),"!!");
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Strategy Deinitialization Method                                 |
//+------------------------------------------------------------------+
int CStrategyMA::Deinitialization()
  {
   Position_CloseOpenedPosition(m_position);
   IndicatorRelease(m_handle);
   return(0);
  };
//+------------------------------------------------------------------+
//| Checking trading conditions and opening virtual positions        |
//+------------------------------------------------------------------+
bool CStrategyMA::CheckTradeConditions()
  {
   RecalcPositionProperties(m_position);
   double p_close;

   // get history data of the last three bars
   if(CopyRates(_Symbol,_Period,0,3,m_rates)<0)
     {
      Alert("Error of copying history data - error:",GetLastError(),"!!");
      return(false);
     }
   // Copy the current price of closing of the previous bar (it is bar 1)
   p_close=m_rates[1].close;  // close price of the previous bar          

   if(CopyBuffer(m_handle,0,0,3,m_values)<0)
     {
      Alert("Error of copying buffers of the Moving Average indicator - error number:",GetLastError());
      return(false);
     }

   // buy condition 1: MA rises
   bool buy_condition_1=(m_values[0]>m_values[1]) && (m_values[1]>m_values[2]);
   // buy condition 2: previous price is greater than the MA
   bool buy_condition_2=(p_close>m_values[1]);

   // sell condition 1: // MA falls
   bool sell_condition_1=(m_values[0]<m_values[1]) && (m_values[1]<m_values[2]);
   // sell condition 2: // previous price is lower than the MA   
   bool sell_condition_2=(p_close<m_values[1]);

   int new_state=0;

   if(buy_condition_1  &&  buy_condition_2) new_state=SIGNAL_OPEN_LONG;
   if(sell_condition_1 && sell_condition_2) new_state=SIGNAL_OPEN_SHORT;

   if((GetSignalState()==SIGNAL_OPEN_SHORT) && (buy_condition_1 || buy_condition_2)) new_state=SIGNAL_CLOSE_SHORT;
   if((GetSignalState()==SIGNAL_OPEN_LONG) && (sell_condition_1 || sell_condition_2)) new_state=SIGNAL_CLOSE_LONG;

   if(GetSignalState()!=new_state)
     {
      SetSignalState(new_state);
     }

   return(true);
  };

개념은 간단합니다. 표시기 상태와 가격을 기반으로 신호 유형(new_state)이 결정된 다음 가상 거래의 현재 상태가 요청됩니다(GetSignalState 기능 사용). 동일하지 않은 경우 가상 포지션을 "수정"하기 위해 SetSignalState 함수가 호출됩니다.

3.2. 클래스 CStrategyStoch - Stochastic에 의한 거래 전략

iStochastic 오실레이터의 메인 라인과 시그널 라인의 교차를 기반으로 거래를 수행하는 클래스의 코드는 다음과 같습니다.

//+------------------------------------------------------------------+
//|                                               CStrategyStoch.mqh |
//|                        Copyright 2010, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2010, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#include <CSampleStrategy.mqh>
//+------------------------------------------------------------------+
//| Class CStrategyStoch for implementation of virtual trading by    |
//| the strategy of intersection of lines of stochastic oscillator   |
//+------------------------------------------------------------------+
class CStrategyStoch : public CSampleStrategy
  {
protected:
   int               m_handle;          // handle of the Stochastic Oscillator (iStochastic)
   int               m_period_k;        // K-period (number of bars for calculations)
   int               m_period_d;        // D-period (period of primary smoothing)
   int               m_period_slowing;  // final smoothing
   double            m_main_line[];     // array for storing indicator values
   double            m_signal_line[];   // array for storing indicator values
public:
   // initialization of strategy
   int               Initialization(int period_k,int period_d,int period_slowing,bool virtual_trade_flag);
   // deinitialization of strategy
   int               Deinitialization();
   // checking trading conditions and opening virtual positions
   bool              CheckTradeConditions();
  };
//+------------------------------------------------------------------+
//| Strategy Initialization Method                                   |
//+------------------------------------------------------------------+
int CStrategyStoch::Initialization(int period_k,int period_d,int period_slowing,bool virtual_trade_flag)
  {
   // Set period of the oscillator
   m_period_k=period_k;
   m_period_d=period_d;
   m_period_slowing=period_slowing;

   // set specified flag of the virtual trading
   SetVirtualTradeFlag(virtual_trade_flag);

   // set indexation of arrays like the one of timeseries
   ArraySetAsSeries(m_rates,true);
   ArraySetAsSeries(m_main_line,true);
   ArraySetAsSeries(m_signal_line,true);

   // create handle of the indicator
   m_handle=iStochastic(_Symbol,_Period,m_period_k,m_period_d,m_period_slowing,MODE_SMA,STO_LOWHIGH);
   if(m_handle<0)
     {
      Alert("Error of creating the Stochastic indicator - error number: ",GetLastError(),"!!");
      return(-1);
     }

   return(0);
  }
//+------------------------------------------------------------------+
//| Strategy Deinitialization Method                                 |
//+------------------------------------------------------------------+
int CStrategyStoch::Deinitialization()
  {
   // close all open positions
   Position_CloseOpenedPosition(m_position);
   // release handle of the indicator
   IndicatorRelease(m_handle);
   return(0);
  };
//+------------------------------------------------------------------+
//| Checking Trading Conditions and Opening Virtual Positions        |
//+------------------------------------------------------------------+
bool CStrategyStoch::CheckTradeConditions()
  {
   // call the functions of recalculation of position parameters
   RecalcPositionProperties(m_position);
   double p_close;

   // get history  data of the last 3 bars 
   if(CopyRates(_Symbol,_Period,0,3,m_rates)<0)
     {
      Alert("Error of copying history data - error:",GetLastError(),"!!");
      return(false);
     }
   // copy the current close price of the previous bar (it is bar 1)
   p_close=m_rates[1].close;  // close price of the previous bar          

   if((CopyBuffer(m_handle,0,0,3,m_main_line)<3) || (CopyBuffer(m_handle,1,0,3,m_signal_line)<3))
     {
      Alert("Error of copying buffers of the Stochastic indicator - error number:",GetLastError());
      return(false);
     }

   // buy condition: crossing the signal line by the main one from bottom up
   bool buy_condition=((m_signal_line[2]<m_main_line[2]) && (m_signal_line[1]>m_main_line[1]));
   // sell condition: crossing the signal line by the main one from top downwards
   bool sell_condition=((m_signal_line[2]>m_main_line[2]) && (m_signal_line[1]<m_main_line[1]));

   int new_state=0;

   if(buy_condition) new_state=SIGNAL_OPEN_LONG;
   if(sell_condition) new_state=SIGNAL_OPEN_SHORT;

   if((GetSignalState()==SIGNAL_OPEN_SHORT) && (buy_condition)) new_state=SIGNAL_CLOSE_SHORT;
   if((GetSignalState()==SIGNAL_OPEN_LONG) && (sell_condition)) new_state=SIGNAL_CLOSE_LONG;

   if(GetSignalState()!=new_state)
     {
      SetSignalState(new_state);
     }

   return(true);
  };

보시다시피 CStrategyStoch 클래스 구조와 CStrategyMA 구조 간의 유일한 차이점은 초기화 함수(다른 매개변수), 사용된 지표의 유형과 거래 신호.

따라서 적응형 Expert Advisor에서 전략을 사용하려면 이러한 유형의 클래스 형태로 전략을 다시 작성하고 m_all_strategies 컨테이너에 로드해야 합니다.


4. 적응 거래 전략 분석 결과

이 섹션에서는 적응 전략의 실제 사용과 개선 방법의 여러 측면에 대해 논의할 것입니다.

4.1. 역 신호를 사용하는 전략으로 시스템 향상

이동 평균은 추세가 없으면 좋지 않습니다. 우리는 이미 이러한 상황을 만났습니다. 그림 3에서 1월 8일부터 20일까지의 기간에는 추세가 없었음을 알 수 있습니다. 따라서 거래에서 이동 평균을 사용하는 10가지 전략 모두 가상 손실을 입었습니다. 적응형 시스템은 수익을 얻은 양의 전략이 없기 때문에 거래를 중단했습니다. 그러한 부정적인 영향을 피할 수 있는 방법이 있습니까?

10가지 전략(MA_3, MA_13, ... MA_93) 거래 신호가 반대인 다른 10개 클래스 CStrategyMAinv(조건은 동일하지만 SIGNAL_OPEN_LONG/SIGNAL_OPEN_SHORT와 SIGNAL_CLOSE_LONG/SIGNAL_CLOSE_SHORT가 자리를 바꿉니다). 따라서 10개의 추세 전략(CStrategyMA 클래스의 인스턴스) 외에도 10개의 반대 추세 전략( CStrategyMAinv 클래스의 인스턴스)이 있습니다.

20개의 전략으로 구성된 적응 시스템을 사용한 결과는 그림 5와 같다.

그림 5. 20개의 거래 신호를 사용하는 적응 전략 계정의 자기자본 다이어그램: 10개의 이동 평균 CAdaptiveMA 및 10개의 "미러링된" 신호 CAdaptiveMAinv

그림 5. 20개의 거래 신호를 사용하는 적응 전략 계정의 자기 자본 다이어그램: 10개의 이동 평균 CAdaptiveMA 및 10개의 "미러링된" 신호 CAdaptiveMAinv

그림 5에서 볼 수 있듯이 모든 CAdaptiveMA 전략이 부정적인 결과를 낳은 기간 동안 CAdaptiveMAinv 전략을 따르면 Expert Advisor가 원치 않는 손실을 피할 수 있었습니다. 거래의 아주 시작.

그림 6. 적응 전략이 "반대 추세" CAdaptiveMAinv 전략의 신호를 사용한 기간

그림 6. 적응 전략이 "역 추세" 신호를 사용한 기간CAdaptiveMAinv

이러한 접근 방식은 수용할 수 없는 것처럼 보일 수 있습니다. 반대 추세 전략을 사용할 때 보증금을 잃는 것은 시간 문제일 뿐이기 때문입니다. 그러나 우리의 경우 단일 전략으로 제한되지 않습니다. 시장은 현재 어떤 전략이 효과적인지 더 잘 알고 있습니다.

적응형 시스템의 장점은 시장이 스스로 어떤 전략을 사용해야 하고 언제 사용해야 하는지 제안한다는 것입니다.

전략의 논리에서 추상화할 수 있는 가능성을 제공합니다. 전략이 효과적이라면 전략이 작동하는 방식은 중요하지 않습니다. 적응형 접근 방식은 전략의 유일한 성공 기준인 효과를 사용합니다.

4.2. 최악의 전략의 신호를 뒤집을 가치가 있습니까?

위에 표시된 반전이 있는 트릭은 최악의 전략의 신호를 사용할 수 있는 잠재적 가능성에 대한 생각으로 이어집니다. 전략이 수익성이 없는 경우(그리고 최악의 경우) 반대로 행동하여 이익을 얻을 수 있습니까?

단순히 신호를 변경하여 지는 전략을 수익성 있는 전략으로 바꿀 수 있습니까? 이 질문에 답하기 위해서는 CAdaptiveStrategy 클래스의 Expert_OnTick() 함수에서 ArrayMaximumArrayMinimum으로 변경하고, 의 값을 곱하여 방향 변경을 구현해야 합니다. BestDirection 변수는 -1입니다.

또한 부정적인 효과의 경우 가상 거래의 한계를 언급해야 합니다(최악의 전략의 결과를 분석할 예정이므로).

//if((Performance[BestStrategyIndex]<0) && (RealPositionDirection()==0)) {return;}

최악의 전략의 역 신호를 사용하는 적응형 Expert Advisor의 형평성 다이어그램은 그림 7에 나와 있습니다.

그림 7. 10가지 전략의 계정과 최악의 시스템의 역 신호를 사용하는 적응 시스템의 에퀴티 다이어그램

그림 7. 10가지 전략의 계정과 최악의 시스템의 역 신호를 사용하는 적응 시스템의 에퀴티 다이어그램

이 경우 대부분의 시간 동안 가장 성공하지 못한 전략은 이동 평균과 기간 3(MA_3)의 교차를 기반으로 하는 전략이었습니다. 그림 7에서 볼 수 있듯이 MA_3(파란색)과 적응 전략(빨간색) 사이에는 역 상관관계가 존재하지만 적응 시스템의 재무 결과는 인상적이지 않습니다.

최악의 전략의 신호를 복사(및 역전)한다고 해서 거래의 효율성이 향상되는 것은 아닙니다.

4.2. 이동 평균의 무리가 보이는 것만큼 효과적이지 않은 이유는 무엇입니까?

10개의 이동 평균 대신 m_all_strategies 컨테이너에 기간이 다른 100개의 다른 CStrategyMA 전략을 추가하여 많은 이동 평균을 사용할 수 있습니다.

그렇게 하려면 CAAdaptiveStrategy 클래스에서 코드를 약간 변경합니다.

   for(int i=0; i<100; i++)
     {
      CStrategyMA *t_StrategyMA;
      t_StrategyMA=new CStrategyMA;
      if(t_StrategyMA==NULL)
        {
         delete m_all_strategies;
         Print("Error of creation of object of the CStrategyMA type");
         return(-1);
        }
      //set period for each strategy
      int period=3+i*10;
      // initialization of strategy
      t_StrategyMA.Initialization(period,true);
      // set details of the strategy
      t_StrategyMA.SetStrategyInfo(_Symbol,"[MA_"+IntegerToString(period)+"]",period,"Moving Averages "+IntegerToString(period));
      //add the object of the strategy to the array of objects m_all_strategies
      m_all_strategies.Add(t_StrategyMA);
     }

그러나 가까운 이동 평균은 불가피하게 교차한다는 점을 이해해야 합니다. 지도자는 끊임없이 변할 것입니다. 적응형 시스템은 필요한 것보다 더 자주 상태와 열림/닫힘 포지션을 전환합니다. 결과적으로 적응 시스템의 특성이 악화됩니다. 시스템의 통계적 특성(전략 테스터의 "결과" 탭)을 비교하여 스스로 확인할 수 있습니다.

가까운 매개변수가 있는 많은 전략을 기반으로 적응형 시스템을 만들지 않는 것이 좋습니다.


5. 고려해야 할 사항

m_all_strategies 컨테이너에는 수천 개의 제안된 전략 인스턴스가 포함될 수 있으며 다른 매개변수를 사용하여 모든 전략을 추가할 수도 있습니다. 그러나 Automated Trading Championship 2010에서 우승하려면 고급 자금 관리 시스템을 개발해야 합니다. 기록 데이터(및 클래스 코드)에 대한 테스트를 위해 거래량을 0.1랏으로 사용했습니다.

5.1 Adaptive Expert Advisor의 수익성을 높이는 방법은 무엇입니까?

CSampleStrategy 클래스에는 가상 함수 MoneyManagement_CalculateLots가 있습니다.

//+------------------------------------------------------------------+
//| The function returns the recommended volume for a strategy       |
//| Current volume is passed to it as a parameter                    |
//| Volume can be set depending on:                                  |
//| current m_virtual_balance and m_virtual_equity                   |
//| current statistics of deals (located in m_deals_history)         |
//| or any other thing you want                                      |
//| If a strategy doesn't require change of volume                   |
//| you can return the passed value of volume:  return(trade_volume);|
//+------------------------------------------------------------------+ 
double CSampleStrategy::MoneyManagement_CalculateLots(double trade_volume)
  {
   //return what we've got 
   return(trade_volume);
  }

거래량을 관리하기 위해 m_deals_history[] 배열에 기록된 가상 거래의 결과 및 특성에 대한 통계 정보를 사용할 수 있습니다.

볼륨을 늘려야 하는 경우(예: m_deals_history[]의 마지막 가상 거래가 수익성이 있는 경우 두 배로 늘리거나 줄이기 위해) 해당 방식으로 반환된 값을 변경해야 합니다.

5.2 전략 성과 계산을 위한 거래 통계 사용

CSampleStrategy 클래스에서 구현된 StrategyPerformance() 함수는 전략 성과를 계산하기 위한 것입니다.

//+-----------------------------------------------------------------------+
//| Function StrategyPerformance - the function of strategy effectiveness |
//+-----------------------------------------------------------------------+ 
double CSampleStrategy::StrategyPerformance()
  {
   //returns effectiveness of a strategy
   //in this case it's the difference between the amount
   //of equity at the moment and the initial balance, 
   //i.e. the amount of assets earned by the strategy
   double performance=(m_virtual_equity-m_initial_balance);
   return(performance);
  }

전략의 효율성 공식은 더 복잡할 수 있으며 예를 들어 진입, 퇴장, 거래의 효율성, 이익, 손실 등의 효율성이 포함될 수 있습니다.

진입, 퇴장 및 거래의 효율성 계산(m_deals_history[] 배열 구조의 entry_eff, exit_eff 및 trade_eff 필드)은 가상 거래 중에 자동으로 수행됩니다(CSampeStrategy 클래스 참조). 이 통계 정보는 전략의 효율성에 대한 보다 복잡한 자신만의 비율을 만드는 데 사용할 수 있습니다.

예를 들어, 효율성의 특성으로 마지막 세 거래의 이익을 사용할 수 있습니다(거래 m_deals_history[] 아카이브의 pos_Profit 필드 사용).

double CSampleStrategy::StrategyPerformance()
  {
  //if there are deals, multiply this value by the result of three last deals
   if(m_virtual_deals_total>0)
     {
      int avdeals=MathRound(MathMin(3,m_virtual_deals_total));
      double sumprofit=0;
      for(int j=0; j<avdeals; j++)
        {
         sumprofit+=m_deals_history[m_virtual_deals_total-1-j].profit;
        }
      double performance=sumprofit/avdeals;
     }
     return(performance);

  }

이 기능을 변경하려면 CSampleStrategy 클래스에서만 변경하고 적응형 시스템의 모든 거래 전략에 대해 동일해야 합니다. 그러나 Equity와 Balance의 차이도 효율성의 좋은 요소라는 것을 기억해야 합니다.

5.3 이익실현 및 손절매 사용

고정된 정지 수준을 설정하여 거래 시스템의 효율성을 변경할 수 있습니다(Set_Stops 함수를 호출하여 수행할 수 있으며 가상 거래를 위한 포인트에서 정지 수준을 설정할 수 있음). 수준이 지정되면 가상 포지션의 청산이 자동으로 수행됩니다. 이 기능은 CSampleStrategy 클래스에서 구현됩니다.

우리의 예(2.2, 이동 평균 클래스의 기능 참조)에서 정지 수준을 설정하는 기능이 설명되어 있습니다.

5.4. 누적 가상 이익의 주기적 제로화

적응형 접근 방식은 일반적인 전략과 동일한 단점이 있습니다. 선도 전략이 지기 시작하면 적응 시스템도 지기 시작합니다. 이것이 때때로 모든 전략의 작업 결과를 "제로화"하고 모든 가상 포지션을 닫아야 하는 이유입니다. 

이를 위해 다음 함수가 CSampleStrategy 클래스에서 구현됩니다.

// sets a value for cumulative "virtual profit"
 void              SetVirtualCumulativeProfit(double cumulative_profit) { m_virtual_cumulative_profit=cumulative_perofit; };
//closes an open virtual position
 void              CloseVirtualPosition();

이러한 종류의 CheckPoint는 예를 들어 각 N개의 바 이후에 때때로 사용할 수 있습니다.

5.5. 기적은 없다

적응형 시스템은 성배가 아님을 기억해야 합니다(USDJPY H1, 4.01.2010-20.08.2010):

그림 8. 베스트 10 전략의 신호를 사용하는 적응 시스템의 균형 및 자기자본 곡선(USDJPY H1)

그림 8. 베스트 10 전략의 신호를 사용하는 적응 시스템의 균형 및 자기자본 곡선(USDJPY H1)

모든 전략의 자기자본 곡선은 그림 9에 나와 있습니다.

그림 9. 10가지 전략(USDJPY H1)을 기반으로 한 적응 시스템이 있는 계정의 주가 곡선

그림 9. 10가지 전략을 기반으로 한 적응 시스템이 있는 계정의 자기자본 곡선 (USDJPY H1)

적응 시스템에 수익성 있는 전략이 없으면 사용하는 것이 효과적이지 않습니다. 수익성 있는 전략을 사용하십시오.

우리는 또 다른 중요하고 흥미로운 점을 고려해야 합니다. 거래 초기에 적응 전략의 동작에 주의하십시오.

그림 10. 적응 전략의 10가지 전략이 있는 계정의 자기자본 곡선

그림 10. 적응 전략의 10가지 전략이 있는 계정의 자기자본 곡선

처음에는 모든 전략이 부정적인 결과를 가져왔고 적응 전략은 거래를 중단했습니다. 그런 다음 긍정적인 결과를 가져온 전략 사이를 전환하기 시작했습니다. 그리고 나서 모든 전략은 다시 무익해졌습니다.

모든 전략은 처음에 동일한 균형을 가지고 있습니다. 그리고 얼마 지나지 않아 하나 또는 다른 전략이 리더가 됩니다. 따라서 첫 번째 바에서 거래를 피하기 위해 적응 전략에 제한을 설정하는 것이 좋습니다. 이를 수행하려면 CAdaptiveStrategy 클래스의 Expert_OnTick 함수를 변수로 보완합니다. 이 값은 새 바가 올 때마다 증가합니다.

처음에는 시장이 최선의 전략을 선택할 때까지 실제 거래를 멀리해야 합니다.


결론

이 글에서 우리는 각각 자체 "가상" 거래 작업을 수행하는 많은 전략으로 구성된 적응 시스템의 예를 고려했습니다. 실제 거래는 현재 가장 수익성이 높은 전략의 신호에 따라 수행됩니다.

표준 라이브러리의 객체 지향 접근 방식, 데이터 작업을 위한 클래스거래 클래스 덕분에 시스템 아키텍처는 다음과 같이 나타났습니다. 단순하고 확장 가능해야 합니다. 이제 수백 가지 거래 전략을 포함하는 적응형 시스템을 쉽게 만들고 분석할 수 있습니다.

P.S. 적응형 시스템의 동작에 대한 편의 분석을 위해 CSampleStrategy 클래스의 디버그 버전이 첨부되었습니다(adaptive-systems-mql5-sources-debug-en.zip 아카이브). 이 버전의 차이점은 작업 중에 텍스트 파일을 생성한다는 것입니다. 여기에는 시스템에 포함된 전략의 가상 균형/자본 변화의 역학에 대한 요약 보고서가 포함됩니다.

MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/143

MQL5의 Expert Advisor 테스트 및 최적화 가이드 MQL5의 Expert Advisor 테스트 및 최적화 가이드
이 문서에서는 코드 오류를 식별하고 해결하는 단계별 프로세스와 Expert Advisor 입력 매개변수를 테스트하고 최적화하는 단계를 설명합니다. MetaTrader 5 클라이언트 터미널의 Strategy Tester를 사용하여 Expert Advisor에 가장 적합한 기호와 입력 매개변수 세트를 찾는 방법을 배우게 됩니다.
Bill Williams의 "New Trading Dimensions"에 기반한 Expert Advisor Bill Williams의 "New Trading Dimensions"에 기반한 Expert Advisor
이 글에서는 Bill Williams의 "New Trading Dimensions: How to Profit from Chaos in Stocks, Bonds, and Commodities" 책을 기반으로 한 Expert Advisor의 개발에 대해 논의할 것입니다. 이 전략 자체는 잘 알려져 있으며 그 사용은 여전히 ​​트레이더들 사이에서 논란이 되고 있습니다. 이 글은 시스템의 거래 신호, 구현의 세부 사항 및 과거 데이터에 대한 테스트 결과를 고려합니다.
MetaTrader 5의 주문, 포지션 및 거래 MetaTrader 5의 주문, 포지션 및 거래
강력한 거래 로봇을 만드는 것은 MetaTrader 5 거래 시스템의 메커니즘에 대한 이해 없이는 수행할 수 없습니다. 클라이언트 터미널은 거래 서버로부터 포지션, 주문 및 거래에 대한 정보를 수신합니다. MQL5를 사용하여 이 데이터를 올바르게 처리하려면 MQL5 프로그램과 클라이언트 터미널 간의 상호 작용을 잘 이해해야 합니다.
거래 시스템의 평가 - 일반적 진입, 퇴출 및 거래의 효율성 거래 시스템의 평가 - 일반적 진입, 퇴출 및 거래의 효율성
거래 시스템의 효율성과 수익성을 결정할 수 있는 많은 조치가 있습니다. 그러나 트레이더는 항상 모든 시스템을 새로운 충돌 테스트에 적용할 준비가 되어 있습니다. 이 글은 효율성 측정에 기반한 통계가 MetaTrader 5 플랫폼에 어떻게 사용될 수 있는지 알려줍니다. 여기에는 S.V.의 "Statistika dlya traderov"("Statistics for traders") 책에 나와 있는 설명과 모순되지 않는 거래로 통계 해석을 변환하는 클래스가 포함됩니다. 불라쇼프 (Bulashev). 또한 최적화를 위한 사용자 정의 함수의 예도 포함되어 있습니다.