English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
MQL5 Cookbook: ОСО 주문

MQL5 Cookbook: ОСО 주문

MetaTrader 5 | 12 10월 2021, 17:31
242 0
Denis Kirichenko
Denis Kirichenko

소개

이 글은 OCO와 같은 유형의 주문 쌍을 다루는 데 중점을 둡니다. 이 메커니즘은 MetaTrader 5와 경쟁하는 일부 거래 터미널에서 구현됩니다. 저는 OCO 주문 처리를 위한 패널이 있는 EA 생성의 예를 통해 두 가지 목표를 추구합니다. 한편으로는 표준 라이브러리의 기능을 설명하고 다른 한편으로는 트레이더의 도구 세트를 확장하고 싶습니다.


1. OCO 명령의 본질

OCO 주문(one-cancel-the-other order)은 두 개의 보류 중인 주문 쌍을 나타냅니다.

그들은 상호 취소 기능에 의해 연결됩니다. 첫 번째 트리거가 트리거되면 두 번째 트리거가 제거되어야 하며 그 반대의 경우도 마찬가지입니다.

그림 1 OCO 주문 쌍

그림 1 OCO 주문 쌍

그림 1은 간단한 차수 상호 의존 방식을 보여줍니다. 그것은 본질적인 정의를 반영합니다. 두 주문이 모두 존재하는 한 쌍은 존재합니다. 논리의 관점에서 쌍의 [일] 순서는 쌍이 존재하기 위한 필수 조건이지만 충분 조건은 아닙니다.

일부 소식통은 쌍에 하나의 지정가 주문과 하나의 중지 주문이 있어야 하며 주문에는 하나의 방향(구매 또는 판매)이 있어야 한다고 말합니다. 내 생각에 그러한 제한은 유연한 거래 전략을 만드는 데 도움이 되지 않습니다. 저는 다양한 OCO 주문이 쌍에서 분석되어야 하며 가장 중요한 것은 이 쌍을 프로그래밍하려고 시도할 것을 제안합니다.


2. 프로그래밍 순서 쌍

내 생각에 ООP 도구 세트는 OCO 주문에 대한 제어와 연결된 프로그래밍 작업에 가장 적합합니다.

다음 섹션에서는 우리의 목적에 부합하는 새로운 데이터 유형에 대해 설명합니다. CiOcoObject 클래스가 우선입니다.


2.1. CiOcoObject 클래스

따라서 우리는 두 개의 상호 연결된 주문을 제어하는 ​​소프트웨어 개체를 만들어야 합니다.

전통적으로 CObject 추상 클래스를 기반으로 새 개체를 생성해 보겠습니다.

이 새 클래스는 다음과 같이 보일 수 있습니다.

//+------------------------------------------------------------------+
//| Class CiOcoObject                                                |
//| Purpose: a class for OCO orders                                  |            
//+------------------------------------------------------------------+
class CiOcoObject : public CObject
  {
   //--- === Data members === --- 
private:
   //--- tickets of pair
   ulong             m_order_tickets[2];
   //--- initialization flag
   bool              m_is_init;
   //--- id
   uint              m_id;

   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CiOcoObject(void){m_is_init=false;};
   void             ~CiOcoObject(void){};
   //--- copy constructor
   void              CiOcoObject(const CiOcoObject &_src_oco);
   //--- assignment operator
   void              operator=(const CiOcoObject &_src_oco);

   //--- initialization/deinitialization
   bool              Init(const SOrderProperties &_orders[],const uint _bunch_cnt=1);
   bool              Deinit(void);
   //--- get id
   uint              Id(void) const {return m_id;};

private:
   //--- types of orders
   ENUM_ORDER_TYPE   BaseOrderType(const ENUM_ORDER_TYPE _ord_type);
   ENUM_BASE_PENDING_TYPE PendingType(const ENUM_PENDING_ORDER_TYPE _pend_type);
   //--- set id
   void              Id(const uint _id){m_id=_id;};
  };
-->

각 OCO 주문 쌍에는 고유한 식별자가 있습니다. 그 값은 난수 생성기를 통해 설정됩니다(CRandom 클래스의 개체).

쌍 초기화 및 초기화 해제 방법은 인터페이스 컨텍스트에서 중요합니다. 첫 번째는 쌍을 생성(초기화)하고 두 번째는 쌍을 제거(초기화 해제)합니다.

CiOcoObject::Init() 메소드는 SOrderProperties 유형의 구조 배열을 인수로 받아들입니다. 이 유형의 구조는 쌍의 주문 속성, 즉 OCO 주문을 나타냅니다.


2.2 SOrderProperties 구조

앞서 언급한 구조의 필드를 살펴보자.

//+------------------------------------------------------------------+
//| Order properties structure                                       |
//+------------------------------------------------------------------+
struct SOrderProperties
  {
   double                  volume;           // order volume   
   string                  symbol;           // symbol
   ENUM_PENDING_ORDER_TYPE order_type;       // order type   
   uint                    price_offset;     // offset for execution price, points
   uint                    limit_offset;     // offset for limit price, points
   uint                    sl;               // stop loss, points
   uint                    tp;               // take profit, points
   ENUM_ORDER_TYPE_TIME    type_time;        // expiration type
   datetime                expiration;       // expiration
   string                  comment;          // comment
  }
-->

따라서 초기화 방법이 작동하도록 하려면 이전에 두 개의 요소로 구성된 구조 배열을 채워야 합니다. 간단히 말해서, 우리는 그것이 배치될 주문 프로그램을 설명해야 합니다.

ENUM_PENDING_ORDER_TYPE 유형의 열거가 구조에서 사용됩니다.

//+------------------------------------------------------------------+
//| Pending order type                                               |
//+------------------------------------------------------------------+
enum ENUM_PENDING_ORDER_TYPE
  {
   PENDING_ORDER_TYPE_BUY_LIMIT=2,       // Buy Limit
   PENDING_ORDER_TYPE_SELL_LIMIT=3,      // Sell Limit
   PENDING_ORDER_TYPE_BUY_STOP=4,        // Buy Stop
   PENDING_ORDER_TYPE_SELL_STOP=5,       // Sell Stop
   PENDING_ORDER_TYPE_BUY_STOP_LIMIT=6,  // Buy Stop Limit
   PENDING_ORDER_TYPE_SELL_STOP_LIMIT=7, // Sell Stop Limit
  };
-->

일반적으로 말해서 ENUM _ORDER_TYPE 표준 열거와 같지만 보류 중인 주문만 선택할 수 있습니다.

입력 매개변수에서 해당 주문 유형을 선택할 때 오류로부터 보호합니다(그림 2).

그림 2. 사용 가능한 주문 유형의 드롭다운 목록이 있는 "유형" 필드

그림 2. 사용 가능한 주문 유형의 드롭다운 목록이 있는 "유형" 필드

그러나 ENUM _ORDER_TYPE 표준 열거를 사용하는 경우 시장 주문 유형(ORDER_TYPE_BUY 또는 ORDER_TYPE_SELL)을 설정할 수 있으며 이는 보류 중인 주문만 처리하므로 필요하지 않습니다.


2.3. 초기화

위에서 언급했듯이 CiOcoObject::Init() 메소드는 주문 쌍 초기화에 관여합니다.

실제로 그것은 주문 쌍 자체를 배치하고 새로운 쌍 출현의 성공 또는 실패를 기록합니다. 자체적으로 거래 작업을 수행하기 때문에 이것은 활성 방법이라고 말하고 싶습니다. 우리는 또한 수동적인 방법을 만들 수도 있습니다. 그것은 단순히 독립적으로 배치된 이미 활성화된 보류 중인 주문 쌍에 연결됩니다.

저는 전체 방법의 코드를 제공하지 않을 것입니다. 그러나 모든 가격(시가, 중지, 이익, 한도)을 계산하는 것이 중요하므로 CTrade::OrderOpen() 거래 클래스 메소드가 거래 주문을 수행할 수 있도록 하는 것이 중요합니다. 이를 위해 주문 방향(구매 또는 판매)과 현재 가격에 대한 주문 실행 가격의 포지션(이상 또는 이하)의 두 가지를 고려해야 합니다.

이 메소드는 BaseOrderType()PendingType()과 같은 몇 가지 비공개 메소드를 호출합니다. 첫 번째 항목은 주문 방향을 정의하고 두 번째 항목은 보류 중인 주문 유형을 결정합니다.

주문이 접수되면 티켓이 m_order_tickets[] 배열에 기록됩니다.

이 방법을 테스트하기 위해 간단한 Init_OCO.mq5 스크립트를 사용했습니다.

#property script_show_inputs
//---
#include "CiOcoObject.mqh"
//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
sinput string Info_order1="+===--Order 1--====+";   // +===--Order 1--====+
input ENUM_PENDING_ORDER_TYPE InpOrder1Type=PENDING_ORDER_TYPE_SELL_LIMIT; // Type
input double InpOrder1Volume=0.02;                  // Volume
input uint InpOrder1PriceOffset=125;                // Offset for execution price, points
input uint InpOrder1LimitOffset=50;                 // Offset for limit price, points
input uint InpOrder1SL=250;                         // Stop loss, points
input uint InpOrder1TP=455;                         // Profit, points
input string InpOrder1Comment="OCO Order 1";        // Comment
//---
sinput string Info_order2="+===--Order 2--====+";   // +===--Order 2--====+
input ENUM_PENDING_ORDER_TYPE InpOrder2Type=PENDING_ORDER_TYPE_SELL_STOP; // Type
input double InpOrder2Volume=0.04;                  // Volume    
input uint InpOrder2PriceOffset=125;                // Offset for execution price, points
input uint InpOrder2LimitOffset=50;                 // Offset for limit price, points
input uint InpOrder2SL=275;                         // Stop loss, points
input uint InpOrder2TP=300;                         // Profit, points
input string InpOrder2Comment="OCO Order 2";        // Comment

//--- globals
CiOcoObject myOco;
SOrderProperties gOrdersProps[2];
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- property of the 1st order
   gOrdersProps[0].order_type=InpOrder1Type;
   gOrdersProps[0].volume=InpOrder1Volume;
   gOrdersProps[0].price_offset=InpOrder1PriceOffset;
   gOrdersProps[0].limit_offset=InpOrder1LimitOffset;
   gOrdersProps[0].sl=InpOrder1SL;
   gOrdersProps[0].tp=InpOrder1TP;
   gOrdersProps[0].comment=InpOrder1Comment;

//--- property of the 2nd order
   gOrdersProps[1].order_type=InpOrder2Type;
   gOrdersProps[1].volume=InpOrder2Volume;
   gOrdersProps[1].price_offset=InpOrder2PriceOffset;
   gOrdersProps[1].limit_offset=InpOrder2LimitOffset;
   gOrdersProps[1].sl=InpOrder2SL;
   gOrdersProps[1].tp=InpOrder2TP;
   gOrdersProps[1].comment=InpOrder2Comment;

//--- initialization of pair
   if(myOco.Init(gOrdersProps))
      PrintFormat("Id of new OCO pair: %I32u",myOco.Id());
   else
      Print("Error when placing OCO pair!");
  }
-->

여기에서 쌍의 미래 주문에 대한 다양한 속성을 설정할 수 있습니다. MetaTrader 5에는 6가지 유형의 보류 주문이 있습니다.

이 컨텍스트에서 쌍의 변형(조합)이 있을 수 있습니다(쌍에 다른 순서가 있는 경우).

C(k,N) = C(2,6) = 15

모든 변형은 스크립트의 도움으로 테스트되었습니다. Buy Stop - Buy Stop Limit 쌍의 예를 보겠습니다.

주문 유형은 스크립트 매개변수에 지정해야 합니다(그림 3).


그림 3. "Buy Stop" 주문과 "Buy Stop Limit" 주문 쌍

그림 3. "Buy Stop" 주문과 "Buy Stop Limit" 주문 쌍

"전문가" 등록부에 다음 정보가 표시됩니다.

QO      0       17:17:41.020    Init_OCO (GBPUSD.e,M15) Code of request result: 10009
JD      0       17:17:41.036    Init_OCO (GBPUSD.e,M15) New order ticket: 24190813
QL      0       17:17:41.286    Init_OCO (GBPUSD.e,M15) Code of request result: 10009
JH      0       17:17:41.286    Init_OCO (GBPUSD.e,M15) New order ticket: 24190814
MM      0       17:17:41.379    Init_OCO (GBPUSD.e,M15) Id of new OCO pair: 3782950319
-->

그러나 우리는 루핑에 의존하지 않고 스크립트의 도움으로 OCO 명령으로 최대한 작업할 수 없습니다.


2.4. 쌍의 초기화 해제

이 방법은 주문 쌍에 대한 제어를 담당합니다. 주문이 활성 주문 목록을 벗어나면 쌍이 "죽습니다".

이 메소드는 EA 코드의 OnTrade() 또는 OnTradeTransaction() 핸들러에 배치되어야 한다고 가정합니다. 이러한 방식으로 EA는 지연 없이 모든 페어 주문의 활성화를 처리할 수 있습니다.

//+------------------------------------------------------------------+
//| Deinitialization of pair                                         |
//+------------------------------------------------------------------+
bool CiOcoObject::Deinit(void)
  {
//--- if pair is initialized
   if(this.m_is_init)
     {
      //--- check your orders 
      for(int ord_idx=0;ord_idx<ArraySize(this.m_order_tickets);ord_idx++)
        {
         //--- current pair order
         ulong curr_ord_ticket=this.m_order_tickets[ord_idx];
         //--- another pair order
         int other_ord_idx=!ord_idx;
         ulong other_ord_ticket=this.m_order_tickets[other_ord_idx];

         //---
         COrderInfo order_obj;

         //--- if there is no current order
         if(!order_obj.Select(curr_ord_ticket))
           {
            PrintFormat("Order #%d is not found in active orders list.",curr_ord_ticket);
            //--- attempt to delete another order                 
            if(order_obj.Select(other_ord_ticket))
              {
               CTrade trade_obj;
               //---
               if(trade_obj.OrderDelete(other_ord_ticket))
                  return true;
              }
           }
        }
     }
//---
   return false;
  }
-->

한 가지 세부 사항을 언급하고 싶습니다. 페어 초기화 플래그는 클래스 메소드의 본문에서 확인됩니다. 플래그가 지워진 경우 주문 확인 시도가 이루어지지 않습니다. 이 접근 방식은 다른 하나가 아직 배치되지 않은 경우 하나의 활성 주문을 삭제하는 것을 방지합니다.

몇 가지 주문이 이루어진 스크립트에 기능을 추가해 보겠습니다. 이를 위해 Control_OCO_EA.mq5 테스트 EA를 생성합니다.

일반적으로 EA는 코드의 Trade() 이벤트 처리 블록만 스크립트와 다릅니다.

//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
//--- OCO pair deinitialization
   if(myOco.Deinit())
     {
      Print("No more order pair!");
      //--- clear  pair
      CiOcoObject new_oco;
      myOco=new_oco;
     }
  }

-->

비디오는 MetaTrader 5 터미널에서 두 프로그램의 작업을 보여줍니다.



그러나 두 테스트 프로그램 모두 약점이 있습니다.

첫 번째 프로그램(스크립트)은 쌍을 능동적으로 생성할 수만 있지만 그런 다음에는 제어를 잃습니다.

두 번째 프로그램(Expert Advisor)은 쌍을 제어하지만 첫 번째 쌍을 생성한 후에는 다른 쌍을 반복적으로 생성할 수 없습니다. OCO 주문 프로그램(스크립트)을 완전한 기능으로 만들려면 주문 기회가 있는 도구 집합을 확장해야 합니다. 다음 섹션에서 그렇게 할 것입니다.


3. EA 제어

페어 주문의 매개변수를 배치하고 설정하기 위해 차트에 OCO 주문 관리 패널을 생성해 보겠습니다.

제어 EA의 일부가 됩니다(그림 4). 소스 코드는 Panel_OCO_EA.mq5에 있습니다.

그림 4. OCO 주문 생성 패널: 초기 상태

그림 4. OCO 주문 생성 패널: 초기 상태


미래 주문 유형을 선택하고 필드를 작성하여 한 쌍의 OCO 주문을 해야 합니다.

그러면 패널에 있는 유일한 버튼의 레이블이 변경됩니다(텍스트 속성, 그림 5).

그림 5. OCO 주문 생성 패널: 새 쌍

그림 5. OCO 주문 생성 패널: 새 쌍


표준 라이브러리의 다음 클래스는 패널을 구성하는 데 사용되었습니다.

  • CAppDialog는 기본 응용 프로그램 대화 상자입니다.
  • CPanel은 직사각형 레이블입니다.
  • CLabel은 텍스트 레이블입니다.
  • CComboBox는 드롭다운 목록이 있는 필드입니다.
  • CEdit는 입력 필드입니다.
  • CButton은 버튼입니다.

물론 부모 클래스 메소드는 자동으로 호출됩니다.

이제 코드로 넘어갑니다. 표준 라이브러리에서 표시 패널 및 대화 상자 생성 전용으로 사용되는 부분이 상당히 큽니다.

예를 들어, 드롭다운 목록 닫기 이벤트를 포착하려면 호출 스택을 자세히 조사해야 합니다(그림 6).

그림 6. 호출 스택

그림 6. 호출 스택


개발자는 특정 이벤트에 대해 %MQL5\Include\Controls\Defines.mqh 파일에 매크로와 표기법을 설정합니다.

OCO 쌍을 만들기 위해 ON_OCO 맞춤 이벤트를 만들었습니다.

#define ON_OCO (101) // OCO pair creation event 

-->

미래 주문의 매개변수가 채워지고 OnChartEvent() 핸들러 본문에서 쌍이 생성됩니다. 

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- handling all chart events by main dialog
   myDialog.ChartEvent(id,lparam,dparam,sparam);

//--- drop-down list handling
   if(id==CHARTEVENT_CUSTOM+ON_CHANGE)
     {
      //--- if it is Panel list
      if(!StringCompare(StringSubstr(sparam,0,7),"myCombo"))
        {
         static ENUM_PENDING_ORDER_TYPE prev_vals[2];
         //--- list index
         int combo_idx=(int)StringToInteger(StringSubstr(sparam,7,1))-1;

         ENUM_PENDING_ORDER_TYPE curr_val=(ENUM_PENDING_ORDER_TYPE)(myCombos[combo_idx].Value()+2);
         //--- remember order type change
         if(prev_vals[combo_idx]!=curr_val)
           {
            prev_vals[combo_idx]=curr_val;
            gOrdersProps[combo_idx].order_type=curr_val;
           }
        }
     }

//--- handling input fields
   else if(id==CHARTEVENT_OBJECT_ENDEDIT)
     {
      //--- if it is Panel's input field
      if(!StringCompare(StringSubstr(sparam,0,6),"myEdit"))
        {
         //--- find object
         for(int idx=0;idx<ArraySize(myEdits);idx++)
           {
            string curr_edit_obj_name=myEdits[idx].Name();
            long curr_edit_obj_id=myEdits[idx].Id();
            //--- if names coincide
            if(!StringCompare(sparam,curr_edit_obj_name))
              {
               //--- get current value of field
               double value=StringToDouble(myEdits[idx].Text());
               //--- define gOrdersProps[] array index
               int order_num=(idx<gEditsHalfLen)?0:1;
               //--- define gOrdersProps structure field number
               int jdx=idx;
               if(order_num)
                  jdx=idx-gEditsHalfLen;
               //--- fill up gOrdersProps structure field
               switch(jdx)
                 {
                  case 0: // volume
                    {
                     gOrdersProps[order_num].volume=value;
                     break;
                    }
                  case 1: // execution
                    {
                     gOrdersProps[order_num].price_offset=(uint)value;
                     break;
                    }
                  case 2: // limit
                    {
                     gOrdersProps[order_num].limit_offset=(uint)value;
                     break;
                    }
                  case 3: // stop
                    {
                     gOrdersProps[order_num].sl=(uint)value;
                     break;
                    }
                  case 4: // profit
                    {
                     gOrdersProps[order_num].tp=(uint)value;
                     break;
                    }
                 }
              }
           }
         //--- OCO pair creation flag
         bool is_to_fire_oco=true;
         //--- check structure filling 
         for(int idx=0;idx<ArraySize(gOrdersProps);idx++)
           {
            //---  if order type is set 
            if(gOrdersProps[idx].order_type!=WRONG_VALUE)
               //---  if volume is set  
               if(gOrdersProps[idx].volume!=WRONG_VALUE)
                  //---  if offset for execution price is set
                  if(gOrdersProps[idx].price_offset!=(uint)WRONG_VALUE)
                     //---  if offset for limit price is set
                     if(gOrdersProps[idx].limit_offset!=(uint)WRONG_VALUE)
                        //---  if stop loss is set
                        if(gOrdersProps[idx].sl!=(uint)WRONG_VALUE)
                           //---  if take profit is set
                           if(gOrdersProps[idx].tp!=(uint)WRONG_VALUE)
                              continue;

            //--- clear OCO pair creation flag 
            is_to_fire_oco=false;
            break;
           }
         //--- create OCO pair?
         if(is_to_fire_oco)
           {
            //--- complete comment fields
            for(int ord_idx=0;ord_idx<ArraySize(gOrdersProps);ord_idx++)
               gOrdersProps[ord_idx].comment=StringFormat("OCO Order %d",ord_idx+1);
            //--- change button properties
            myButton.Text("New pair");
            myButton.Color(clrDarkBlue);
            myButton.ColorBackground(clrLightBlue);
            //--- respond to user actions 
            myButton.Enable();
           }
        }
     }
//--- handling click on button
   else if(id==CHARTEVENT_OBJECT_CLICK)
     {
      //--- if it is OCO pair creation button
      if(!StringCompare(StringSubstr(sparam,0,6),"myFire"))
         //--- if to respond to user actions
         if(myButton.IsEnabled())
           {
            //--- generate OCO pair creation event
            EventChartCustom(0,ON_OCO,0,0.0,"OCO_fire");
            Print("Command to create new bunch has been received.");
           }
     }
//--- handling new pair initialization command 
   else if(id==CHARTEVENT_CUSTOM+ON_OCO)
     {
      //--- OCO pair initialization
      if(gOco.Init(gOrdersProps,gOcoList.Total()+1))
        {
         PrintFormat("Id of new OCO pair: %I32u",gOco.Id());
         //--- copy pair
         CiOcoObject *ptr_new_oco=new CiOcoObject(gOco);
         if(CheckPointer(ptr_new_oco)==POINTER_DYNAMIC)
           {
            //--- add to list
            int node_idx=gOcoList.Add(ptr_new_oco);
            if(node_idx>-1)
               PrintFormat("Total number of bunch: %d",gOcoList.Total());
            else
               PrintFormat("Error when adding OCO pair %I32u to list!",gOco.Id());
           }
        }
      else
         Print("OCO-orders placing error!");

      //--- clear properties
      Reset();
     }
  }
-->

핸들러 코드는 작지 않습니다. 여러 블록에 중점을 두고 싶습니다.

모든 차트 이벤트의 첫 번째 처리는 기본 대화 상자에 제공됩니다.

다음은 다양한 이벤트 처리 블록입니다.

  • 주문 유형을 정의하기 위한 드롭다운 목록 변경;
  • 주문 속성을 채우기 위한 입력 필드 편집;
  • ON_OCO 이벤트 생성 버튼을 클릭하십시오.
  • ON_OCO 이벤트 응답: 주문 쌍 생성.

EA는 패널 필드 작성의 정확성을 확인하지 않습니다. 이것이 우리가 스스로 값을 확인해야 하는 이유입니다. 그렇지 않으면 EA에 OCO 주문 오류가 표시됩니다.

OnTrade() 핸들러 본문에서 쌍을 제거하고 나머지 주문을 닫을 필요가 있는지 확인합니다.


결론

일부 특정 작업을 수행하는 데 사용할 수 있는 표준 라이브러리 클래스의 풍부함을 보여주려고 했습니다.

특히, 우리는 OCO 주문 처리 문제를 다루고 있었습니다. OCO 주문 처리를 위한 패널이 있는 EA의 코드가 더 복잡한 주문 쌍 생성을 위한 출발점이 되기를 바랍니다.


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

파일 첨부됨 |
ciocoobject.mqh (27.71 KB)
crandom.mqh (5.19 KB)
init_oco.mq5 (6.42 KB)
control_oco_ea.mq5 (7.88 KB)
panel_oco_ea.mq5 (30.25 KB)
MetaTrader 5에서 RSS 피드를 표시하는 대화형 애플리케이션 구축 MetaTrader 5에서 RSS 피드를 표시하는 대화형 애플리케이션 구축
이 글에서는 RSS 피드 표시를 위한 응용 프로그램을 만드는 가능성을 살펴봅니다. 이 글에서는 MetaTrader 5용 대화형 프로그램을 만드는 데 표준 라이브러리의 여러 측면을 사용할 수 있는 방법을 보여줍니다.
기술적 분석 및 시장 예측 방법에 관하여 기술적 분석 및 시장 예측 방법에 관하여
이 글은 시각적 사고 및 "즉시 사용 가능한" 시장 전망과 결합된 잘 알려진 수학적 방법의 기능과 잠재력을 보여줍니다. 한편으로는 트레이딩 패러다임 자체를 재고할 수 있는 창의적인 마인드를 가질 수 있어 폭넓은 청중의 이목을 집중시키는 역할을 합니다. 그리고 다른 한편으로는 분석 및 예측을 위한 광범위한 도구와 관련된 대안 개발 및 프로그램 코드 구현을 야기할 수 있습니다.
가격 방향과 이동 속도에 따른 거래 아이디어 가격 방향과 이동 속도에 따른 거래 아이디어
이 글은 가격의 움직임 방향과 속도에 대한 분석을 기반으로 아이디어에 대한 검토를 제공합니다. 우리는 고려 중인 전략의 실행 가능성을 탐색하기 위해 Expert Advisor으로 제시된 MQL4 언어로 공식화를 수행했습니다. 또한 글에 제공된 예를 확인, 검사 및 최적화하여 최상의 매개변수를 결정합니다.
트레이더의 황금률 트레이더의 황금률
높은 기대치를 바탕으로 수익을 내기 위해서는 좋은 거래의 세 가지 기본 원칙을 이해해야 합니다. 1) 시장에 진입할 때 위험을 알아야 합니다. 2) 손실을 조기에 줄이고 이익이 날 수 있도록 하십시오. 3) 시스템의 기대치를 파악하고 정기적으로 테스트하고 조정합니다. 이 글은 가능한 최고 수준의 수익을 올릴 수 있도록 열린 포지션을 추적하고 두 번째 황금 원칙을 실현하는 프로그램 코드를 제공합니다.