English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
ORDER_MAGIC을 사용하여 단일 상품에서 여러 Expert Advisors와의 거래

ORDER_MAGIC을 사용하여 단일 상품에서 여러 Expert Advisors와의 거래

MetaTrader 5 | 5 7월 2021, 15:54
105 0
Mykola Demko
Mykola Demko


소개

MQL5에는 이 정보를 사용하여 주문을 식별하기 위해 각 보류중인 주문에 매직 넘버를 할당하는 함수가 있습니다. 이것은 서로 다른 Expert Advisor 간의 상호 작용의 광대한 가능성과 훨씬 더 복잡한 시스템의 개발을 열어줍니다. 이 글에서는 매직 넘버의 저평가된 기회에 대해 대중에게 알리고 싶습니다.

그러나 이 글의 주제로 넘어 가기 전에 매직 넘버를 구성하는 요소를 더 잘 이해해야 합니다. 어떤 Expert Advisors가 그것을 설정했는지를 결정하는 데 있어 어떤 숫자가 매지컬 (magical) 할 수 있을까요? "기적 (miracles)"은 개발자가 매직 넘버로 선언된 ulong , 유형에 설정한 기회에서 시작됩니다.

유형 ulong이 가장 깁니다

정수형 long을 자세히 살펴보면 이 유형의 최대 값이 경이적이라는 것을 알 수 있습니다.

유형

크기(바이트)

최소값

최대 가치

언어 C의 아날로그 + +

long

8

-9 223 372 036 854 775 808

9 223 372 036 854 775 807

__int64

ulong

8

0

18 446 744 073 709 551 615

서명되지 않은 __int64

표 1. long 및 ulong 데이터 유형의 속성

그러나 그 유형 ulong 은 긍정적이고 부정적인 가수를 결합하여 그를 능가했습니다.

그래서 지정된 길이는 거대하지만 이전에는 어떻게 사용 되었습니까?

mql 4에서 작업한 경험에서 저는 종종 많은 개발자들이 매직 넘버를 코딩하는 무의미함을 발견했습니다. 매직 넘버는 현명하게 사용됐지만 코딩은 어리석은 듯했다. 매직 넘버 12345의 개성에 대해 말할 수 있는 것은, 그러한 매직 (Magic)은 발전하는 협회 (fraternity)의 거의 절반에 의해 사용됩니다. 후반부는 매직 넘버 55555, 33333, 77777을 사용하며 이것은 거의 완전한 세트입니다. 저는 그의 컴퓨터에 1,000 명 이상의 Expert Advisor가 있을 가능성이 낮기 때문에 독자의 관심을 끌고 싶습니다. 따라서 1000은 모든 Expert Advisor의 개별 이름을 인코딩하기에 충분할 것입니다.

1000 - 전체 카테고리가 3 개뿐이므로 ulong 유형에서 사용할 수 있는 나머지 15 개 전체 카테고리는 어떻게 해야 합니까? 답은 간단합니다: 인코딩합니다.

Wikipidia는 코드라는 단어에 대해 무엇을 말합니까?:

코드 - 규칙 (알고리즘), 엄격하게 특정 조합의 각 개별 메시지에 대한 비교 기호 (문자) (또는 신호).

따라서 규칙을 만들겠습니다. Expert Advisor의 ID뿐만 아니라 실행중인 기기도 매직 넘버의 코드로 처방할 것을 제안합니다. 예를 들어, EURUSD, 에서 Expert Advisor가 실행되고 있다고해서 Expert Advisor가 해당 상품에만 주문을 표시한다는 의미는 아닙니다. 또한 Expert Advisor의 상호 작용 코드를 "귀하 / 외국인"과 같이 작성하는 것이 도움이 될 것이라고 생각합니다. 그러면 Expert Advisor가 포지션을 확인할 때 현재 주문이 친절한 Expert Advisor가 구성한 것임을 이해할 수 있습니다. 이것은 매우 복잡한 시스템을 만들기에 충분하다고 생각합니다.

이제 우리가 가진 것을 요약해보겠습니다. 우리가 시스템에 어떤 기회를 부여하고 있습니까?

  1. 둘 이상의 Expert Advisor가 단일 기기에서 작업하고 간섭하지 않을 가능성.
  2. 두 명 이상의 Expert Advisor가 서로 다른 기기에서 작업하고 서로를 보완할 수 있는 가능성.
  3. Expert Advisor와 협력하여 기기에서 주문을 식별하는 함수.

이제 작업이 설정되었으므로 이제 구현을 시작하겠습니다.

단순 Expert Advisor

간단한 Expert Advisor의 코드 초안을 작성합니다. 예를 들어 이동 방향으로 포지션을 유지합니다. 매직 넘버를 분석하기로 결정한 독자는 이미 초보자를 위한 MQL5 Expert Advisor 작성을 위한 단계별 가이드 글을 읽은 것 같습니다. 따라서 Expert Advisor 생성에 대해 자세히 설명하지 않을 것입니다. 기본적으로 Expert Advisor는 포지션 을 한 번 열고 다른 모든 시간에 전환합니다. 따라서 포지션을 열기 위한 함수, 즉 거래 요청 (거래 주문)을 위한 함수가 필요합니다.

거래 요청 구조의 필드를 채우기 위한 매개 변수를 계산하는 보조 클래스를 만듭니다.

//+------------------------------------------------------------------+
//| The class provides auxiliary trading calculations                |
//+------------------------------------------------------------------+
class CProvision
  {
protected:
   MqlTradeRequest   trades;                 // pointer to the request structure of OrderSend
public:
   int               TYPE(const double &v[]);  // determines the type, in respect to the  readings of the moving
   double            pricetype(int type);     // calculates the level of the opening, in respect to the type 
   double            SLtype(int type);        // calculates the level of the stop-loss in respect to the type
   double            TPtype(int type);        // calculates the level of the take-profit, in respect to the type
   long              spread();               // returns the spread of the current instrument
   int               SendOrder(ENUM_ORDER_TYPE type,double volume);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CProvision::SendOrder(ENUM_ORDER_TYPE type,double volume)
  {
   trades.action          =TRADE_ACTION_DEAL;       // Type of the implemented actions
   trades.magic           =magic;                 // Stamp of the Expert Advisor (identifier of the magic number)
   trades.symbol          =_Symbol;                // Name of the trading instrument
   trades.volume          =volume;                // Request the volume of the trade in lots
   trades.price           =pricetype((int)type);  // Price       
   trades.sl              =SLtype((int)type);     // Level of Stop Loss order
   trades.tp              =TPtype((int)type);     // Level of Take Profit order         
   trades.deviation=(int)spread();                // Maximum acceptable deviation from the requested price
   trades.type=type;                              // Order type
   trades.type_filling=ORDER_FILLING_FOK;
   if(OrderSend(trades,res)){return(res.retcode);}
   return(-1);
  }
//+------------------------------------------------------------------+
//| Determines the type, in respect to the reading of the moving     |
//+------------------------------------------------------------------+
int CProvision::TYPE(const double &v[])
  {
   double t=v[0]-v[1];
   if(t==0.0)t=1.0;
   return((int)(0.5*t/fabs(t)+0.5));
  }
//+------------------------------------------------------------------+
//| Calculates the level of opening in respect to the type           |
//+------------------------------------------------------------------+
double CProvision::pricetype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.ask);
      if(type==1)return(tick.bid);
     }
   return(-1);
  }
//+------------------------------------------------------------------+
//| Calculates the level of stop-loss in respect to the type         |
//+------------------------------------------------------------------+
double CProvision::SLtype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.bid-SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
      if(type==1)return(tick.ask+SL*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Calculates the level of timeframe in respect to the type         |
//+------------------------------------------------------------------+
double CProvision::TPtype(int type)
  {
   if(SymbolInfoTick(_Symbol,tick))
     {
      if(type==0)return(tick.bid+TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
      if(type==1)return(tick.ask-TP*SymbolInfoDouble(Symbol(),SYMBOL_POINT));
     }
   return(0);
  }
//+------------------------------------------------------------------+
//| Returns the spread                                               |
//+------------------------------------------------------------------+
long CProvision::spread() 
  {
   return(SymbolInfoInteger(_Symbol,SYMBOL_SPREAD));
  }

이러한 클래스가 있으면 문제없이 간단한 Expert Advisor에 대한 코드를 작성할 수 있습니다. 

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+

//--- Input parameters
input ulong              magic       =1;           // magic
input int                SL          =300;         // Stop Loss
input int                TP          =1000;        // Take Profit
input int                MA_Period   =25;         // MA period
input double             lot         =0.1;         // Volume of position
input int                MA_shift    =0;          // Shift of indicator
input ENUM_MA_METHOD     MA_smooth   =MODE_SMA;     // Smoothing type
input ENUM_APPLIED_PRICE price       =PRICE_OPEN;    // Price type 

//--- We will store the indicator's handle
int
MA_handle,     // Handle of the indicator
type_MA,       // Type that specify the direction of MA
rezult;        // The variable takes the value of the result of the OrderSend operation
double v[2];    // Buffer for receiving values of MA

MqlTradeResult   res;   // Pointer to the structure of responding by OrderSend
MqlTick         tick;  // Pointer to the structure of last market information
CProvision      prov;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication

   if(PositionSelect(_Symbol))// If there is an open position 
     {
      if(PositionGetInteger(POSITION_TYPE)!=type_MA)// Check if its time to close
        {
         Print("#",magic,"Position by magic number has volume ",PositionGetDouble(POSITION_VOLUME),
               " reverse position of type ",PositionGetInteger(POSITION_TYPE)," by ",type_MA);
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,PositionGetDouble(POSITION_VOLUME)+lot);
         // reverse the position
         if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("#",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Position by magic number has volume ",PositionGetDouble(POSITION_VOLUME),
            " open position of type ",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);
      // open position 
      if(rezult!=-1)Print("#",magic," Code of operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  } 

그것을 실행하고 Expert Advisor의 수익성이 다르지 않지만 지정된 로직에 따라 정확하게 거래되는지 확인하십시오.

그림 1. 단일 기기에 대한 한 명의 Expert Advisor의 작업

그림 1. 단일 기기에 대한 한 명의 Expert Advisor의 작업

이제이 EA를 실행하려고 하지만 한 기기의 다른 시간 프레임에서 실행합니다 (실험을 위해 임의의 기기를 선택했습니다. EURUSD: o)

그림 2. 서로 다른 시간대에 동일한 도구를 사용하는 두 Expert Advisor의 충돌

그림 2. 서로 다른 시간대에 동일한 도구를 사용하는 두 Expert Advisor의 충돌

두 Expert Advisors가 하나의 상품에서 실행되고 코드가 포지션 공유를 지정하지 않기 때문에, 두 Expert Advisor는 인디케이터의 판독 값에 따라 거래 포지션을 수정하려고 합니다. - 갈등이 생긴다. M1에서 실행되는 Expert Advisor는 Cell의 포지션을 ​​바꾸려고 노력하고 있으며 경쟁자는 이를 막으려고 합니다. 별도의 포지션 계산이 필요하다는 것이 분명합니다.


위치 또는 가상 위치?

MetaTrader 5 개발자 가 주문에서 포지션 고려로 이동했기 때문에 관련 함수를 더 자세히 고려하는 것이 합리적입니다. 기록 위치.

// Returns the number of open positions.
int     PositionsTotal();

// Returns the symbol of the open position by the number in the list of positions.
string  PositionGetSymbol(int  index);

// Selects the open position for further working with it.
bool    PositionSelect(string  symbol, uint timeout=0);

// Function returns the requested property of the open position.
double  PositionGetDouble(ENUM_POSITION_PROPERTY  property_id);

// The function returns the requested property of the open position.
long    PositionGetInteger(ENUM_POSITION_PROPERTY  property_id);

// The function returns the requested property of the open position.
string  PositionGetString(ENUM_POSITION_PROPERTY  property_id);

표 2-4에 주어진 준수 포지션 속성 PositionGetDouble, PositionGetInteger, 및 PositionGetString의 요청을 얻는 함수에 대한 열거형 식별자.

식별자

기술

유형

POSITION_VOLUME

포지션 볼륨

더블

POSITION_PRICE_OPEN

포지션 가격

더블

POSITION_SL

오픈 포지션에 대한 손절매 수준

더블

POSITION_TP

오픈 포지션의 이익 실현 수준

더블

POSITION_PRICE_CURRENT

기호 별 현재 가격

더블

POSITION_COMMISSION

커미션

더블

POSITION_SWAP

누적 스왑

더블

POSITION_PROFIT

현재 이익

더블

표 2. 열거형 값 ENUM_POSITION_PROPERTY_DOUBLE

식별자

기술

유형

POSITION_TIME

포지션 오프닝 시간

날짜 시간

POSITION_TYPE

직위 유형

ENUM_POSITION_TYPE

POSITION_MAGIC

포지션에 대한 매직 넘버 ( ORDER_MAGIC 참조)

long

POSITION_IDENTIFIER

직책 식별 - 재개된 각 직책에 할당되고 수명주기 동안 변경되지 않는 고유한 번호입니다. 포지션의 이직은 ID를 변경하지 않습니다.

long

표 3. 열거형 값 ENUM_POSITION_PROPERTY_INTEGER

식별자

기술

유형

POSITION_SYMBOL

위치가 열린 기호

POSITION_COMMENT

포지션에 대한 해설

표 4. 열거형 값 ENUM_POSITION_PROPERTY_STRING

함수를 통해 "누가 명령을 내 렸는지"라는 원칙에 따라 언어에 포지션 구분이 포함되어 있지 않음을 분명히 알 수 있지만 ORDER_MAGIC 이후 이러한 기록의 가능성이 있습니다. , POSITION_MAGICDEAL_MAGIC는 정확히 동일한 숫자이며 사용자가 지정한 매직 넘버에서 가져옵니다. POSITION_MAGIC은 포지션을 여는 DEAL_MAGIC에서 가져오고 DEAL_MAGIC은 주문한 주문의 ORDER_MAGIC에서 가져옵니다.

주문, 거래, 포지션 식별은 문제없이 가능하지만 특정 매직 넘버로 포지션을 이끌어내는 것은 불가능합니다. 이제 우리는 이 단점을 제거하려고 노력할 것입니다 . 내장 함수의 아날로그를 매직 넘버로 식별하여 만들어 보겠습니다. 매직 넘버에서 가상 포지션 작업을 위한 클래스를 선언하십시오.

OOP로 작업 할 수 있는 기회가 있으므로 우리 자신의 구조를 선언해 보겠습니다 (객관적으로 작성하는 추가 연습을 얻음).

//+------------------------------------------------------------------+
//| Structure of the CPositionVirtualMagic class                     |
//+------------------------------------------------------------------+
struct SPositionVirtualMagic
  {
   double            volume; // volume of virt. position
   ENUM_POSITION_TYPE type;  // type of virt. position
  };
//+--------------------------------------------------------------------------------+
//| The class calculates the virtual position of an Expert Advisor by magic number |
//+--------------------------------------------------------------------------------+
class CPositionVirtualMagic
  {
protected:
   SPositionVirtualMagic pvm;
public:
   double               cVOLUME(){return(pvm.volume);}
   // Returns the volume of virtual position of an Expert Advisor
   ENUM_POSITION_TYPE   cTYPE(){return(pvm.type);}
   // Returns the type of virtual position of an Expert Advisor
   bool              PositionVirtualMagic(ulong Magic,
                                          string symbol,
                                          datetime CurrentTime
                                          );
   // the method of calculation virt. position returns the presence or absence of virt. position
private:
   void              prHistory_Deals(ulong &buf[],int HTD);
   // Fills the array of tickets
  };
//+-------------------------------------------------------------------------------------+
//| Method of calculation of virt. position, returns true if there is a virt. position  |
//+-------------------------------------------------------------------------------------+
bool  CPositionVirtualMagic::PositionVirtualMagic(ulong Magic,
                                                  string symbol,
                                                  datetime CurrentTime
                                                  )
  {
   int DIGITS=(int)-log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP));
   if(DIGITS<0)DIGITS=0;
   ulong Dticket=0;
   int History_Total_Deals=-1;
   double volume=0,volume_BUY=0,volume_SELL=0;
   ulong DTicketbuf[];

   do
     {
      if(HistorySelect(0,TimeCurrent()))
        {
         History_Total_Deals=HistoryDealsTotal();
         prHistory_Deals(DTicketbuf,History_Total_Deals);
        }
      HistorySelect(0,TimeCurrent());
     }
   while(History_Total_Deals!=HistoryDealsTotal());

   for(int t=0;t<History_Total_Deals;t++)
     {
      Dticket=DTicketbuf[t];
      if(HistoryDealSelect(Dticket))
        {
         if(HistoryDealGetInteger(Dticket,DEAL_TIME)>=CurrentTime)
           {
            if(HistoryDealGetInteger(Dticket,DEAL_MAGIC)==Magic)
              {
               if(HistoryDealGetInteger(Dticket,DEAL_TYPE)==DEAL_TYPE_BUY)
                 {
                  volume_BUY+=HistoryDealGetDouble(Dticket,DEAL_VOLUME);
                 }
               else
                 {
                  if(HistoryDealGetInteger(Dticket,DEAL_TYPE)==DEAL_TYPE_SELL)
                    {
                     volume_SELL+=HistoryDealGetDouble(Dticket,DEAL_VOLUME);
                    }
                 }
              }
           }
        }
      else{HistorySelect(0,TimeCurrent());t--;}
      // if there is a fault, load history data and pass the step again
     }
   volume=NormalizeDouble(volume_BUY-volume_SELL,DIGITS);
   if(volume<0)pvm.type=POSITION_TYPE_SELL;
   else
     {
      if(volume>0)pvm.type=POSITION_TYPE_BUY;
     }
   pvm.volume=fabs(volume);
   if(pvm.volume==0)return(false);
   else return(true);
  }

위의 텍스트 (CProvision 클래스의 코드가 제공되는 곳)에서는 Expert Advisor의 개발이 이 글의 주제가 아니기 때문에 모든 것이 어디서 왔고 어디로 가는지 설명하지 않았습니다.

그러나 CPositionVirtualMagic 클래스에 대해 자세히 살펴 보겠습니다.

클래스에는 다음 구조가 제공됩니다.

struct SPositionVirtualMagic

pvm (구조의 변수) 덕분에 클래스 내 전역 선언과 같은 계산 결과를 수락하는 데 사용되는 이 구조는 클래스의 모든 메소드에서 모든 곳에서 사용할 수 있습니다.

다음으로 클래스의 두 가지 방법을 따르십시오.

double               cVOLUME(){return(pvm.volume);} // Returns the volume of the virtual position of the EA
ENUM_POSITION_TYPE   cTYPE()  {return(pvm.type);}   // Returns the type of the virtual position of the EA

이러한 메소드는 공용으로 선언되므로 호출된 클래스 변수를 통해 프로그램의 어느 포지션에서나 사용할 수 있으며 요청된 포지션의 구조 값을 출력하도록 설계되었습니다.

이것은 또한 다음 메소드가 선언되는 섹션입니다.

bool              PositionVirtualMagic(ulong Magic,string symbol,datetime CurrentTime);

이것이 클래스의 주요 함수가며 자세한 분석에 더 초점을 맞출 것이며 그 동안에는 개인 액세스 지정자 아래에서 함수를 설명하겠습니다.

void              prHistory_Deals(ulong &buf[],int HTD);

이 메소드는 기본적으로 순환이고 호출 된 함수에서 설명 할 수 있는 배열로 트랜잭션의 티켓 레코드를 생성하지만 PositionVirtualMagic() 함수의 크기를 줄이려고 했습니다 (코드의 가독성을 높이기 위해), 그래서 저는 이 주기를 함수의 한계를 넘어서서 개인 액세스 지정자를 사용하는 방법을 보여주었습니다.

그럼 PositionVirtualMagic() 으로 돌아가 보겠습니다. 이 함수는 처음에 정확도를 한 줄로 계산하므로 계산된 포지션 볼륨의 이중 값을 반올림해야 합니다.

int DIGITS=(int)-log10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP)); if(DIGITS<0)DIGITS=0;

이는 0으로 비교 연산을 수행하는 데 필요합니다. 그렇지 않으면 소수점 이하 8 번째 자리에 잔액이 있으면 값을 0으로 동일하게 만들지 못해 실행 오류가 발생합니다.

포지션 볼륨은 최소 단계로 반올림됩니다. 그리고 최소 단계가 1보다 크면 반올림이 적분 부분에 의해 수행됩니다. 다음은 while주기이지만 새로운 방식으로 사용됩니다 (mql4의 것과는 다름). 처음:

    do
     {
      if(HistorySelect(0,TimeCurrent()))
        {
         History_Total_Deals=HistoryDealsTotal();
         prHistory_Deals(DTicketbuf,History_Total_Deals);
        }
      HistorySelect(0,TimeCurrent());  
     }
   while(History_Total_Deals!=HistoryDealsTotal());

이러한 접근 방식은 진실성 표현이 주기 내에서 계산되기 때문에 사용되며 출시 시점에는 아직 이 검증을 준비하지 않았습니다.

주기에는 히스토리 업로드 가 포함되어 있습니다. 저는 히스토리 작업의 내장 함수와 함께 이것이 필수 조건 이라는 사실에 독자의 주의를 환기시키고 싶습니다. .

HistorySelect(0,TimeCurrent())

변수명 고르는 방식에 대해 설명해야 할 것 같아요.

세심한 독자는 클래스의 이름이 첫 글자 "C"로 정의된다는 사실을 알고 있어야 합니다. 이것은 구문에 필요하지 않으며 어떤 이름도 지정할 수 있지만 이러한 방식은 읽기를 훨씬 쉽게 만듭니다. 문자 "C"가 이름 앞에 나타나면 이것이 클래스의 이름이고 문자가 "S"이면 구조입니다. 변수가 내장 함수의 값을 취하면 함수 이름의 구성 요소를 변경하고 변수 이름을 가져옵니다. 예를 들면 다음과 같습니다:

CurrentTime = TimeCurrent();

간단하고 읽기 쉬우므로 변수에 포함된 내용을 즉시 확인할 수 있습니다. 특히 MetaEditor에는 특정 코드를 지정된 위치로 드래그하는 함수가 포함되어 있기 때문입니다.

코드를 자세히 살펴보면 히스토리를 업로드 한 후 함수 호출을 따릅니다.

History_Total_Deals=HistoryDealsTotal();

트랜잭션 수를 변수에 저장합니다. 같은 조건으로 사이클 종료 확인을 실시합니다. 이 확인이 필요한 이유는 무엇입니까? 왜 단순히 기록을 업로드 한 다음 여기에서 트랜잭션을 검색할 수 없습니까?

문제는 Expert Advisors의 작업 중에 내역이 각 EA에서 별도로 요청되므로 Expert Advisors가 다른 시간에 실행되면 내역의 깊이가 달라진다는 사실에 있습니다. 즉, 한 명의 Expert Advisor가 주기에 진입하여 해당 기간 동안의 이력을 업로드하면 주기가 끝나기 전에 다른 Expert Advisor의 요청에 의해 이미 업로드된 이력을 발견할 수 있습니다. 그렇게 함으로써 진정성에 대한 확인이 이뤄지는 것입니다.

덧붙여서, 이것이 최선의 검증 유형은 아니지만 작동합니다. 그래서 계속합시다. 주기에서 우리는 트랜잭션의 티켓 값을 특별히 준비된 버퍼에 입력하는 클래스 메소드를 호출합니다. prHistory_Deals () 함수를 호출 한 후 다시 히스토리 업로드를 생성합니다.

prHistory_Deals () 함수의 작업 과정에서 거래 이력에 변화가 있었는지 여부를 검증하는 방식입니다. 변경 사항이 없는 경우 History_Total_Deals의 변수는 HistoryDealsTotal ()과 같고 단일 패스에 대한 사이클 종료가 발생합니다. 변경 사항이있는 경우 시스템은 두 번째주기를 시작하고 오류없이 티켓 내역이 업로드 될 때까지 계속 반복합니다 (그리고 끝에 ";"을 입력하는 것을 잊지 마십시오).

while(History_Total_Deals!=HistoryDealsTotal());

또한 for , 주기에서 가상 포지션 계산이 수행됩니다.

트랜잭션이 일련의 필터 (트랜잭션 시간 및 트랜잭션 매직 넘버)를 성공적으로 통과한 경우 거래량은 트랜잭션이 속한 유형인 가상 포지션의 해당 부분을 증가시킵니다.

다른 옵션도 가능하지만 Expert Advisor가 출시된 이후에만 가상 포지션 계산을 기록합니다.

여기서 포지션이 정확히 어떻게 계산되는지 주목해야 합니다. 태고부터 지금까지 우리 모두가 사용하고있는 기록부에는 지출과 이익이 있고, 잔액 계산은 이 값의 차이로 유지되며, 포지션 계산에도 동일한 방식이 적용됩니다. 랏을 오픈하면 0.2는 매도, 0.3은 매수로, 즉 매수 포지션은 0.1입니다. 개장 시간과 레벨 차이는 수익의 범주이지만 보유할 포지션은 매수 유형인 0.1 랏입니다.

이것이 바로 매수 및 매도에서 Expert Advisors가 수행한 모든 거래를 간단히 요약한 다음 비교하고 일반적인 입장을 얻는 이유입니다 (실제로는 조사된 나머지 함수가 관여하는 것입니다).

포지션 볼륨 계산:

volume=NormalizeDouble(volume_BUY-volume_SELL,DIGITS);

구조의 값 출력으로 포지션 유형 인식:

   if(volume<0)pvm.type=POSITION_TYPE_SELL;
   else
     {
      if(volume>0)pvm.type=POSITION_TYPE_BUY;
     }

구조로 볼륨 출력:

pvm.volume=fabs(volume);

 함수 값의 출력: 포지션 볼륨이 0이면 거짓이고 그렇지 않으면 포지션이 존재하면 참입니다.

   if(pvm.volume==0)return(false);
   else return(true);

이제 가상 포지션의 함수를 사용하여 "이웃"과 충돌하지 않는 Expert Advisor의 코드를 쉽게 작성할 수 있습니다.

공간을 절약하기 위해 전체 코드 자체가 아닌 위에 배치되지 않은 코드의 특정 부분을 제공합니다.

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+

//--- input parameters
input ulong              magic       =1;           // magic
input int                SL          =300;         // Stop Loss
input int                TP          =1000;        // Take Profit
input int                MA_Period   =25;          // MA period
input double             lot         =0.1;         // Volume of position
input int                MA_shift    =0;          // Shift of indicator
input ENUM_MA_METHOD     MA_smooth   =MODE_SMA;     // Smoothing type
input ENUM_APPLIED_PRICE price       =PRICE_OPEN;    // Price type 
//--- we will store the indicator's handle
int MA_handle,type_MA,rezult;
double v[2];
datetime  CurrentTime;  // The variable stores the time of start of the Expert Advisor
MqlTradeResult    res;   // Pointer to the structure of responding by OrderSend
MqlTick          tick;  // Pointer to the structure of last market information
CPositionVirtualMagic cpvm;
CProvision prov;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   CurrentTime=TimeCurrent();// The variable stores the time of start of the Expert Advisor
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication

   if(cpvm.PositionVirtualMagic(magic,_Symbol,CurrentTime))// If there is ab open position 
     {
      if((int)cpvm.cTYPE()!=type_MA)// Check if it is time to close
        {
         Print("#",magic,"Position by magic number has volume ",cpvm.cVOLUME(),
               " reverse position of type ",(int)cpvm.cTYPE()," by ",type_MA);
         //cpvm.cVOLUME() - volume of virtual position
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,cpvm.cVOLUME()+lot);// reverse the poistion
         if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("#",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Poistion by magic number has volume ",cpvm.cVOLUME()," open position of type ",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);// Open position 
      if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  }

Expert Advisor를 단일 기기에서 세 번 실행하지만 시간 프레임이 다르며 매번 다른 매직 넘버를 할당합니다.

그림 3. 두 명의 동일한 Expert Advisor에게 서로 다른 매직 넘버를 할당해보겠습니다. (하나의 도구, 다른 기간) 첫 번째 Expert Advisor 출시

그림 3. 두 명의 동일한 Expert Advisor에게 서로 다른 매직 넘버를 할당해보겠습니다. (하나의 도구, 다른 기간) 첫 번째 Expert Advisor 출시

그림 4. 두 번째 Expert Advisor의 두 명의 동일한 Expert Advisor (하나의 도구, 다른 기간)에 다른 매직 넘버를 할당해보겠습니다.

그림 4. 두 번째 Expert Advisor의 두 명의 동일한 Expert Advisor (하나의 도구, 다른 기간)에 다른 매직 넘버를 할당해보겠습니다.

그림 5. 그 결과 다양한 매직 넘버를 사용하여 단일 기기에서 Expert Advisors의 충돌없는 작업이 가능합니다.

그림 5. 그 결과 다양한 매직 넘버를 사용하여 단일 기기에서 Expert Advisors의 충돌없는 작업이 가능합니다.

시운전은 성공적으로 통과되었고, Expert Advisors는 의무적으로 서로에게 양보했으며, 상충되는 사항은 없는 것 같습니다.

기술 사양의 첫 번째 요점이 구현되었지만 앞으로 더 많은 것이 있습니다.


매직 (Magic)의 코딩

다음 부분을 구현하려면 정보를 인코딩 / 디코딩하고 내장 함수에서 값을 검색하여 지정된 형식으로 변환하는 메소드 클래스를 개발해야 합니다.

이렇게 하려면 코딩 용어 (즉, 개발을 위한 기술 사양)를 반복합니다.

  • 메소드는 Expert Advisor의 이름을 인코딩해야 합니다 (디지털 이름이라고 합시다).
  • 본인 / 외국인 인식 코드 (상호 작용 코드라고 합시다)
  • Expert Advisor가 실행되는 심볼 코드 (EA가 작업중인 트랜잭션에서 확인할 수 있도록 하기 위해).

먼저 새 클래스의 이름을 선택하고, magic (일반 이름)으로 하고 열거형을 할당하여 코드를 시각적으로 이해하기 쉽게 만듭니다.

enum Emagic
  {
   ENUM_DIGITAL_NAME,    // digital name if the Expert Advisor
   ENUM_CODE_INTERACTION,// code of interaction
   ENUM_EXPERT_SYMBOL    // symbol, on which the EA is launched
  };

열거 형은 간단하게 작동합니다. 이름을 쉼표로 구분하여 설명하면 컴파일러가 시퀀스에 따라 번호를 할당합니다.

우선, 다른 유형의 변수를 할당하면 (숫자에는 적용되지 않음) 열거 형에서 매개 변수를 지정할 때 컴파일 중에 오류가 발생하고 두 번째로 명확성을 얻을 수 있습니다. 간단히 0 을 지정하고 ENUM_DIGITAL_NAME 을 지정하는 명령을 지정하십시오.

구조체나 클래스를 만들 때와 마찬가지로 열거형에 대한 간단한 이름을 선택했습니다. 일반적으로 선택한 이름에 E 를 추가하고 각각 Emagic 을 얻었습니다. 해당 구조는 Smagic , 클래스 입니다. Cmagic .

다시 말하지만, 이 문제는 필수 사항이 아니며 열거형 열거자, 구조 구조자 및 클래스 분류자를 호출할 수 있습니다. 그러나 이것은 이름에 공통성을 제공하지 않으며 이러한 유형의 코드를 읽는 것은 불편할 것입니다.

다음으로 코드를 저장하기 위한 구조를 만들어 보겠습니다.

struct Smagic
  {
   ulong             magicnumber;      // magic in an assembled form - how it is written in the order
   int               digital_name;     // digital name
   int               code_interaction; // code of interaction
   int               expert_symbol;    // symbol, on which the Expert Advisor is launched
  };

그런 다음 이전 Expert Advisor의 메소드를 포함하여 Magic 인코딩 및 디코딩의 모든 메소드를 등록하는 Cmagic 클래스를 선언합니다 (단순히 현재 클래스에서 선언하고 헤더를 다시 작성).

class Cmagic
  {
protected:
   Smagic            mag;
   SPositionVirtualMagic pvm;
public:
// the function returns the assembled magic, assembled from the incoming data
   ulong             SetMagic_request(int digital_name=0,int code_interaction=0);

// the function obtains the assembled magic and divides it according to the assembly logic
   ulong             SetMagic_result(ulong magicnumber);    

// the function obtains the return identification and returns the requested part of the assembled magic
   ulong             GetMagic_result(Emagic enum_); 

// the function obtains the return identification and returns the textual interpretation of the request part of the assembled magic
   string            sGetMagic_result(Emagic enum_);

// returns the voulme of the virtual position of the Expert Advisor
   double            cVOLUME(){return(pvm.volume);}
   
// returns the type of the virtual position of the Expert Advisor
   ENUM_POSITION_TYPE  cTYPE(){return(pvm.type);}
                                           
// method of calculating the virtual position, returns the presence of absence of the virtual position   
   bool              PositionVirtualMagic(Emagic enum_,
                                          string symbol,
                                          datetime CurrentTime);
private:
// function divides the magic into three parts  of three charges, and returns the part to which the category points to
   int               decodeMagic_result(int category); 

// interpretor of instrument symbols into the digital code                                                      
   int               symbolexpert();     
   
// interpretor of the digital code into the prescribed text (Expert Advisors)
   string            expertcode(int code);    
                                 
// interpretor of the digital code into the prescribed text (interaction)   
   string            codeinterdescript(int code);

// interpretor of the digital code into the instrument symbol                                         
   string            symbolexpert(int code);

// cycle of recording tickets into the buffer
   void              prHistory_Deals(ulong &buf[],int HTD);    
  };   

이제 우리는 방법을 개발할 것입니다.

클래스의 첫 번째 방법:

//+------------------------------------------------------------------+
//| Function returns the assembled magic, assembled from the input data    |
//+------------------------------------------------------------------+
ulong Cmagic::SetMagic_request(int digital_name=0,int code_interaction=0)
  {
   if(digital_name>=1000)Print("Incorrectly specified digital name of the Expert Advisor (more than 1000)");
   if(code_interaction>=1000)Print("Incorrectly specified the code of recognizing yours-foreign (more than 1000)");
   mag.digital_name     =digital_name;
   mag.code_interaction =code_interaction;
   mag.expert_symbol    =symbolexpert();
   mag.magicnumber      =mag.digital_name*(int)pow(1000,2)+
                         mag.code_interaction*(int)pow(1000,1)+
                         mag.expert_symbol;
   return(mag.magicnumber);
  }

이 방법은 Expert Advisor의 디지털 이름과 상호 작용 코드의 두 가지 값을받습니다.

ulong Cmagic::SetMagic_request(int digital_name=0,int code_interaction=0)

그리고 즉시 정확성을 확인합니다.

   if(digital_name>=1000)Print("Incorrectly specified the digital name of the Expert Advisor(more than 1000)");
   if(code_interaction>=1000)Print("Incorrectly specifies the code of recognizing yours-foreign (more than 1000)");

그러나 사용자의 행동에 대한 보복은 없으며 오류가 발생하더라도 순조롭게 계속 작동합니다.

다음으로 사용자가 지정하지만 기기 기호가 지정되지 않은 입력 데이터의 구조에 대한 할당이 제공되며 private 메소드에서 가져옵니다.

int Cmagic::symbolexpert()

코드는 매우 길고 첨부 파일에 나와있으므로 제공하지 않겠습니다. 이 방법은 기본적으로 "시장보기"창의 모든 기호에 해당 숫자를 할당하는 표일 뿐이라고 말하겠습니다. 예를 들어 EURUSD의 경우 1등 입니다.

"시장보기"창에 어떤 통화가 있는지 조사하기 위한 코드를 작성하여 이 데이터를 동적으로 얻을수 있지만 솔루션은 문제의 복잡성과 일치해야 하며 호출을 처리하는 것은 의미가 없습니다. 따라서 우리는 통화 목록을 구성하고 각각에 인덱스를 할당하는 간단한 방법으로 이를 수행 할 것입니다.

그리고 마지막으로 전체 방법 중 가장 중요한 부분은 다음과 같습니다.

mag.magicnumber      =mag.digital_name*(int)pow(1000,2)+
                      mag.code_interaction*(int)pow(1000,1)+
                      mag.expert_symbol;

전체 매직의 이질적인 부분으로 조립됩니다. 이것이 우리 Expert Advisor의 명령에 할당될 매직 (Magic)입니다.

클래스의 다음 공개 메소드:

//+------------------------------------------------------------------+
//| Function obtains the assembled magic                                   |
//| and divides it according to the logic of the assembly                  |
//+------------------------------------------------------------------+
ulong Cmagic::SetMagic_result(ulong magicnumber)
  {
   mag.magicnumber      =magicnumber;
   mag.expert_symbol    =decodeMagic_result(1);
   mag.code_interaction =decodeMagic_result(2);
   mag.digital_name     =decodeMagic_result(3);
   return(mag.magicnumber);
  }

실제로 이 메소드는 단일 private 메소드의 세 번 호출 결과를 구조를 통해 배포하는 셸 역할을 합니다. 이러한 지정자 아래의 선언은 클래스 변수를 호출할 때 팝업 프롬프트 메시지에 표시되지 않고 모든 작업이 공용 함수에 의해 수행되었다는 인상을 생성한다는 점에서 좋습니다.

그러나 개인 함수으로 돌아가 보겠습니다.

//+------------------------------------------------------------------+
//| Function divides the magic into three parts of three charges              |
//| and returns the part, which the category points to             |
//+------------------------------------------------------------------+
int Cmagic::decodeMagic_result(int category)
  {
   string string_value=(string)mag.magicnumber;
   int rem=(int)MathMod(StringLen(string_value),3);
   if(rem!=0)
     {
      rem=3-rem;
      string srem="0";
      if(rem==2)srem="00";
      string_value=srem+string_value;
     }
   int start_pos=StringLen(string_value)-3*category;
   string value=StringSubstr(string_value,start_pos,3);
   return((int)StringToInteger(value));
  }

시각적으로이 방법은 지정된 필드에서 3 자리 숫자를 읽는 것으로 나타낼 수 있습니다. 예를 들어 Magic 123456789 이 있는 경우 다음과 같이 나타낼 수 있습니다. | 123 | 456 | 789 | 지정된 필드가 1 이면 필드에 번호가 오른쪽에서 왼쪽으로 지정되어 있으므로 결과는 789 가 됩니다.

따라서 호출된 메소드에서 3 개의 필드를 모두 사용한 후 획득한 모든 데이터의 구조에 배포합니다. 이것은 매직을 작은 유형의 문자열 으로 가져 오는 절차를 통해 수행됩니다.

string string_value=(string)mag.magicnumber;

개별 라인 구성 요소를 정렬합니다.

다음은 본질적으로 스위치 를 전환하고 출력 값의 유형만 다른 두 가지 유사한 함수를 따릅니다.

//+------------------------------------------------------------------+
//| Function obtains the identifier of the return                          |
//| and returns the requested part of the assembled magic                   |
//+------------------------------------------------------------------+
ulong Cmagic::GetMagic_result(Emagic enum_)
  {
   switch(enum_)
     {
      case ENUM_DIGITAL_NAME     : return(mag.digital_name);     break;
      case ENUM_CODE_INTERACTION : return(mag.code_interaction); break;
      case ENUM_EXPERT_SYMBOL    : return(mag.expert_symbol);    break;
      default: return(mag.magicnumber); break;
     }
  }
//+------------------------------------------------------------------------------+
//| Function obtains the identifier of the return and returns                    |
//| a textual interpretation of the requested type of the assembled magic        |
//+------------------------------------------------------------------------------+
string Cmagic::sGetMagic_result(Emagic enum_)
  {
   switch(enum_)
     {
      case ENUM_DIGITAL_NAME     : return(expertcode(mag.digital_name));            break;
      case ENUM_CODE_INTERACTION : return(codeinterdescript(mag.code_interaction)); break;
      case ENUM_EXPERT_SYMBOL    : return(symbolexpert(mag.expert_symbol));         break;
      default: return((string)mag.magicnumber); break;
     }
  }

함수는 Emagic 유형의 매개 변수를 지정하는 Magic 부분을 반환합니다. 첫 번째는 계산에 사용되는 ulong 형식의 결과를 제공하고 두 번째는 다음의 결과를 제공합니다. 시각화에 사용할 수 있는 문자열 유형입니다.

GetMagic_result () 함수에서는 모든 것이 간단하게 구성되어 있으며 switch, 분기 전체에 구조 값을 배포하는 반면 sGetMagic_result () 은 조금 더 복잡합니다. 각 분기 케이스 는 구조의 값을 시각적 형식으로 전송하는 테이블 함수를 호출합니다. 따라서 값이 mag.expert_symbol = 1 이면 첫 번째 함수는 1 을, 두 번째 함수는 EURUSD 을 제공합니다.

정보를 인코딩 / 디코딩 할 때 테이블 함수의 장점을 이미 설명 했으므로 테이블리스 메소드 구현의 복잡성과 테이블을 작성하는데 필요한 시간에 대한 장점을 기반으로 각 경우를 개별적으로 고려해야 한다는 점만 언급하겠습니다. 상태 표를 작성하는 것이 더 쉬우면 문제를 복잡하게 만들 필요가 없습니다. 그러나 테이블을 작성하는데 많은 시간이 소요된다면 분명히 절차적 방법을 선호해야 합니다. 공간을 절약하기 위해 테이블을 제공하지 않습니다 (첨부 파일에서 찾을 수 있음).

기본적으로 이것은 우리 클래스가 개발되었지만 이전 Expert Advisor의 개발에 사용했던 나머지 함수는 여전히 ​​4 개입니다. 

특히 약간 수정이 필요하다는 점을 고려하여 새 클래스에서 간단히 다시 선언했습니다.

이제 주요 방법:

bool  Cmagic::PositionVirtualMagic(Emagic enum_,
                                   string symbol,
                                   datetime CurrentTime)

Cmagic 클래스의 메소드로 선언 될 뿐만 아니라 다른 매개 변수 집합도 있습니다.

매직 대신 포지션이 계산 된 매직 필드로 식별이 가능하게 되었습니다. 또한 마지막 옵션에 심볼이 존재하더라도 심볼별로 랏의 단계에 대한 정보를 얻기 위해서만 사용되었습니다. 그리고 이제는 필터에 규정되어 있으며 다른 사람과 동일하게 포지션 계수의 필터링에 참여할 수 있습니다.

이것은 우리에게 무엇을 제공합니까? 이제 우리는 다른 도구에서 열려 있지만 동일한 Expert Advisor에 의해 열린 트랜잭션을 동시에 필터링할 수 있습니다. 그렇게 함으로써 그들은 다른 기기에서 실행되는 다른 유사한 Expert Advisor와 혼동되지 않을 것입니다. 솔직히 말해서 이 새로운 계산 시스템을 사용하는 모든 다른 방법을 설명하는 것은 매우 어렵습니다. 그리고 독자는 그러한 복잡한 시스템이 필요한 것을 개인적으로 결정할 수 있습니다. 간단하게 작성할 수 있는 경우를 복잡하게 만들지 말고 분명한 필요성이 있을 때 그러한 합병증을 두려워하지 않는 것이 좋습니다.

클래스가 설계되었으므로 새로운 Expert Advisor에서 테스트 할 때입니다.

//+------------------------------------------------------------------+
//| Code of the Expert Advisor                                       |
//+------------------------------------------------------------------+
//--- input parameters
input ulong              digital_name_       =4;           // Digital name of Expert Advisor
input ulong              code_interaction_   =1;           // Code of interaction
input Emagic             _enum               =0;           // Model of magic number  
input int                SL                  =300;         // Stop Loss
input int                TP                  =1000;        // Take Profit
input int                MA_Period           =25;          // MA period
input double             lot                 =0.4;         // Volume of position
input int                MA_shift            =0;           // Shift of indicator
input ENUM_MA_METHOD     MA_smooth           =MODE_SMA;      // Smoothing type
input ENUM_APPLIED_PRICE price               =PRICE_OPEN;    // Price type 

//--- we will store the indicator's handle
int MA_handle,type_MA,rezult;
static ulong magic;
double v[2];
datetime  CurrentTime;// The variable stores the time of start of the Expert Advisor

MqlTradeResult  res;   // Pointer to the structure of responding by OrderSend
MqlTick         tick;  // Pointer to the structure of last market information
CProvision prov;
Cmagic mg;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   magic=mg.SetMagic_request(digital_name_,code_interaction_);
// Stamp of Expert Advisor (the magic number identifier) the magic variable is declared at the global scope
// used in int CProvision::SendOrder(ENUM_ORDER_TYPE type,double volume)
   CurrentTime=TimeCurrent();// The variable stores the time of start of the Expert Advisor
//--- Create the indicator's handle
   MA_handle=iMA(Symbol(),0,MA_Period,MA_shift,MA_smooth,price);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(CopyBuffer(MA_handle,0,0,2,v)<=0)
     {Print("#",magic,"Error of copying");return;}
   type_MA=prov.TYPE(v); // Determine type depending on MA indication
   mg.SetMagic_result(magic);// put the information into the structure
   if(mg.PositionVirtualMagic(_enum,_Symbol,CurrentTime))// If three is an open position 
     {
      if((int)mg.cTYPE()!=type_MA)// Check if it is time to close
        {
         mg.SetMagic_result(magic);// put the information into the structure
         Print("#",mg.GetMagic_result(_enum),"Position by magic number has volume ",mg.cVOLUME(),
               " reverse position of type ",(int)mg.cTYPE()," by ",type_MA);
         //cpvm.cVOLUME() - volume of virtual position
         rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,mg.cVOLUME()+lot);// reverse position
         if(rezult!=-1)Print("№",magic," Code of the operation result ",rezult," volume ",res.volume);
         else{Print("№",magic,"Error",GetLastError()); return;}
        }
     }
   else // If there is no open position then open
     {
      Print("#",magic,"Position by magic number has volume  ",mg.cVOLUME()," open position of type",type_MA);
      rezult=prov.SendOrder((ENUM_ORDER_TYPE)type_MA,lot);// Open position 
      if(rezult!=-1)Print("#",magic," Code of the operation result ",rezult," volume ",res.volume);
      else{Print("#",magic,"Error",GetLastError()); return;}
     }
  }

앞서 언급했듯이 이 Expert Advisor는 매우 간단하며 다양한 함수를 시연하기 위해 만들어졌으며 단일 기기에서 세 번 실행합니다.

그림 6. 서로 다른 그래프에 서로 다른 매직 (Magic)을 가진 세 명의 Expert Advisor 설치

그림 6. 서로 다른 그래프에 서로 다른 매직 (Magic)을 가진 세 명의 Expert Advisor 설치

그림 7. 그 결과 서로 다른 매직 (Magic)을 가진 세 명의 Expert Advisors가 분쟁없이 거래됩니다.

그림 7. 그 결과 서로 다른 매직 (Magic)을 가진 세 명의 Expert Advisors가 분쟁없이 거래됩니다.

Expert Advisors의 메시지 출력물에서 볼 수 있듯이 세 참가자 모두 성공적으로 시작되었으며 충돌이 없음을 보여주었습니다.


결론

MQL5의 제작자는 거래 작업에 매직 (Magic)의 주문을 할당 할 수 있는 기회를 제공함으로써 Expert Advisor 작가의 삶을 크게 향상 시켰습니다. 그러나 개발자는 도구 만 제공할 수 있습니다. 실제로 다이아몬드를 얻을 수 있는 사람이어야 합니다.

다시 만날 때까지 행운을 빕니다.


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

파일 첨부됨 |
magic_exp0_en.mq5 (8.34 KB)
magic_exp1_en.mq5 (11.84 KB)
magic_exp2_en.mq5 (25.39 KB)
Google Chart API를 통해 차트를 구성하는 라이브러리 Google Chart API를 통해 차트를 구성하는 라이브러리
다양한 유형의 다이어그램 구성은 시장 상황 분석 및 거래 시스템 테스트의 필수 부분입니다. 종종 멋진 다이어그램을 구성하려면 데이터 출력을 파일로 구성해야 하며 그 후에 MS Excel과 같은 응용 프로그램에서 사용됩니다. 이건 그닥 편리하지 않고 데이터를 동적으로 업데이트하는 함수를 뺏어가기까지 합니다. Google Charts API는 서버에 특별한 요청을 보내 온라인 모드에서 차트를 만드는 수단을 제공했습니다. 이 글에서는 이러한 요청을 작성하고 Google 서버에서 차트를 가져 오는 프로세스를 자동화하려고 합니다.
인디케이터의 경제적 계산 원칙 인디케이터의 경제적 계산 원칙
사용자 및 기술 인디케이터에 대한 호출은 자동 거래 시스템의 프로그램 코드에서 매우 적은 공간을 차지합니다. 종종 단순히 몇 줄의 코드 일뿐입니다. 그러나 가장 많은 시간을 사용하는 몇 줄의 코드로 Expert Advisor를 테스트하는 데 소비해야 하는 경우가 종종 있습니다. 따라서 인디케이터 내 데이터 계산과 관련된 모든 것은 언뜻 보기 보다 훨씬 더 철저히 고려되어야 합니다. 이 글은 이것에 대해 정확하게 이야기 할 것입니다.
Named Pipes를 사용하여 MetaTrader 5 터미널 간 통신을 위한 DLL없는 솔루션 Named Pipes를 사용하여 MetaTrader 5 터미널 간 통신을 위한 DLL없는 솔루션
이 글에서는 명명된 파이프를 사용하여 MetaTrader 5 클라이언트 터미널 간의 프로세스 간 통신을 구현하는 방법을 설명합니다. 명명된 파이프를 사용하기 위해 CNamedPipes 클래스가 개발되었습니다. 사용을 테스트하고 연결 처리량을 측정하기 위해 눈금 인디케이터, 서버 및 클라이언트 스크립트가 제공됩니다. 실시간 따옴표에는 명명된 파이프를 사용하면 충분합니다.
예시를 통해 보는 MQL5 의 OOP: 프로세싱 경고와 에러 코드 예시를 통해 보는 MQL5 의 OOP: 프로세싱 경고와 에러 코드
이 문서에서는 매매 서버 리턴 코드 작업을 위한 클래스를 생성하는 예와 MQL 프로그램 실행 중에 발생하는 모든 오류에 대해 설명합니다. 이 문서를 다 읽고나면 당신은 MQL5로 클래스나 객체를 어떻게 다뤄야하는지 알게될 것입니다. 또한 이 도구는 오류를 처리하는 데 편리한 도구이며 특정 필요에 따라 이 도구를 추가로 변경할 수 있습니다.