적응형 거래 시스템과 MetaTrader 5 클라이언트 터미널에서의 사용
소개
전 세계 수십만 명의 트레이더가 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에서 볼 수 있듯이 Expert Advisors는 작업 첫 2주 동안 거의 동일한 결과를 얻었지만 점점 더 수익이 크게 달라지기 시작했습니다. 테스트 기간이 끝날 때 Expert Advisors는 기간 63, 53 및 43에서 최고의 거래 결과를 보여주었습니다.
시장은 최고의 것을 선택했습니다. 왜 우리는 그 선택을 따라야 합니까? 하나의 Expert Advisor에서 10가지 전략을 모두 결합하고 각 전략에 대해 "가상" 거래의 가능성을 제공하고 주기적으로(예: 각각의 새로운 바가 시작될 때) 신호에 따라 실제 거래 및 거래를 위한 최상의 전략을 결정하면 어떻게 될까요?
획득한 적응 전략의 결과는 그림 2에 나와 있습니다. 적응형 거래 계정의 자기자본 곡선은 빨간색으로 표시됩니다. 기간의 절반 이상 동안 적응형 전략에 대한 자기자본 곡선의 형태는 MA_63 전략과 동일하며 마침내 승자로 나타났습니다.
그림 2. 10가지 거래 시스템의 신호를 사용하는 적응 전략이 있는 계정의 주가 곡선
균형 곡선은 유사한 역학을 가지고 있습니다(그림 3).
그림 3. 10가지 거래 시스템의 신호를 사용하는 적응 전략의 균형 곡선
어떤 전략도 현재 수익성이 없다면 적응형 시스템은 거래 작업을 수행하지 않아야 합니다. 그러한 경우의 예가 그림 4에 나와 있습니다 (2010년 1월 4일부터 22일까지 기간).
그림 4. 적응형 전략이 수익성 있는 전략의 부재로 인해 새로운 포지션을 열지 못하게 된 기간
2010년 1월부터 MA_3 전략이 최고의 효율성을 보여줍니다. MA_3(파란색)은 그 순간 최대 수익을 올렸으므로 적응형 전략(빨간색)은 신호를 따랐습니다. 1월 8일부터 20일까지의 기간 동안 고려된 모든 전략이 부정적인 결과를 얻었으므로 적응 전략이 새로운 거래 포지션을 열지 못했습니다.
모든 전략이 부정적인 결과를 가져오면 거래를 멀리하는 것이 좋습니다. 이것은 수익성이 없는 거래를 중단하고 돈을 절약할 수 있게 해주는 중요한 것입니다.
2. 적응형 거래 전략의 구현
이 섹션에서는 여러 거래 전략을 동시에 사용하여 "가상" 거래를 수행하고 신호에 따라 실제 거래에 가장 수익성이 높은 것을 선택하는 적응 전략의 구조를 고려할 것입니다. 객체 지향 접근 방식을 사용하면 이 문제를 훨씬 쉽게 해결할 수 있습니다.
먼저 적응형 Expert Advisor의 코드를 조사한 다음 적응형 시스템의 기능이 구현된 CAdaptiveStrategy에 대해 자세히 살펴본 다음 가상 거래 기능이 구현되는 거래 전략의 기본 클래스인 CSampleStrategy 클래스의 구조를 보여줍니다.
또한 이동 평균과 확률적 오실레이터에 의한 거래 전략을 나타내는 CStrategyMA 및 CStrategyStoch 클래스의 두 하위 코드를 고려할 것입니다. 구조를 분석한 후 전략을 실현하는 클래스를 쉽게 작성하고 추가할 수 있습니다.
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, OnDeinit 및 OnTick 함수의 코드는 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 배열이 되며 거래 전략의 "컨테이너"로 사용됩니다.
각 전략은 클래스로 표시됩니다. 이 경우 이동 평균에 의한 거래와 스토캐스틱 오실레이터에 의한 거래 전략을 나타내는 CStrategyMA 및 CStrategyStoch 클래스가 포함된 파일을 포함했습니다.
현재 포지션의 속성을 요청하고 거래 작업을 수행하기 위해 표준 라이브러리의 CPositionInfo 및 CTrade 클래스를 사용하므로 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()); } } }
트레이드 클래스를 사용하여 트레이드 포지션으로 작업하는 것이 더 쉽습니다. CPositionInfo 및 CTrade 클래스의 개체를 각각 시장 포지션 속성을 요청하고 거래 작업을 수행하는 데 사용했습니다.
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 함수가 호출됩니다. 다음 거래 신호 중 네 가지 중 하나가 전달됩니다.
- 롱 포지션 오픈 시그널(SIGNAL_OPEN_LONG)
- 숏 포지션 오픈 시그널(SIGNAL_OPEN_SHORT)
- 롱 포지션 청산 신호(SIGNAL_CLOSE_LONG)
- 매도 포지션 청산 신호(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에서 볼 수 있듯이 모든 CAdaptiveMA 전략이 부정적인 결과를 낳은 기간 동안 CAdaptiveMAinv 전략을 따르면 Expert Advisor가 원치 않는 손실을 피할 수 있었습니다. 거래의 아주 시작.
그림 6. 적응 전략이 "역 추세" 신호를 사용한 기간CAdaptiveMAinv
이러한 접근 방식은 수용할 수 없는 것처럼 보일 수 있습니다. 반대 추세 전략을 사용할 때 보증금을 잃는 것은 시간 문제일 뿐이기 때문입니다. 그러나 우리의 경우 단일 전략으로 제한되지 않습니다. 시장은 현재 어떤 전략이 효과적인지 더 잘 알고 있습니다.
적응형 시스템의 장점은 시장이 스스로 어떤 전략을 사용해야 하고 언제 사용해야 하는지 제안한다는 것입니다.
전략의 논리에서 추상화할 수 있는 가능성을 제공합니다. 전략이 효과적이라면 전략이 작동하는 방식은 중요하지 않습니다. 적응형 접근 방식은 전략의 유일한 성공 기준인 효과를 사용합니다.
4.2. 최악의 전략의 신호를 뒤집을 가치가 있습니까?
위에 표시된 반전이 있는 트릭은 최악의 전략의 신호를 사용할 수 있는 잠재적 가능성에 대한 생각으로 이어집니다. 전략이 수익성이 없는 경우(그리고 최악의 경우) 반대로 행동하여 이익을 얻을 수 있습니까?
단순히 신호를 변경하여 지는 전략을 수익성 있는 전략으로 바꿀 수 있습니까? 이 질문에 답하기 위해서는 CAdaptiveStrategy 클래스의 Expert_OnTick() 함수에서 ArrayMaximum을 ArrayMinimum으로 변경하고, 의 값을 곱하여 방향 변경을 구현해야 합니다. BestDirection 변수는 -1입니다.
또한 부정적인 효과의 경우 가상 거래의 한계를 언급해야 합니다(최악의 전략의 결과를 분석할 예정이므로).
//if((Performance[BestStrategyIndex]<0) && (RealPositionDirection()==0)) {return;}
최악의 전략의 역 신호를 사용하는 적응형 Expert Advisor의 형평성 다이어그램은 그림 7에 나와 있습니다.
그림 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)
모든 전략의 자기자본 곡선은 그림 9에 나와 있습니다.
그림 9. 10가지 전략을 기반으로 한 적응 시스템이 있는 계정의 자기자본 곡선 (USDJPY H1)
적응 시스템에 수익성 있는 전략이 없으면 사용하는 것이 효과적이지 않습니다. 수익성 있는 전략을 사용하십시오.
우리는 또 다른 중요하고 흥미로운 점을 고려해야 합니다. 거래 초기에 적응 전략의 동작에 주의하십시오.
그림 10. 적응 전략의 10가지 전략이 있는 계정의 자기자본 곡선
처음에는 모든 전략이 부정적인 결과를 가져왔고 적응 전략은 거래를 중단했습니다. 그런 다음 긍정적인 결과를 가져온 전략 사이를 전환하기 시작했습니다. 그리고 나서 모든 전략은 다시 무익해졌습니다.
모든 전략은 처음에 동일한 균형을 가지고 있습니다. 그리고 얼마 지나지 않아 하나 또는 다른 전략이 리더가 됩니다. 따라서 첫 번째 바에서 거래를 피하기 위해 적응 전략에 제한을 설정하는 것이 좋습니다. 이를 수행하려면 CAdaptiveStrategy 클래스의 Expert_OnTick 함수를 변수로 보완합니다. 이 값은 새 바가 올 때마다 증가합니다.
처음에는 시장이 최선의 전략을 선택할 때까지 실제 거래를 멀리해야 합니다.
결론
이 글에서 우리는 각각 자체 "가상" 거래 작업을 수행하는 많은 전략으로 구성된 적응 시스템의 예를 고려했습니다. 실제 거래는 현재 가장 수익성이 높은 전략의 신호에 따라 수행됩니다.
표준 라이브러리의 객체 지향 접근 방식, 데이터 작업을 위한 클래스 및 거래 클래스 덕분에 시스템 아키텍처는 다음과 같이 나타났습니다. 단순하고 확장 가능해야 합니다. 이제 수백 가지 거래 전략을 포함하는 적응형 시스템을 쉽게 만들고 분석할 수 있습니다.
P.S. 적응형 시스템의 동작에 대한 편의 분석을 위해 CSampleStrategy 클래스의 디버그 버전이 첨부되었습니다(adaptive-systems-mql5-sources-debug-en.zip 아카이브). 이 버전의 차이점은 작업 중에 텍스트 파일을 생성한다는 것입니다. 여기에는 시스템에 포함된 전략의 가상 균형/자본 변화의 역학에 대한 요약 보고서가 포함됩니다.
MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/143