English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
MQL5 Cookbook: 트리플 스크린 전략에 기반한 거래 시스템을 위한 프레임워크 개발

MQL5 Cookbook: 트리플 스크린 전략에 기반한 거래 시스템을 위한 프레임워크 개발

MetaTrader 5 | 2 9월 2021, 17:09
73 0
Anatoli Kazharski
Anatoli Kazharski

소개

거래 시스템을 검색하거나 개발할 때 많은 거래자는 Alexander Elder가 도입한 Triple Screen 전략에 대해 들어봤을 것입니다. 인터넷에는 그 전략에 대해 부정적인 판단을 하는 사람들이 많이 있습니다. 그러나 많은 사람들은 그것이 이익을 얻는 데 도움이 될 수 있다고 믿습니다. 두 가지 의견 중 하나를 신뢰할 필요는 없습니다. 모든 것은 항상 직접 확인해야 합니다. 프로그래밍을 공부한다면 백 테스팅을 사용하여 거래 전략의 성과를 확인할 수 있으므로 모든 것이 당신의 손에 달려 있습니다.

이 글에서는 MQL5의 Triple Screen 전략을 기반으로 하는 거래 시스템의 프레임워크를 개발할 것입니다. Expert Advisor는 처음부터 개발되지 않습니다. 대신 이전 글 "MQL5 Cookbook: 지표를 사용하여 Expert Advisor의 거래 조건 설정"에서 프로그램을 수정하기만 하면 됩니다. 따라서 이 글에서는 기성 프로그램의 패턴을 쉽게 수정할 수 있는 방법도 보여줍니다.

이전 글의 Expert Advisor는 이미 Stop Loss/Take Profit 및 Trailing Stop 레벨, 포지션 볼륨 증가 및 반대 신호에 대한 포지션 반전을 활성화/비활성화할 수 있는 가능성을 제공합니다. 필요한 모든 기능이 제자리에 설정되었습니다. 따라서 우리의 작업은 추가 옵션을 추가하고 일부 기존 기능을 수정하여 외부 매개변수 목록을 변경하는 데 중점을 둡니다.

설명을 위해 이동 평균 지표를 사용하여 생성될 3개의 시간 프레임에 대한 신호를 정렬합니다. 나중에 개발된 프레임워크를 계속 실험하면서 코드를 약간 수정하여 다른 지표를 사용할 수 있습니다. 우리는 또한 각 화면에 대한 시간 프레임을 설정할 수 있는 기회를 구현할 것입니다. 표시 기간을 담당하는 매개변수의 값이 0이면 해당 화면을 사용하지 않음을 나타냅니다. 즉, 시스템은 하나 또는 두 개의 시간 프레임을 갖도록 설정할 수 있습니다.

시작하기 전에 이전 글의 Expert Advisor 파일이 있는 폴더를 복사하고 이름을 바꿉니다.

 

Expert Advisor 개발

외부 매개변수부터 시작하겠습니다. 아래는 업데이트된 목록의 코드입니다. 새로운 라인이 선택됩니다. 시간 프레임은 ENUM_TIMEFRAMES 열거 유형으로 선언됩니다. 드롭다운 목록에서 시간 프레임을 선택할 수 있습니다.

//--- External parameters of the Expert Advisor
sinput   long              MagicNumber=777;        // Magic number
sinput   int               Deviation=10;           // Slippage
//---
input    ENUM_TIMEFRAMES   Screen01TimeFrame=PERIOD_W1;  // Time frame of the first screen
input    int               Screen01IndicatorPeriod=14;   // Indicator period of the first screen
//---
input    ENUM_TIMEFRAMES   Screen02TimeFrame=PERIOD_D1;  // Time frame of the second screen
input    int               Screen02IndicatorPeriod=24;   // Indicator period of the second screen
//---
input    ENUM_TIMEFRAMES   Screen03TimeFrame=PERIOD_H4;  // Time frame of the third screen
input    int               Screen03IndicatorPeriod=44;   // Indicator period of the third screen
//---
input    double            Lot=0.1;                      // Lot
input    double            VolumeIncrease=0.1;           // Position volume increase
input    double            VolumeIncreaseStep=10;        // Step for position volume increase
input    double            StopLoss=50;                  // Stop Loss
input    double            TakeProfit=100;               // Take Profit
input    double            TrailingStop=10;              // Trailing Stop
input    bool              Reverse=true;                 // Position reversal
sinput   bool              ShowInfoPanel=true;           // Display of the info panel

예제를 단순화하기 위해 IndicatorSegments 매개변수와 AllowedNumberOfSegments 변수 및 CorrectInputParameters() 함수가 제거되었습니다. 이 조건에 관심이 있는 분들은 직접 구현해 볼 수 있습니다. 또한 이 Expert Advisor는 하나의 지표만 사용하므로 Enums.mqh 파일에서 지표 열거를 제거해야 합니다.

각 시간 프레임에 별도의 지표가 있으므로 각 지표의 핸들을 가져오려면 별도의 변수가 필요합니다.

//--- Indicator handles
int                  Screen01IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the first screen
int                  Screen02IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the second screen
int                  Screen03IndicatorHandle=INVALID_HANDLE;   // Indicator handle on the third screen

새 바는 최소 시간 프레임을 사용하여 확인됩니다. 외부 매개변수에서 최소 시간 프레임을 설정할 때 특정 순서, 즉 최대, 중간, 최소를 따를 필요는 없습니다. 역순과 기본적으로 모든 순서가 가능합니다. 따라서 지정된 모든 시간 프레임 중에서 최소 시간 프레임을 식별하는 함수가 필요합니다.

Expert Advisor는 3개의 시간대와 1~2개의 시간대에 작동하도록 설정할 수 있으므로 최소 시간 범위를 결정할 때 모든 옵션을 고려해야 합니다. GetMinimumTimeframe() 함수의 코드가 아래와 같은 경우:

//+------------------------------------------------------------------+
//| Determining the minimum time frame for the new bar check         |
//+------------------------------------------------------------------+
ENUM_TIMEFRAMES GetMinimumTimeframe(ENUM_TIMEFRAMES timeframe1,int period1,
                                    ENUM_TIMEFRAMES timeframe2,int period2,
                                    ENUM_TIMEFRAMES timeframe3,int period3)
  {
//--- Default minimum time frame value
   ENUM_TIMEFRAMES timeframe_min=PERIOD_CURRENT;

//--- Convert time frame values to seconds for calculations
   int t1= PeriodSeconds(timeframe1);
   int t2= PeriodSeconds(timeframe2);
   int t3= PeriodSeconds(timeframe3);

//--- Check for incorrect period values
   if(period1<=0 && period2<=0 && period3<=0)
      return(timeframe_min);

//--- Conditions for a single time frame
   if(period1>0 && period2<=0 && period3<=0)
      return(timeframe1);
   if(period2>0 && period1<=0 && period3<=0)
      return(timeframe2);
   if(period3>0 && period1<=0 && period2<=0)
      return(timeframe3);

//--- Conditions for two time frames
   if(period1>0 && period2>0 && period3<=0)
     {
      timeframe_min=(MathMin(t1,t2)==t1) ? timeframe1 : timeframe2;
      return(timeframe_min);
     }
   if(period1>0 && period3>0 && period2<=0)
     {
      timeframe_min=(MathMin(t1,t3)==t1) ? timeframe1 : timeframe3;
      return(timeframe_min);
     }
   if(period2>0 && period3>0 && period1<=0)
     {
      timeframe_min=(MathMin(t2,t3)==t2) ? timeframe2 : timeframe3;
      return(timeframe_min);
     }

//--- Conditions for three time frames
   if(period1>0 && period2>0 && period3>0)
     {
      timeframe_min=(int)MathMin(t1,t2)==t1 ? timeframe1 : timeframe2;
      int t_min=PeriodSeconds(timeframe_min);
      timeframe_min=(int)MathMin(t_min,t3)==t_min ? timeframe_min : timeframe3;
      return(timeframe_min);
     }
   return(WRONG_VALUE);
  }

최소 시간 프레임 값을 저장하기 위해 다른 전역 범위 변수를 생성합니다.

//--- Variable for determining the minimum time frame
ENUM_TIMEFRAMES  MinimumTimeframe=WRONG_VALUE;

GetMinimumTimeframe() 함수는 OnInit() 함수에서 Expert Advisor를 초기화할 때 호출해야 합니다.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }

MinimumTimeframe 변수 값은 CheckNewBar()GetBarsData() 함수에서 사용됩니다.

GetIndicatorHandle() 함수는 이제 아래와 같이 보입니다. 기간과 기간은 각 지표에 대해 지정됩니다.

//+------------------------------------------------------------------+
//| Getting indicator handles                                        |
//+------------------------------------------------------------------+
void GetIndicatorHandles()
  {
//--- Get handles of the indicators specified in the parameters
   if(Screen01IndicatorPeriod>0)
     Screen01IndicatorHandle=iMA(_Symbol,Screen01TimeFrame,Screen01IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen02IndicatorPeriod>0)
     Screen02IndicatorHandle=iMA(_Symbol,Screen02TimeFrame,Screen02IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
   if(Screen03IndicatorPeriod>0)
     Screen03IndicatorHandle=iMA(_Symbol,Screen03TimeFrame,Screen03IndicatorPeriod,0,MODE_SMA,PRICE_CLOSE);
     
//--- If the indicator handle for the first time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 1!");
//--- If the indicator handle for the second time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 2!");
//--- If the indicator handle for the third time frame could not be obtained
   if(Screen01IndicatorHandle==INVALID_HANDLE)
     Print("Failed to get the indicator handle for Screen 3!");
  }

또한 지표 값을 가져오기 위한 배열을 추가해야 합니다(각 시간 프레임에 대해 별도로).

//--- Arrays for values of the indicators
double               indicator_buffer1[];
double               indicator_buffer2[];
double               indicator_buffer3[];

이제 지표 값을 가져오는 GetIndicatorsData() 함수가 아래와 같이 표시됩니다. 얻은 핸들의 정확성을 확인하고 모든 것이 정상이면 배열이 지표 값으로 채워집니다.

//+------------------------------------------------------------------+
//| Getting indicator values                                         |
//+------------------------------------------------------------------+
bool GetIndicatorsData()
  {
//--- Number of indicator buffer values for determining the trading signal   
   int NumberOfValues=3;
//--- If indicator handles have not been obtained
   if((Screen01IndicatorPeriod>0 && Screen01IndicatorHandle==INVALID_HANDLE) ||
      (Screen02IndicatorPeriod>0 && Screen02IndicatorHandle==INVALID_HANDLE) ||
      (Screen03IndicatorPeriod>0 && Screen03IndicatorHandle==INVALID_HANDLE))
      //--- try to get them again
      GetIndicatorHandles();

//--- If the time frame of the first screen is used and the indicator handle has been obtained
   if(Screen01TimeFrame>0 && Screen01IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer1,true);
      //--- Get indicator values
      if(CopyBuffer(Screen01IndicatorHandle,0,0,NumberOfValues,indicator_buffer1)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer1 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the second screen is used and the indicator handle has been obtained
   if(Screen02TimeFrame>0 && Screen02IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer2,true);
      //--- Get indicator values
      if(CopyBuffer(Screen02IndicatorHandle,0,0,NumberOfValues,indicator_buffer2)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer2 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//--- If the time frame of the third screen is used and the indicator handle has been obtained
   if(Screen03TimeFrame>0 && Screen03IndicatorHandle!=INVALID_HANDLE)
     {
      //--- Reverse the indexing order (... 3 2 1 0)
      ArraySetAsSeries(indicator_buffer3,true);
      //--- Get indicator values
      if(CopyBuffer(Screen03IndicatorHandle,0,0,NumberOfValues,indicator_buffer3)<NumberOfValues)
        {
         Print("Failed to copy the values ("+
                  _Symbol+"; "+TimeframeToString(Period())+") to the indicator_buffer3 array! Error ("+
                  IntegerToString(GetLastError())+"): "+ErrorDescription(GetLastError()));
         //---
         return(false);
        }
     }
//---
   return(true);
  }

GetTradingSignal()GetSignal() 함수는 당면한 작업에 따라 수정되어야 합니다. 다음은 이러한 기능의 코드입니다.

//+------------------------------------------------------------------+
//| Determining trading signals                                      |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetTradingSignal()
  {
//--- If there is no position
   if(!pos.exists)
     {
      //--- A Sell signal
      if(GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      //--- A Buy signal
      if(GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
     }
//--- If the position exists
   if(pos.exists)
     {
      //--- Get the position type
      GetPositionProperties(P_TYPE);
      //--- Get the last deal price
      GetPositionProperties(P_PRICE_LAST_DEAL);

      //--- A Sell signal
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_SELL)
         return(ORDER_TYPE_SELL);
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_SELL && 
         close_price[1]<pos.last_deal_price-CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_SELL);

      //--- A Buy signal
      if(pos.type==POSITION_TYPE_SELL && 
         GetSignal()==ORDER_TYPE_BUY)
         return(ORDER_TYPE_BUY);
      if(pos.type==POSITION_TYPE_BUY && 
         GetSignal()==ORDER_TYPE_BUY && 
         close_price[1]>pos.last_deal_price+CorrectValueBySymbolDigits(VolumeIncreaseStep*_Point))
         return(ORDER_TYPE_BUY);

     }
//--- No signal
   return(WRONG_VALUE);
  }

GetSignal() 함수는 최소 시간 프레임을 결정할 때와 마찬가지로 포지션 개방 조건과 관련된 외부 매개변수 상태의 가능한 모든 변형을 고려합니다. 함수 코드는 아래와 같습니다.

//+------------------------------------------------------------------+
//| Checking the condition and returning a signal                    |
//+------------------------------------------------------------------+
ENUM_ORDER_TYPE GetSignal()
  {
//--- A SELL SIGNAL: the current value of the indicators on completed bars is lower than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
//---
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer3[1]<indicator_buffer3[2])
         return(ORDER_TYPE_SELL);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]<indicator_buffer1[2] && 
         indicator_buffer2[1]<indicator_buffer2[2] && 
         indicator_buffer3[1]<indicator_buffer3[2]
         )
         return(ORDER_TYPE_SELL);
     }

//--- A BUY SIGNAL: the current value of the indicators on completed bars is higher than on the previous bars
//--- Conditions for a single time frame
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
     
//--- Conditions for two time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod<=0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod<=0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod<=0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer3[1]>indicator_buffer3[2])
         return(ORDER_TYPE_BUY);
     }

//--- Conditions for three time frames
   if(Screen01IndicatorPeriod>0 && Screen02IndicatorPeriod>0 && Screen03IndicatorPeriod>0)
     {
      if(indicator_buffer1[1]>indicator_buffer1[2] && 
         indicator_buffer2[1]>indicator_buffer2[2] && 
         indicator_buffer3[1]>indicator_buffer3[2]
         )
         return(ORDER_TYPE_BUY);
     }
     
//--- No signal
   return(WRONG_VALUE);
  }

이제 OnInit()OnDeinit() 함수를 약간만 변경하면 됩니다. 아래 코드에서 강조 표시된 변경 사항을 볼 수 있습니다.

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Determine the minimum time frame for the new bar check
   MinimumTimeframe=GetMinimumTimeframe(Screen01TimeFrame,Screen01IndicatorPeriod,
                                        Screen02TimeFrame,Screen02IndicatorPeriod,
                                        Screen03TimeFrame,Screen03IndicatorPeriod);
//--- Get indicator handles
   GetIndicatorHandles();
//--- Initialize the new bar
   CheckNewBar();
//--- Get the properties
   GetPositionProperties(P_ALL);
//--- Set the info panel
   SetInfoPanel();
//---
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- Print the deinitialization reason to the journal
   Print(GetDeinitReasonText(reason));
//--- When deleting from the chart
   if(reason==REASON_REMOVE)
     {
      //--- Delete all objects relating to the info panel from the chart
      DeleteInfoPanel();
      //--- Delete the indicator handles
      IndicatorRelease(Screen01IndicatorHandle);
      IndicatorRelease(Screen02IndicatorHandle);
      IndicatorRelease(Screen03IndicatorHandle);
     }
  } 

트리플 스크린 전략에 기반한 거래 시스템을 위한 프레임워크가 준비되었습니다. 지표를 변경하거나 필요한 경우 몇 가지 추가 조건을 추가하여 언제든지 수정할 수 있습니다.

 

매개변수 최적화 및 Expert Advisor 테스트

파라미터 최적화를 진행하여 결과를 확인해보자. 전략 테스터는 아래와 같이 설정됩니다(세 시간 프레임 중 가장 낮은 시간을 지정해야 함).

그림 1. 전략 테스터 설정

그림 1. 전략 테스터 설정.

최적화를 위한 Expert Advisor 매개변수는 아래와 같이 설정되었습니다. 최적화를 위해 시간 프레임을 설정할 수 있지만 수동으로 설정하는 것을 선호합니다.

그림 2. Expert Advisor의 설정

그림 2. Expert Advisor의 설정.

최적화는 듀얼 코어 프로세서에서 약 30분 만에 완료되었습니다. The Optimization Graph is provided below:

그림 3. 최적화 그래프

그림 3. 최적화 그래프.

최대 균형 테스트 결과는 최대 회복 계수 테스트 결과보다 더 적은 드로다운을 보여주므로 최대 균형 테스트 결과가 데모 목적으로 사용되는 이유입니다.

그림 4. 최대 균형 테스트 결과

그림 4. 최대 균형 테스트 결과.

그림 5. 최대 균형 테스트 그래프

그림 5. 최대 균형 테스트 그래프.

 

결론

이 글에서는 주요 기능을 사용할 수 있는 경우 Expert Advisor를 상당히 빠르게 수정할 수 있음을 보여주었습니다. 시그널 블록과 지표만 변경하면 새로운 거래 시스템을 얻을 수 있습니다. 글에 첨부된 다운로드 가능한 아카이브에는 추가 자가 학습을 위해 위에 설명된 Expert Advisor의 소스 코드와 입력 매개변수 설정이 포함된 세트 파일이 포함되어 있습니다.

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

MQL5 Cookbook: 다중 통화 Expert Advisor - 간단하고 깔끔하며 빠른 접근 MQL5 Cookbook: 다중 통화 Expert Advisor - 간단하고 깔끔하며 빠른 접근
이 글에서는 다중 통화 Expert Advisor에 적합한 간단한 접근 방식의 구현에 대해 설명합니다. 이는 동일한 조건에서 각 기호에 대해 다른 매개변수를 사용하여 테스트/거래를 위해 Expert Advisor를 설정할 수 있음을 의미합니다. 예를 들어, 필요한 경우 코드를 약간 변경하여 추가 기호를 추가할 수 있는 방식으로 두 개의 기호에 대한 패턴을 만들 것입니다.
지그재그 지표: 신선한 접근 방식과 새로운 솔루션 지그재그 지표: 신선한 접근 방식과 새로운 솔루션
이 글에서는 고급 ZigZag 지표를 만들 가능성을 검토합니다. 노드를 식별하는 아이디어는 Envelopes 지표의 사용을 기반으로 합니다. 우리는 모든 ZigZag 노드가 Envelopes 밴드의 범위 내에 있는 일련의 Envelopes에 대한 입력 매개변수의 특정 조합을 찾을 수 있다고 가정합니다. 결과적으로 우리는 새로운 노드의 좌표를 예측하려고 시도할 수 있습니다.
MQL5 Cookbook: 매개변수 수에 제한이 없는 다중 통화 Expert Advisor 개발 MQL5 Cookbook: 매개변수 수에 제한이 없는 다중 통화 Expert Advisor 개발
이 글에서는 무제한의 매개변수를 허용하면서 거래 시스템 최적화를 위해 단일 매개변수 세트를 사용하는 패턴을 만들 것입니다. 기호 목록은 표준 텍스트 파일(*.txt)로 생성됩니다. 각 기호에 대한 입력 매개변수도 파일에 저장됩니다. 이렇게 하면 Expert Advisor의 입력 매개변수 수에 대한 터미널 제한을 피할 수 있습니다.
MQL5 Cookbook: 지표를 사용하여 Expert Advisor의 거래 조건 설정 MQL5 Cookbook: 지표를 사용하여 Expert Advisor의 거래 조건 설정
이 글에서는 MQL5 Cookbook 시리즈의 이전 글에서 작업한 Expert Advisor를 계속 수정할 것입니다. 이번에는 Expert Advisor가 포지션 개방 조건을 확인하는 데 사용할 값의 지표로 향상됩니다. 재미를 더하기 위해 외부 매개변수에 드롭다운 목록을 만들어 세 가지 거래 지표 중 하나를 선택할 수 있습니다.