English Русский 中文 Español Deutsch 日本語 Português Français Italiano
preview
MQL5의 주문에 대한 이해

MQL5의 주문에 대한 이해

MetaTrader 5트레이딩 |
21 6
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

소개

모든 트레이딩 시스템에서 우리는 포지션 진입, 손절 및 이익실현, 주문 수정 등 주문과 그 운영을 처리해야 합니다. 따라서 MetaTrader5용 트레이딩 시스템을 만들 때 mql5에서 주문 작업을 처리하는 방법을 이해하는 것이 매우 중요합니다. 이 글의 목적은 대부분의 주문 및 포지션 작업에 대한 간단한 지침을 제공하여 이글의 주제에 대한 모든 것을 효과적으로 처리할 수 있도록 하는 것입니다. 이 글에서는 다음의 주제들을 다룹니다:

이 글이 MetaTrader5 트레이딩 시스템을 원활하게 구축하는 데 도움이 되길 바랍니다. 여러분은 이 글에서 다루는 모든 애플리케이션을 사용하기 전에 반드시 테스트하여 수익성이 있는지 또는 거래에 적합한지 확인해야 합니다. 이 글의 주된 목적은 주문, 거래 및 포지션 작업과 관련하여 두 가지 다른 방법을 사용하여 거래 시스템을 만드는 예제를 제공하는 것입니다.

면책: 모든 정보는 정보 제공의 목적으로만 '있는 그대로' 제공되며 거래의 목적이나 조언을 위해 준비된 것이 아닙니다. 여기의 정보는 어떤 종류의 결과도 보장하지 않습니다. 거래 계좌에서 이러한 자료를 사용하기로 선택한 경우, 이에 대한 책임은 전적으로 귀하에게 있으며, 이에 대한 책임은 전적으로 귀하에게 있습니다.

주문, 포지션 및 거래 조건

이 부분에서는 주문을 효과적으로 처리하는 방법을 이해하는 데 도움이 되는 중요한 용어에 대해 설명합니다. MetaTrader 5에서 주문과 관련된 세 가지 용어의 차이점에 대해 알아 보겠습니다. 이러한 용어는 주문, 거래, 포지션이며 이들 모두 거래를 체결하기 위한 단계로 간주할 수 있습니다.

주문: 특정 랏 또는 수량으로 특정 가격에 매수 또는 매도 거래를 개시하라는 거래 서버에 접수된 요청입니다. 주문에는 마켓 주문과 펜딩 주문의 두 가지 유형이 있습니다.

  • 마켓 주문: 현재 시장가로 즉시 체결될 수 있는 주문입니다.
  • 펜딩 주문: 해당 호가 수준에서 거래를 체결할 가격과 거래 체결 시간에 대해 미리 정해진 조건에 따라 거래를 체결하는 주문입니다. 

이러한 펜딩 주문은 다음 중 하나일 수 있습니다:

    • 바이 스탑: 현재 시장가보다 높은 특정 가격에 펜딩 매수 주문을 넣습니다.
    • 바이 리밋: 현재 시장의 가격보다 낮은 특정 가격에 바이 리밋 주문을 넣습니다.
    • 셀 스탑: 현재 시장의 가격보다 낮은 특정 가격에 매도 펜딩 주문을 넣습니다.
    • 셀 리밋: 현재 시장의 가격보다 높은 특정 가격에 매도 펜딩 주문을 넣습니다.

주문이 접수되면 마켓 주문이든 펜딩 주문이든 상관없이 MetaTrader 5의 도구 상자의 매매 탭에서 확인할 수 있습니다. 다음은 그 예입니다:

1- 매매 탭


주문이 실행되지 않고 종료되거나 취소된 경우 도구 상자의 거래 내역 탭에서 해당 주문을 확인할 수 있습니다.

2- 거래 내역 탭

MQL5로 현재 포지션을 수정하려면 나중에 주문 수정을 처리할 때와 마찬가지로 주문을 처리해야 합니다.

거래: 거래 주문이 체결되거나 체결될 때의 결과입니다. 거래 실행에 따른 인/아웃 액션으로 찾을 수 있습니다. 한 랏의 매수 주문이 체결되었다고 가정해 보겠습니다. 그 후 포지션의 일부 0.5 랏을 청산한 다음 나머지 0.5 랏을 청산했습니다. 따라서 거래는 다음과 같습니다:

  • 1 바이 인
  • 0.5 셀 아웃
  • 0.5 셀 아웃

MetaTrader 5 도구 상자의 거래 내역 탭에서 마우스 오른쪽 버튼으로 클릭하고 선택하여 이러한 거래를 찾을 수 있습니다.

3- 거래

포지션: 금융자산의 매수 또는 매도를 기준으로 한 매수 또는 매도 거래의 순차익입니다. 매매 탭에서 활성 거래로 표시되거나 포지션을 선택하면 거래 내역 탭에서 확인할 수 있습니다.

4- 포지션

매수 주문의 체결 가격은 Ask, 매도시 체결 가격은 Bid라는 점을 기억해두는 것이 좋습니다. 반면 매도 주문의 체결 가격은 Bid, 매수시 체결 가격은 Ask입니다.

OrderSend()

MetaTrader 5에서 거래의 체결과 관련한 중요한 용어를 이해한 후에는 MQL5에서 주문을 자동으로 체결하는 방법을 알아야 합니다. 먼저 거래를 관리하기 위한 함수에 대한 자세한 내용은 MQL5 참조 Trade Functions에서 확인할 수 있습니다.

이제 거래 서버에 요청을 전송하여 거래 작업을 실행하는 데 사용할 수 있는 OrderSend() 함수에 대해 알아보겠습니다. 이 함수는 주문, 수정, 청산에 사용할 수 있습니다.

이 함수의 형식은 다음과 같습니다:

bool  OrderSend(
   MqlTradeRequest&  request,      
   MqlTradeResult&   result        
   );

보시다시피 이 함수에는 두 개의 매개 변수가 있습니다:

  • MqlTradeRequest 구조: 여기에는 주문 매개변수와 거래를 수행하는 데 필요한 모든 필드와 변수가 포함되어 있습니다. ampersands에 따라 참조로 전달된 객체. TradeRequest는 주문을 체결하기 위해 클라이언트 터미널과 트레이딩 서버가 상호 작용하는 메서드입니다.
  • MqlTradeResult 구조: radeResult는 주문 요청의 결과를 반환합니다. 참조로 전달된 객체도 마찬가지입니다.

MqlTradeRequest 구조:

구조는 다양한 유형의 관련 데이터 집합입니다. MqlTradeRequest 구조 정의는 다음과 같습니다:

struct MqlTradeRequest
  {
   ENUM_TRADE_REQUEST_ACTIONS    action;           // Trade operation type
   ulong                         magic;            // Expert Advisor ID (magic number)
   ulong                         order;            // Order ticket
   string                        symbol;           // Trade symbol
   double                        volume;           // Requested volume for a deal in lots
   double                        price;            // Price
   double                        stoplimit;        // StopLimit level of the order
   double                        sl;               // Stop Loss level of the order
   double                        tp;               // Take Profit level of the order
   ulong                         deviation;        // Maximal possible deviation from the requested price
   ENUM_ORDER_TYPE               type;             // Order type
   ENUM_ORDER_TYPE_FILLING       type_filling;     // Order execution type
   ENUM_ORDER_TYPE_TIME          type_time;        // Order expiration type
   datetime                      expiration;       // Order expiration time (for the orders of ORDER_TIME_SPECIFIED type)
   string                        comment;          // Order comment
   ulong                         position;         // Position ticket
   ulong                         position_by;      // The ticket of an opposite position
  };

MqlTradeRequest 객체를 선언하려면 다음의 코드를 통해 선언할 수 있습니다:

MqlTradeRequest request;

이후 다음 예시와 같이 객체 뒤에 점(.)을 추가하여 생성된 요청 객체의 변수에 거래 매개변수를 할당할 수 있습니다:

request.symbol = _Symbol;
request.volume = 0.01;
request.type = ORDER_TYPE_BUY;

다음은 할당에 허용되는 값과 MqlTradeRequest 구조의 모든 멤버 또는 변수 목록입니다.

변수 설명 할당에 허용된 값
action 거래 작업의 유형을 나타냅니다.

ENUM_TRADE_REQUEST_ACTIONS(TRADE_ACTION_DEAL, TRADE_ACTION_PENDING, TRADE_ACTION_SLTP, TRADE_ACTION_MODIFY, TRADE_ACTION_REMOVE, TRADE_ACTION_CLOSE_BY). 중 하나

magic 어떤 EA가 주문한 주문인지를 식별하기 위한 EA의 ID입니다. 모든 울롱 값
order 주문 티켓입니다. action 변수에서 TRADE_ACTION_MODIFY 또는 TRADE_ACTION_REMOVE를 사용할 때 필요합니다.  모든 울롱 값
symbol 지정한 심볼 또는 거래할 상품(_SYMBOL)은 현재 심볼을 나타냅니다. 모든 문자열 기호
volume 거래 볼륨 또는 랏을 지정합니다.  허용되는 모든 더블 값
price 시초가 더블 값
stoplimit 리밋 펜딩 오더의 개시 가격입니다. 액션은 TRADE_ACTION_PENDING이어야 하고 유형 변수는 ORDER_TYPE_BUY_STOP_LIMIT 또는 ORDER_TYPE_SELL_STOP_LIMIT이어야 하며 스탑 리밋 주문에 필요합니다. 더블 값
sl 거래의 손절매 가격 더블 값
tp 거래의 이익실현가 더블 값
deviation 포인트로 최대 가격 편차 울롱 값
유형 주문 유형 ENUM_ORDER_TYPE  (ORDER_TYPE_BUY, ORDER_TYPE_SELL, ORDER_TYPE_BUY_STOP, ORDER_TYPE_SELL_STOP, 
ORDER_TYPE_BUY_LIMIT, ORDER_TYPE_SELL_LIMIT,  ORDER_TYPE_BUY_STOP_LIMIT, ORDER_TYPE_SELL_STOP_LIMIT)
type_filling 주문 실행 유형 또는 주문의 체결 정책 ENUM_ORDER_TYPE_FILLING (ORDER_FILLING_FOK, ORDER_FILLING_IOC, ORDER_FILLING_BOC, ORDER_FILLING_RETURN) 중 하나입니다.
type_time 펜딩 오더 만료 유형 ENUM_ORDER_TYPE_TIME (ORDER_TIME_GTC, ORDER_TIME_DAY, ORDER_TIME_SPECIFIED, ORDER_TIME_SPECIFIED_DAY) 중 하나
expiration 펜딩 오더 만료 시간입니다. type_time이 ORDER_TIME_SPECIFIED 경우 필요합니다. 날짜/시간 값
comment 주문 코멘트 문자열 값
position 포지션 티켓입니다. 포지션이 수정되거나 청산 될 때 포지션을 식별하기 위해 필요합니다. 울롱 값
position_by 반대 포지션의 티켓입니다. 동일한 심볼에 대해 반대 방향의 열린 포지션이 닫혀 있을 때 사용됩니다. 울롱 값

이제 MQL5에서 주문할 때 사용해야 하는 몇 가지 중요한 작업에 대해 알아보겠습니다.

  • 마켓 오더
  • 손절매 및 이익실현 추가
  • 펜딩 오더
  • 펜딩 오더 수정
  • 펜딩 오더 삭제

마켓 오더:

이 유형에서는 현재의 시장가로 주문하는 마켓 오더를 해야 하므로(TRADE_ACTION_DEAL)을 사용합니다. 매수 주문인 경우 현재 Ask 가격에 주문이 체결되고 매도 주문인 경우 현재 Bid 가격에 주문이 체결됩니다. 방법은 다음과 같습니다: 

MqlTradeRequest 및 MqlTradeResult 객체를 선언한 후 변수들에 다음 값을 할당할 수 있습니다:

request.action = TRADE_ACTION_DEAL;                    &nbsthe p;   //market order palcement
request.type = ORDER_TYPE_BUY;                             //type of order is buy
request.symbol = _Symbol;                                  //applied for the cuurrent symbol
request.volume = 0.1;                                      //the lot size
request.type_filling = ORDER_FILLING_FOK;                  //the filling policy fill or kill
request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);      //the price is the current ask for buy
request.sl = 0;                                            //stop loss is 0
request.tp = 0;                                            //take profit is 0
request.deviation = 50;                                    //slippage is 50
OrderSend(request, result);                                //calling the OrderSend function

이전 코드에서와 같이 손절매와 이익 실현 값을 추가하지 않았습니다. 다른 변수와 함께 코드에 해당 값을 추가하거나 추후 살펴보겠지만 다른 작업을 통해 추가할 수 있습니다.

손절매 및 이익 실현 추가:

손절매와 이익실현을 추가해야 하는 경우 다음 예시와 같이 TRADE_ACTION_SLTP를 변수 액션에 할당합니다.

request.action = TRADE_ACTION_SLTP;          //adding sl and tp
request.symbol = _Symbol;                    //applied for the cuurrent symbol
request.sl = 1.07000;                        //sl price
request.sl = 1.09000;                        //tp price
OrderSend(request, result);                  //calling the OrderSend function


펜딩 오더:

펜딩 오더를 하려면 다른 액션(TRADE_ACTION_PENDING)을 사용하면 됩니다. 그런 다음 주문 유형을 결정합니다. 펜딩 오더의 만료 시간이 필요한 경우 시간을 설정할 수 있습니다.

request.action = TRADE_ACTION_PENDING;          //pending order placement
request.type = ORDER_TYPE_BUY_STOP;             //type of order is buy stop
request.symbol = _Symbol;                       //applied for the cuurrent symbol
request.volume = 0.1;                           //the lot size
request.price = 1.07000;                        //opening price
request.sl = 1.06950;                           //stop loss
request.tp = 1.07100;                           //take profit
request.type_time = ORDER_TIME_SPECIFIED;       //to set an expiration time
request.expiration = D'2023.08.31 00.00';       //expiration time - datetime constant          
request.type_filling = ORDER_FILLING_FOK;       //the filling policy fill or kill
request.stoplimit = 0;                          //for stoplimit order only
OrderSend(request, result);                     //calling the OrderSend function


펜딩 오더 수정:

펜딩 오더를 수정해야 하는 경우 수정해야 하는 펜딩 오더의 주문 티켓 번호를 받아야 합니다. 오더 티켓을 가져오기 위해 OrderGetTicket 함수를 사용합니다. 이 함수는 해당 오더의 티켓을 반환하며 이를 사용하여 주문을 선택하고 작업할 수 있습니다.

ulong  OrderGetTicket( 
   int  index      // Number in the list of orders 
   );

오더 티켓 번호를 저장하는 (ticket)이라는 변수가 있다고 가정해 보겠습니다. 이 변수를 사용하여 오더 티켓의 번호를 요청 객체의 주문 변수에 할당할 수 있습니다. 그런 다음 예제와 같은 액션(TRADE_ACTION_MODIFY)을 사용하여 주문을 수정할 수 있습니다.

request.action = TRADE_ACTION_MODIFY;           //pending order modyfying
request.order = ticket;                         //ticket variable that holds the pending order ticket to modify
request.price = 1.07050;                        //new opening price
request.sl = 1.07000;                           //new stop loss
request.tp = 1.07150;                           //new take profit
request.type_time = ORDER_TIME_SPECIFIED;       //to set an expiration time
request.expiration = D'2023.09.01 00.00';       //new expiration time - datetime constant        
OrderSend(request, result);                     //calling the OrderSend function

펜딩 오더를 제거합니다:

펜딩 오더를 제거해야 하는 경우(TRADE_ACTION_REMOVE) 액션을 사용하여 제거할 수 있습니다. 제거해야 하는 펜딩 주문의 티켓 번호도 필요합니다. 변수 티켓에 필요한 티켓 번호가 있다고 가정하고 사용할 수 있습니다.

request.action = TRADE_ACTION_REMOVE;           //pending order remove
request.order = ticket;                         //ticket variable that holds the pending order ticket to remove
OrderSend(request, result);                     //calling the OrderSend function

MqlTradeResult 구조:

MqlTradeResult 구조는 주문이 OrderSend() 함수에 의해 접수되면 주문 성공 여부에 대한 결과를 반환합니다. 여기에는 티켓 번호, 볼륨, 가격 등 거래 서버의 거래 정보가 포함되어 있습니다.

다음은 MqlTradeResult 구조의 정의입니다:

struct MqlTradeResult
  {
   uint     retcode;          // Operation return code
   ulong    deal;             // Deal ticket, if it is performed
   ulong    order;            // Order ticket, if it is placed
   double   volume;           // Deal volume, confirmed by broker
   double   price;            // Deal price, confirmed by broker
   double   bid;              // Current Bid price
   double   ask;              // Current Ask price
   string   comment;          // Broker comment to operation (by default it is filled by description of trade server return code)
   uint     request_id;       // Request ID set by the terminal during the dispatch 
   int      retcode_external; // Return code of an external trading system
  };

result라는 객체를 선언하여 첫 번째 매개변수(요청) 뒤에 두 번째 매개변수로 OrderSend() 함수 호출에 전달할 수 있습니다.

MqlTradeResult result;

MqlTradeResult 구조의 변수에서 볼 수 있듯이 retcode 변수는 매우 중요합니다. 이 변수는 요청이 성공했는지 여부를 나타내는 코드를 거래 서버로부터 반환합니다.

거래가 접수되지 않으면 반환 코드는 오류를 표시합니다. 자세한 내용은 MQL5 참조에서 return codes 목록을 확인할 수 있습니다. 다음 예시와 같이 오류 반환 여부를 보고하는 코드를 우리의 거래 시스템에 포함시키는 것이 중요합니다:

   if(result.retcode == TRADE_RETCODE_DONE || result.retcode == TRADE_RETCODE_PLACED)
     {
      Print("Trade Placed Successfully");
     }
   else
     {
      Print("Trade Not Placed, Error ", result.retcode);
     }

이전 코드와 같이 요청 후 결과와 함께 메시지를 출력하고 결과 변수를 채웁니다. 거래가 접수된 경우 해당 메시지를 보내고 문제가 있는 경우 오류가 발생했다는 메시지를 출력하고 오류 코드를 반환하여 문제를 해결하는 데 도움을 줍니다.

OrderSend() 애플리케이션

OrderSend() 함수를 사용하여 거래를 실행할 수 있는 간단한 트레이딩 시스템을 만들어야 합니다. 우리가 만들어야 하는 트레이딩 시스템은 단순 이동평균 교차이며 작업은 마켓 오더만 하는 것입니다.

이 글의 목적은 OrderSend()와 CTrade 클래스를 사용하여 동일한 트레이딩 시스템을 만들 때 어떠한 차이점이 있는지 이해하는 것입니다. OrderSend() 함수를 사용하여 이 MA 교차를 생성하는 단계는 다음과 같습니다.

전역 범위에서 할당 없이 두 개의 정수 변수(simpleMA, barsTotal)를 생성하고 나중에 OnInit 파트에서 할당합니다.

int simpleMA;
int barsTotal;

simpleMA는 이동평균 지표의 핸들을 반환하는 iMA 함수에 할당됩니다. 매개변수는 다음과 같습니다:

  • symbol: 기호 이름을 지정할 때 _Symbol은 현재 상품을 나타냅니다.
  • period: 차트 주기를 지정하기 위해 1시간의 시간 프레임을 나타내는 PERIOD_H1을 사용합니다.
  • ma_period: 이동 평균의 기간, 50으로 설정합니다.
  • ma_shift: 필요한 수평 이동을 지정합니다.
  • ma_method: 이동 평균의 유형을 지정합니다. 우리는 단순 유형을 지정하겠습니다.
  • applied_price: MA 계산에 사용할 가격 유형을 지정합니다. 우리는 종가를 설정합니다.

바의 개수를 반환하는 iBars 함수에 barsTotal이 할당됩니다. 매개변수는 다음과 같습니다:

  • symbol: 심볼명
  • timeframe: 차트 주기 기간
   simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,PERIOD_H1);

OnTick 부분에서는 가격, 거래량 및 스프레드에 대한 정보를 저장하는 MqlRates 유형을 사용하여 가격에 대한 배열을, 더블 변수 유형을 사용해서는 이동 평균에 대한 배열을 각각 생성합니다.

   MqlRates priceArray[];
   double mySMAArray[];

매도 호가 및 매수 호가 정의하기

   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);

OrderSend() 함수에 대해 두 개의 객체를 생성합니다. 하나는 MqlTradeReuest를 사용한 요청용이고 다른 하나는 MqlTradeResult를 사용한 결과용입니다. 그리고 참조로 요청 변수를 재설정합니다.

ZeroMemory(request);

ArraySetAsSeries 함수를 사용하여 생성된 두 개의 배열 priceArray와 mySMAArray에 AS_SERIES 플래그를 설정합니다. 매개변수:

  • array[]: 필요한 배열을 지정합니다
  • flag: 배열 인덱싱 방향을 지정합니다.
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);

CopyRates 함수를 사용하여 MqlRates의 과거 데이터를 가져옵니다. 매개변수는 다음과 같습니다:

  • symbol: 심볼명입니다 현재 심볼을 나타내기 위해 _Symbol을 사용합니다.
  • time frame: 차트 주기입니다. 현재 차트 주기를 나타내기 위해 _period를 사용합니다.
  • start position: 시작할 위치.
  • count: 복사할 데이터 수.
  • rates_array: 복사할 대상 배열.
int Data=CopyRates(_Symbol,_Period,0,3,priceArray);

CopyBuffer 함수를 사용하여 지표 데이터 버퍼 가져오기. 매개변수:

  • indicator_handle: MA로 지표 핸들을 지정.
  • buffer_num: 지표 버퍼 번호를 지정.
  • start_pos: 계산할 시작 위치.
  • count: 복사할 양.
  • buffer[]: 대상 배열.
CopyBuffer(simpleMA,0,0,3,mySMAArray);

최종, 이전 종가, 최종 및 이전 SMA 값 정의하기

   double lastClose=(priceArray[1].close);
   double prevClose=(priceArray[2].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);

정수 바 변수를 생성하고 iBars에 할당합니다.

int bars=iBars(_Symbol,PERIOD_H1);

barsTotal이 바 변수와 같지 않은 경우 바 확인

if(barsTotal != bars)

barsTotal값이 서로 같지 않은 경우 barsTotal값을 바와 같도록 업데이트하기

barsTotal=bars;

이전 종가가 이전 SMA 값보다 작은 이후에 마지막 종가가 마지막 SMA 값보다 큰 경우에 거래를 개시하기 위한 전략의 조건을 확인합니다.

if(prevClose<prevSMAVal && lastClose>SMAVal)

MqlTradeRequest 함수와 관련된 적절한 변수를 사용하여 마켓 매수 주문 열기

         request.action = TRADE_ACTION_DEAL;
         request.type = ORDER_TYPE_BUY;
         request.symbol = _Symbol;
         request.volume = 0.1;
         request.type_filling = ORDER_FILLING_FOK;
         request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         request.sl = Ask-(500*_Point);
         request.tp = Ask+(1000*_Point);
         request.deviation = 50;
         OrderSend(request, result);

이전 종가가 이전 SMA 값보다 큰 후 마지막 종가가 마지막 SMA 값보다 작은 경우 매도 거래를 위해 전략의 조건을 확인합니다.

if(prevClose>prevSMAVal && lastClose<SMAVal)
MqlTradeRequest 함수와 관련된 적절한 변수를 사용하여 마켓 매도 주문 제출하기
         request.type = ORDER_TYPE_SELL;
         request.symbol = _Symbol;
         request.volume = 0.1;
         request.type_filling = ORDER_FILLING_FOK;
         request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         request.sl = Bid+(500*_Point);
         request.tp = Bid-(1000*_Point);
         request.deviation = 50;
         OrderSend(request, result);

OrderSend() 함수를 사용하여 이러한 유형의 거래 시스템을 생성하는 전체 코드는 다음과 같습니다.

//+------------------------------------------------------------------+
//|                                     OrderSend_Trading_system.mq5 |
//+------------------------------------------------------------------+
int simpleMA;
int barsTotal;
int OnInit()
  {
   simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,PERIOD_H1);
   return(INIT_SUCCEEDED);
  }
void OnTick()
  {
   MqlRates priceArray[];
   double mySMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   MqlTradeRequest request;
   MqlTradeResult result;
   ZeroMemory(request);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);
   int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
   CopyBuffer(simpleMA,0,0,3,mySMAArray);
   double lastClose=(priceArray[1].close);
   double prevClose=(priceArray[2].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
   int bars=iBars(_Symbol,PERIOD_H1);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         request.action = TRADE_ACTION_DEAL;
         request.type = ORDER_TYPE_BUY;
         request.symbol = _Symbol;
         request.volume = 0.1;
         request.type_filling = ORDER_FILLING_FOK;
         request.price = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         request.sl = Ask-(500*_Point);
         request.tp = Ask+(1000*_Point);
         request.deviation = 50;
         OrderSend(request, result);
        }
      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         request.action = TRADE_ACTION_DEAL;
         request.type = ORDER_TYPE_SELL;
         request.symbol = _Symbol;
         request.volume = 0.1;
         request.type_filling = ORDER_FILLING_FOK;
         request.price = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         request.sl = Bid+(500*_Point);
         request.tp = Bid-(1000*_Point);
         request.deviation = 50;
         OrderSend(request, result);
        }
     }
  }

CTrade 클래스

OrderSend() 함수로 주문하는 방법을 알게 되면 거래 함수에 쉽게 접근할 수 있는 방법이 있습니다. MQL5에서 제공하는 CTrade 내장 클래스를 사용하거나 개인 취향에 따라 자체 클래스를 만들 수도 있습니다. 이제 MQL5에서 CTrade 내장 클래스를 사용하는 방법에 대해 알아보겠습니다. 자세한 내용은 MQL5 참조 CTrade에서 클래스에 대한 모든 것을 확인할 수 있습니다.

먼저 MetaTrader 5 설치 파일 내 include 폴더의 Trade 폴더에서 CTrade 클래스의 include 파일을 찾을 수 있습니다. 우리는 이 파일을 Expert Advisor에 포함시켜 다음과 같이 모든 거래 함수를 호출하고 사용하기만 하면 됩니다:

#include <Trade\Trade.mqh>

CTrade 클래스에서 객체 생성

CTrade trade;

그 후에는 점(.) 앞에 trade를 붙이고 원하는 함수를 사용하면 CTrade 클래스의 모든 거래 함수를 사용할 수 있습니다. 주문 작업, 포지션 작업, 마지막 요청 매개변수에 대한 액세스, 마지막 요청 확인 결과에 대한 액세스, 마지막 요청 실행 결과에 대한 액세스 등 모든 함수를 사용할 수 있습니다.

두 메서드의 차이점을 이해하기 위해 OrderSend()에서와 마찬가지로 몇 가지 중요한 함수에 대해 알아보겠습니다. 다음을 수행하는 방법을 이해해야 합니다:

  • 마켓 오더
  • 손절매 및 이익실현 추가
  • 펜딩 오더
  • 펜딩 오더 수정
  • 펜딩 오더 삭제

마켓 오더:

거래 객체를 만든 후 PositionOpen 함수를 사용하여 마켓 오더를 할 수 있습니다. 매개 변수는 다음과 같습니다:

  • symbol: 필요한 심볼을 지정합니다.
  • order_type: 포지션을 개설할 주문 유형을 지정합니다.
  • volume: 랏 크기를 지정합니다.
  • price: 포지션 개시 가격을 지정합니다.
  • sl: 손절가 지정
  • TP: 이익실현가 지정
  • comment: 주석 또는 NULL을 지정합니다.

다음은 그 예입니다:

trade.PositionOpen(
   _Symbol,             //to be applied for the current symbol
   ORDER_TYPE_BUY,      //to place buy order
   0.1,                 //lot size or volume
   Ask,                 //opening price of the order - current ask
   Ask-(500*_Point),    //sl
   Ask+(1000*_Point),   //tp
   NULL                 //NULL
);

또한 PositionOpen 대신 Buy, Sell과 같은 메서드를 사용하여 마켓 오더를 제출할 수 있습니다.

손절매 및 이익 실현 추가:

PositionModify 함수를 사용하여 심볼 또는 티켓 번호 별로 포지션을 수정할 수 있습니다. 매개변수는 다음과 같습니다:

  • symbol 또는 ticket: 수정해야 하는 포지션을 지정합니다. 심볼로 수정하는 경우에는 심볼명을 지정하고 티켓으로 수정하는 경우에는 티켓 번호를 지정합니다.
  • SL: 새로운 손절매 가격
  • TP: 이익실현 가격

심볼로 수정하는 예제입니다:

trade.PositionModify(
   EURUSD,       //the symbol name
   1.06950,      //the new sl
   1.07100,      //the new tp
);

티켓으로 수정하는 예제입니다:

trade.PositionModify(
   ticket,       //the ticket variable that holds the needed ticket number to modify
   1.06950,      //the new sl
   1.07100,      //the new tp
);

펜딩 오더:

CTrade 클래스를 사용하여 펜딩 오더를 제출 해야 하는 경우 OrderOpen 함수를 사용할 수 있습니다. 매개변수는 다음과 같습니다:

  • symbol: 심볼명을 결정합니다.
  • order_type: 펜딩 오더 유형을 결정합니다.
  • volume: 랏 크기를 지정합니다.
  • limit_price: 스탑 리밋 가격을 지정합니다.
  • price: 펜딩 오더의 체결 가격을 지정합니다.
  • sl: 손절매를 지정합니다
  • tp: 이익 실현 가격을 지정합니다.
  • type_time: 만료별로 유형을 지정합니다.
  • expiration: 만료 날짜/시간 변수를 지정합니다.
  • comment: 필요한 경우 코멘트를 지정합니다.

다음 예시는 OrderOpen 함수를 사용하여 바이 리밋 펜딩 오더를 하는 경우입니다.

         trade.OrderOpen(
            "EURUSD",                 // symbol
            ORDER_TYPE_BUY_LIMIT,     // order type
            0.1,                      // order volume
            0,                        // StopLimit price
            1.07000,                  // execution price
            1.06950,                  // Stop Loss price
            1.07100,                  // Take Profit price
            ORDER_TIME_SPECIFIED,     // type by expiration
            D'2023.08.31 00.00',      // expiration
            ""                        // comment
         );

펜딩 오더 수정:

펜딩 오더를 수정해야 하는 경우 OrderModify 함수의 CTrade 클래스를 사용하여 수정할 수 있습니다. 매개변수는 다음과 같습니다:

  • ticket: 수정할 펜딩 오더 티켓을 지정합니다.
  • price: 새로운 실행 가격
  • sl: 새로운 손절매 가격
  • TP: 새로운 이익 실현 가격
  • type_time: 만료별로 유형을 지정합니다.
  • expiration: 만료 날짜 시간 변수를 지정합니다.
  • stoplimit: 지정가 주문 가격을 결정합니다.

다음은 펜딩 오더 수정의 예입니다.

         trade.OrderModify(
            ticket,                   // ticket number of the pending order to modify
            1.07050,                  // execution price
            1.07000,                  // Stop Loss price
            1.07150,                  // Take Profit price
            ORDER_TIME_SPECIFIED,     // type by expiration
            D'2023.08.31 00.00',      // expiration
            0,                        // StopLimit price
         );

펜딩 오더를 삭제합니다:

펜딩 오더를 삭제해야 하는 경우에는 OrderDelete 함수를 사용하여 삭제할 수 있으며 삭제할 펜딩 오더의 티켓 번호가 필요합니다. 다음은 해당 함수의 예입니다.

         trade.OrderDelete(
            ticket,                 // tick number of the pending order to delete
         );

CTrade 클래스 애플리케이션

OrderSend() 함수를 사용하여 만든 것과 동일한 트레이딩 시스템을 만들어야 합니다. CTrade 클래스를 사용하여 두 클래스에서 함수가 작동하는 방식의 차이점을 이해하겠습니다.

다음은 CTrade 클래스를 사용하여 이 트레이딩 시스템을 만들때 유일한 차이가 있는 단계이며 나머지 단계는 이전과 동일합니다.

전처리기 #include를 사용하여 include 파일 포함하기

#include <Trade\Trade.mqh>

CTrade 클래스에서 거래 객체를 생성합니다.

CTrade trade;

매수 조건이 충족되면 PositionOpen을 사용할 수 있으며 주문 유형은 ORDER_TYPE_BUY 또는 다음 코드와 같은 추가 매수 메서드가 됩니다.

trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL);

매도 조건이 충족되면 PositionOpen과 함께 주문 유형 ORDER_TYPE_SELL 또는 다음 코드와 같은 추가 매도 메서드를 사용할 수 있습니다.

trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL);

다음은 CTrade 클래스를 사용하여 거래 시스템을 만드는 전체 코드입니다:

//+------------------------------------------------------------------+
//|                                        CTrade_Trading_System.mq5 |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
int simpleMA;
int barsTotal;
CTrade trade;
int OnInit()
  {
   simpleMA = iMA(_Symbol, PERIOD_H1, 50, 0, MODE_SMA, PRICE_CLOSE);
   barsTotal=iBars(_Symbol,PERIOD_H1);
   return(INIT_SUCCEEDED);
  }
void OnTick()
  {
   MqlRates priceArray[];
   double mySMAArray[];
   double Ask = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_ASK),_Digits);
   double Bid = NormalizeDouble(SymbolInfoDouble(_Symbol,SYMBOL_BID),_Digits);
   ArraySetAsSeries(priceArray,true);
   ArraySetAsSeries(mySMAArray,true);
   int Data=CopyRates(_Symbol,_Period,0,3,priceArray);
   CopyBuffer(simpleMA,0,0,3,mySMAArray);
   double lastClose=(priceArray[1].close);
   double prevClose=(priceArray[2].close);
   double SMAVal = NormalizeDouble(mySMAArray[1],_Digits);
   double prevSMAVal = NormalizeDouble(mySMAArray[2],_Digits);
   int bars=iBars(_Symbol,PERIOD_H1);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      if(prevClose<prevSMAVal && lastClose>SMAVal)
        {
         trade.Buy(0.1,_Symbol,Ask,Ask-(500*_Point),Ask+(1000*_Point),NULL);
        }
      if(prevClose>prevSMAVal && lastClose<SMAVal)
        {
         trade.Sell(0.1,_Symbol,Bid,Bid+(500*_Point),Bid-(1000*_Point),NULL);
        }
     }
  }

결론

이 글을 다 읽으셨다면 MQL5에서 주문, 포지션, 거래가 어떻게 작동하는지 이해하셨을 것입니다. 두 가지 거래 운영 메서드인 OrderSend 메서드와 CTrade 메서드를 사용하여 거래 시스템을 원활하게 만드는 방법 이외에

이들 메서드를 사용하여 마켓 오더 및 펜딩 오더, 손절 및 이익실현 추가, 펜딩 오더 수정, 펜딩 오더 제거 또는 삭제하는 방법을 확인했습니다.

우리는 두 가지 메서드를 사용하여 동일한 이동평균 크로스오버 트레이딩 시스템을 만드는 두 가지 간단한 응용 프로그램을 통해 앞서 설명한 모든 메서드를 응용 프로그램을 만드는 데 적용하는 방법을 알아보았습니다.

  • OpenSend_Trading_System
  • CTrade_Trading_System

살펴본 애플리케이션의 목적은 이둘의 차이점을 이해하기 위한 것이었습니다. 여러분은 실제 라이브 계좌에서 사용하기 전에 반드시 테스트하여 수익성이 있고 거래에 적합한지 확인해야 합니다.

여러분이 거래 작업을 할 때 내장 CTrade 클래스를 사용하면 많은 시간과 노력을 절약 할 수 있습니다. 일반적으로 프로그래밍에서 클래스를 사용할 때 다른 기능도 사용할 수 있습니다.

이에 대한 자세한 내용과 MQL5의 객체 지향 프로그래밍에 대해 자세히 알고 싶으시다면 이전 글인 'MQL5 객체 지향 프로그래밍(OOP) 이해'를 읽어보시면 도움이 될 것입니다. MQL5는 트레이딩 소프트웨어를 원활하고 쉽게 개발하고 제작할 수 있는 도구를 제공하기 위해 많은 노력과 수고를 아끼지 않았습니다.

이 글이 도움이 되셨기를 바라며 이 인사이트를 통해 여러분이 작업을 쉽게 이해하고 수행하는 데 유용한 인사이트를 많이 얻으셨기를 바랍니다. 가장 인기있는 기술 지표를 사용하여 거래 시스템을 만드는 방법에 대해 읽고 싶으시면 저의 간행물 섹션에서 이전 기사들을 읽을 수 있습니다. 유용하게 사용하시기 바랍니다.

MetaQuotes 소프트웨어 사를 통해 영어가 번역됨
원본 기고글: https://www.mql5.com/en/articles/13229

최근 코멘트 | 토론으로 가기 (6)
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud | 24 10월 2023 에서 01:11
gunther64 #:

안녕하세요,


좋은 글이었어요, 타이브.

작은 버그 1개를 발견했습니다:

TRADE_ACTION_SLTP 아래 상자에 요청.sl을 두 번 작성했는데, 두 번째 요청은 줄 끝의 주석에 표시된 대로 요청.tp여야 합니다.


감사합니다,

Gunther

안녕하세요,

친절한 의견에 감사드립니다. 맞습니다, 실수이며 검토하겠습니다.


감사합니다,

rurubest
rurubest | 8 4월 2024 에서 12:45
안녕하세요!
귀하의 코드를 사용하여 상품에 대한 간단한 주문을 작성하고 있습니다!


double price = 94500;

double stopLoss = 가격 - (500 * _Point);

더블 테이크프로핏 = 가격 + (1000 * _포인트);


울롱 티켓 = trade.OrderOpen(

"SiM4", // 기호

ORDER_TYPE_BUY, // 주문 유형
1.0, // 주문량
가격, // 스탑리밋 가격
stopLoss, // 체결가
takeProfit, // 스톱로스 가격
NULL
);
GetLastError() = 0을 반환하고 주문이 체결되지 않고 거래가 없습니다
브로커에서 주문할 때 특별한 액세스 토큰을 지정해야 하나요?

Rashid Umarov
Rashid Umarov | 8 4월 2024 에서 13:12
rurubest #:
주문이 체결되지 않았고 트랜잭션이 없음
브로커에서 주문할 때 특별한 액세스 토큰을 지정해야 하나요?
로그를 살펴보고 OrderSend 실행 결과를 분석해 보세요.
Ahmad Juniar
Ahmad Juniar | 8 11월 2024 에서 10:53

안녕하세요 압델 마부드입니다,

이 튜토리얼을 작성해 주셔서 감사합니다.

이 튜토리얼은 주문 배치 만 제공합니다. 기사에 포지션 청산(이익실현 또는 손절매)에 대한 코드가 있나요?

감사합니다,

아마드 주니아르

2020_fusaroli.it
2020_fusaroli.it | 19 11월 2024 에서 15:25
귀중하고 상세한 튜토리얼을 제공해 주셔서 정말 감사합니다. 많은 시간과 조사 시간을 절약해 주셨어요. 다시 한 번 감사드립니다!
새로운 기능: MQL5의 커스텀 인디케이터 새로운 기능: MQL5의 커스텀 인디케이터
MetaTrader5와 MQL5의 새로운 기능 전체를 나열하지는 않겠습니다. 종류도 많은 데다가, 별도의 설명이 필요한 기능들도 있거든요. 객체 지향 프로그래밍을 이용한 코드 작성법 또한 다음에 알아보도록 하겠습니다. 다른 기능들과 함께 설명하기에는 조금 어려운 이야기일 수 있으니까요. 이 글에서는 인디케이터와 인디케이터의 구조, 드로잉 타입과 프로그래밍 디테일을 MQL4와 비교해 볼게요. 초보자 분들께 많은 도움이 되면 좋겠고 기존에 사용하시던 개발자 분들도 뭔가 새로운 걸 얻어 가실 수 있길 바랍니다.
MQL5 Algo Forge로 이동하기(2부): 여러 리포지토리로 작업하기 MQL5 Algo Forge로 이동하기(2부): 여러 리포지토리로 작업하기
이 글에서 우리는 프로젝트의 소스 코드를 공용 리포지토리에 저장하는 방법 중 하나에 대해 알아볼 것입니다. 프로젝트 개발을 위한 명확하고 편리한 규칙을 수립하기 위해 여러 브랜치에 코드를 배포할 예정입니다.
새 MetaTrader 와 MQL5를 소개해드립니다 새 MetaTrader 와 MQL5를 소개해드립니다
본 문서는 MetaTrader5의 간략 리뷰입니다. 짧은 시간 내에 시스템의 모든 세부 사항을 안내해드리기는 어렵습니다 - 테스트는 2009.09.09에 시작되었습니다. 이는 상징적인 일자로, 전 이것이 행운의 숫자가 될거라 믿어 의심치않습니다. 제가 새 MetaTrader 5 터미널과 MQL5 베타버전을 받은지 며칠이 지났습니다. 아직 모든 기능을 사용해본 것은 아니지만, 벌써부터 감명깊네요.
다양한 이동 평균 유형을 테스트하여 이들이 얼마나 통찰력이 있는지 확인합니다. 다양한 이동 평균 유형을 테스트하여 이들이 얼마나 통찰력이 있는지 확인합니다.
우리 모두 이동평균 지표의 중요성을 잘 알고 있습니다. 트레이딩에 유용한 다른 유형의 이동평균들도 있으며 이 글에서는 이러한 유형을 식별하고 각각의 유형과 가장 인기있는 단순 이동평균 유형을 간단히 비교하여 어떤 유형이 최상의 결과를 보여줄 수 있는지 알아볼 것입니다.