매매 거래의 구조 (MqlTradeTransaction)

거래 계좌에 대해 몇 가지 명확한 작업을 수행하면 상태가 변경됩니다. 이러한 작업에는 다음이 포함됩니다:

  • OrderSendOrderSendAsync 기능과 추가 실행을 사용하여 클라이언트 터미널의 MQL5 응용 프로그램에서 거래 요청 전송;
  • 터미널 그래픽 인터페이스 및 추가 실행을 통해 거래 요청 전송;
  • 서버에서 주문 보류 및 주문 활성화 중지;
  • 거래 서버측에서 작업 수행.

이러한 조치의 결과로 다음과 같은 매매 거래가 수행됩니다:

  • 거래 요청 처리;
  • 공개 주문 변경;
  • 주문 내역 변경;
  • 거래 내역 변경;
  • 포지션 변경.

예를 들어, 시장 매수 주문을 보낼 때 처리되고, 계정에 대한 적절한 매수 주문이 생성되며, 주문이 실행되어 열린 주문 목록에서 삭제되고, 주문 기록에 추가되고, 적절한 거래가 내역에 추가되고 새로운 포지션이 생성됩니다. 이 모든 행위는 매매 거래입니다.

특수 OnTradeTransaction() 핸들러는 계정에 적용되는 매매 거래를 가져오기 위해 제공됩니다. 처리기의 첫 번째 매개 변수는 MqlTradeTransaction 구조를 가져와 매매 거래를 설명합니다.

struct MqlTradeTransaction
  {
   ulong                         deal;             // 거래 티켓
   ulong                         order;            // 주문 티켓
   string                        symbol;           // 거래 기호 이름
   ENUM_TRADE_TRANSACTION_TYPE   type;             // 매매 거래 유형
   ENUM_ORDER_TYPE               order_type;       // 주문 유형
   ENUM_ORDER_STATE              order_state;      // 주문 상태
   ENUM_DEAL_TYPE                deal_type;        // 거래 유형
   ENUM_ORDER_TYPE_TIME          time_type;        // 행위 기간별 주문 유형
   datetime                      time_expiration;  // 주문 만료 시간
   double                        price;            // 가격 
   double                        price_trigger;    // 주문 활성화 가격 제한 중지
   double                        price_sl;         // 손실 중지 수준
   double                        price_tp;         // 이익 취득 수준
   double                        volume;           // 볼륨(로트)
   ulong                         position;         // 포지션 티켓
   ulong                         position_by;      // 반대 포지션의 티켓
  };

필드 설명

필드

설명

거래 티켓.

주문

주문 티켓.

심볼

트랜잭션이 수행되는 트레이딩 기호 이름.

유형

매매 거래 유형. 값은 ENUM_TRADE_TRANSACTION_TYPE 열거 값 중 하나일 수 있습니다.

order_type

거래 주문 유형. 값은 ENUM_ORDER_TYPE 열거 값 중 하나일 수 있습니다.

order_state

거래 주문 상태. 값은 ENUM_ORDER_STATE 열거 값 중 하나일 수 있습니다.

deal_type

거래 유형. 값은 ENUM_DEAL_TYPE 열거 값 중 하나일 수 있습니다.

type_time

만료 시 주문 유형. 값은 ENUM_ORDER_TYPE_TIME 값 중 하나일 수 있습니다.

time_expiration

주문 만료 기간 보류 중 (ORDER_TIME_SPECIFIEDORDER_TIME_SPECIFIED_DAY 유형 주문의 경우).

가격

가격. 매매 거래 유형에 따라 주문, 거래 또는 포지션의 가격이 될 수 있습니다.

price_trigger

주문 중지 (활성화) 가격 한도 중지 (ORDER_TYPE_BUY_STOP_LIMITORDER_TYPE_SELL_STOP_LIMIT).

price_sl

손실 중지 가격. 매매 거래 유형에 따라 주문, 거래 또는 포지션과 관련될 수 있습니다.

price_tp

이익 취득 가격. 매매 거래 유형에 따라 주문, 거래 또는 포지션과 관련될 수 있습니다.

볼륨

볼륨(로트). 매매 거래 유형에 따라 주문, 거래 또는 포지션의 현재 수량을 나타낼 수 있습니다.

포지션

트랜잭션의 영향을 받는 포지션의 티켓.

position_by

반대편 포지션의 티켓. 반대 방향, 즉 반대 방향으로 열린 동일한 기호 포지션에 의해 포지션을 닫을 때 사용됩니다.

수신된 트랜잭션 분석을 위한 필수 매개변수는 유형 필드에 지정된 유형입니다. 예를 들어, 트랜잭션이 TRADE_TRANSACTION_REQUEST 유형(서버에서 거래 요청을 처리한 결과)인 경우 구조에는 완전히 채워진 필드 하나인 유형만 있습니다. 다른 필드는 분석되지 않습니다. 이 경우, 아래와 같이 OnTradeTransaction() 핸들러에 제출된 두가지 추가 요청결과 매개변수를 분석할 수 있습니다.

거래 작업 유형에 대한 데이터가 있으면 거래 계정의 주문, 포지션 및 거래 현황 분석을 결정할 수 있습니다. 터미널에서 서버로 전송된 거래 요청 하나로 여러 개의 새 트랜잭션이 생성될 수 있습니다. 터미널에 도착하는 우선순위는 보장되지 않습니다.

MqlTradeTransaction 구조는 매매 거래 유형 (ENUM_TRADE_TRANSACTION_TYPE)에 따라 다양한 방식으로 채워집니다:

TRADE_TRANSACTION_ORDER_* 및 TRADE_TRANSACTION_HISTORY_*

MqlTradeTransaction 구조의 다음 필드는 보류 중인 주문 처리(TRADE_TRANSACTION_ORDER_ADD, TRADE_TRANSACTION_ORDER_UPDATE and TRADE_TRANSACTION_ORDER_DELETE) 및 주문 내역(TRADE_TRANSACTION_HISTORY_ADD, TRADE_TRANSACTION_HISTORY_UPDATE, TRADE_TRANSACTION_HISTORY_DELETE)과 관련된 매매 거래에 대해 채워집니다:

  • order - 주문 티켓;
  • symbol - 주문 기호 이름;
  • type - 매매 거래 유형;
  • order_type - 주문 유형;
  • orders_state - 주문 현재 상태;
  • time_type - 주문 만료 유형;
  • time_expiration - 주문 만료 시간 (ORDER_TIME_SPECIFIEDORDER_TIME_SPECIFIED_DAY 만료 유형이 있는 주문의 경우);
  • price - 클라이언트가 지정한 주문 가격;
  • price_trigger - 중제 제한 주문 중지 가격 (ORDER_TYPE_BUY_STOP_LIMITORDER_TYPE_SELL_STOP_LIMIT인 경우에만);
  • price_sl - 손실 중지 주문 가격 (주문에서 지정된 경우 채워짐);
  • price_tp - 이익 취득 주문 가격 (주문에서 지정된 경우 채워짐);
  • volume - 주문 현재 볼륨(채워지지 않음). 초기 주문량은 HistoryOrders* 기능을 사용하여 주문 내역에서 확인할 수 있습니다.
  • position - 주문 실행의 결과로 열렸거나, 수정되었거나, 닫혔던 위치의 티켓입니다. 시장 주문에 대해서만 작성되며 TRADE_TRANSACTION_ORDER_ADD에는 작성되지 않습니다.
  • position_by - 반대 포지션의 티켓. 명령에 의해서만 채워집니다(반대 포지션에 의해 닫힘).

TRADE_TRANSACTION_DEAL_*

MqlTradeTransaction 구조의 다음 필드는 거래 처리(TRADE_TRANSACTION_DEAL_ADD, TRADE_TRANSACTION_DEAL_UPDATE 및 TRADE_TRANSACTION_DEAL_DELETE)와 관련된 매매 거래에 대해 채워집니다:

  • deal - 거래 티켓;
  • order - 거래가 성사된 티켓 주문;
  • symbol - 거래 기호 이름;
  • type - 매매 거래 유형;
  • deal_type - 거래 유형;
  • price - 거래 가격;
  • price_sl - 손실 중지 가격 (주문에 지정된 경우, 거래가 수행된 기준으로 작성됨);
  • price_tp - 이익 취득 가져오기 (주문에 지정된 경우 수행된 기준으로 작성됨);
  • volume - 거래 볼륨(로트).
  • position - 거래 실행의 결과로 개설, 수정 또는 마감된 포지션의 티켓.
  • position_by - 반대 포지션의 티켓. 거래에 의해서만 아웃이 채워집니다(상대방의 포지션을 닫음).

TRADE_TRANSACTION_POSITION

MqlTradeTransaction 구조의 다음 필드는 거래 실행과 연결되지 않은 위치 변경과 관련된 매매 거래에 대해 채워집니다(TRADE_TRANSACTION_POSITION):

  • symbol - 포지션 기호 이름;
  • type - 매매 거래 유형;
  • deal_type - 포지션 유형 (DEAL_TYPE_BUY 또는 DEAL_TYPE_SELL);
  • price - 가중 평균 포지션 공개 가격;
  • price_sl - 손실 중지 가격;
  • price_tp - 이익 취득 가격;
  • volume - 볼륨이 변경된 경우 볼륨(로트) 포지션.

거래 실행으로 인한 위치 변경(추가, 변경 또는 마감)으로 인해 TRADE_TRANSACTION_POSITION 트랜잭션이 발생하지 않습니다.

TRADE_TRANSACTION_REQUEST

거래 요청이 서버에서 처리되어 처리 결과가 수신되었음을 설명하는 매매 거래에 대해 MqlTradeTransaction 구조이 필드 하나만 채워집니다(TRADE_TRANSACTION_REQUEST):

  • type - 매매 거래 유형;

해당 트랜잭션에 대해 유형 필드(매매 거래 유형)만 분석해야 합니다. 추가 데이터에 대해 OnTradeTransaction 함수의 두 번째 및 세 번째 매개변수(요청 및 결과)를 분석해야 합니다.

예:

input int MagicNumber=1234567;
 
//--- CTrade 트레이딩 클래스를 사용하도록 설정하고 이 클래스의 변수를 선언
#include <Trade\Trade.mqh>
CTrade 거래;
//--- 보류 중인 주문 설치 및 삭제 플래그
bool pending_done=false;
bool pending_deleted=false;
//--- 보류 중인 주문 티켓이 여기에 저장됩니다
ulong order_ticket;
//+------------------------------------------------------------------+
//| 엑스퍼트 초기화 기능                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- MagicNumber를 설정하여 모든 주문을 표시
   trade.SetExpertMagicNumber(MagicNumber);
//--- 거래 요청은 OrderSendAsync() 함수를 사용하여 비동기 모드로 전송됩니다
   trade.SetAsyncMode(true);
//--- 변수를 0으로 초기화
   order_ticket=0;
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 엑스퍼트 틱 기능                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---보류 중인 주문 설치
   if(!pending_done)
     {
      double ask=SymbolInfoDouble(_Symbol,SYMBOL_ASK);
      double buy_stop_price=NormalizeDouble(ask+1000*_Point,(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS));
      bool res=trade.BuyStop(0.1,buy_stop_price,_Symbol);
      //--- BuyStop() 함수가 성공적으로 수행된 경우 
      if(res)
        {
         pending_done=true;
         //--- ctrade에서 요청의 결과를 수신합니다
         MqlTradeResult trade_result;
         trade.Result(trade_result);
         //--- 보낸 요청에 대한 request_id 가져오기
         uint request_id=trade_result.request_id;
         Print("보류 중인 주문을 설정하기 위한 요청이 전송되었습니다. Request_ID=",request_id);
         //--- 주문 티켓 저장 (CTrade로 보내는 비동기 모드를 사용하는 경우 0이 됨)
         order_ticket=trade_result.order;
         //--- 모두 완료됨, OnTick() 핸들러에서 조기 종료
         return;
        }
     }
//--- 보류 중인 주문 삭제
   if(!pending_deleted)
      //--- 추가 확인
      if(pending_done && (order_ticket!=0))
        {
         //--- 보류 중인 주문 삭제 시도
         bool res=trade.OrderDelete(order_ticket);
         Print("OrderDelete=",res);
         //--- 삭제 요청이 성공적으로 전송된 경우
         if(res)
           {
            pending_deleted=true;
            //--- 요청 실행 결과를 가져오기
            MqlTradeResult trade_result;
            trade.Result(trade_result);
            //--- 결과에서 요청 ID를 가져오기
            uint request_id=trade_result.request_id;
            //--- 저널에 표시
            Print("보류 중인 주문 # 삭제 요청이 전송되었습니다",order_ticket,
                  ". Request_ID=",request_id,
                  "\r\n");
            //--- 요청 결과에서 주문 티켓을 고치기
            order_ticket=trade_result.order;
           }
        }
//---        
  }
//+------------------------------------------------------------------+
//| TradeTransaction 기능                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- 열거 값으로 트랜잭션 유형 가져오기
   ENUM_TRADE_TRANSACTION_TYPE type=(ENUM_TRADE_TRANSACTION_TYPE)trans.type;
//--- 트랜잭션이 요청 처리 결과인 경우 트랜잭션 이름만 표시됩니다
   if(type==TRADE_TRANSACTION_REQUEST)
     {
      Print(EnumToString(type));
      //--- 처리된 요청 문자열 이름 표시
      Print("------------RequestDescription\r\n",RequestDescription(request));
      //--- 요청 결과 설명 표시
      Print("------------ResultDescription\r\n",TradeResultDescription(result));
      //--- 삭제 주문 티켓을 OnTick()의 다음 처리 시 보관
      if(result.order!=0)
        {
         //--- 다음 OnTick() 호출 시 이 주문을 티켓으로 삭제
         order_ticket=result.order;
         Print(" Pending order ticket ",order_ticket,"\r\n");
        }
     }
   else // 다른 유형의 트랜잭션에 대한 전체 설명 표시
//--- 수신된 트랜잭션에 대한 설명을 저널에 표시
      Print("------------TransactionDescription\r\n",TransactionDescription(trans));
 
//---     
  }
//+------------------------------------------------------------------+
//| 트랜잭션 텍스트 설명을 반환                          |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans)
  {
//--- 
   string desc=EnumToString(trans.type)+"\r\n";
   desc+="Symbol: "+trans.symbol+"\r\n";
   desc+="Deal ticket: "+(string)trans.deal+"\r\n";
   desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
   desc+="Order ticket: "+(string)trans.order+"\r\n";
   desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
   desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
   desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
   desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
   desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
   desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
   desc+="Position: "+(string)trans.position+"\r\n";
   desc+="Position by: "+(string)trans.position_by+"\r\n";
//--- 얻은 문자열을 반환
   return desc;
  }
//+------------------------------------------------------------------+
//| 거래 요청 텍스트 설명을 반환                    |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request)
  {
//---
   string desc=EnumToString(request.action)+"\r\n";
   desc+="Symbol: "+request.symbol+"\r\n";
   desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
   desc+="Order ticket: "+(string)request.order+"\r\n";
   desc+="Order type: "+EnumToString(request.type)+"\r\n";
   desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
   desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
   desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
   desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
   desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
   desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
   desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
   desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
   desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
   desc+="Comment: "+request.comment+"\r\n";
//--- 얻은 문자열을 반환
   return desc;
  }
//+------------------------------------------------------------------+
//| 요청 처리 결과의 텍스트 설명을 반환   |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result)
  {
//---
   string desc="Retcode "+(string)result.retcode+"\r\n";
   desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
   desc+="Order ticket: "+(string)result.order+"\r\n";
   desc+="Deal ticket: "+(string)result.deal+"\r\n";
   desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
   desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
   desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
   desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
   desc+="Comment: "+result.comment+"\r\n";
//--- 얻은 문자열을 반환
   return desc;
  }

추가 참조

매매 거래 유형, OnTradeTransaction()