
MQL5의 주문에 대한 이해
소개
모든 트레이딩 시스템에서 우리는 포지션 진입, 손절 및 이익실현, 주문 수정 등 주문과 그 운영을 처리해야 합니다. 따라서 MetaTrader5용 트레이딩 시스템을 만들 때 mql5에서 주문 작업을 처리하는 방법을 이해하는 것이 매우 중요합니다. 이 글의 목적은 대부분의 주문 및 포지션 작업에 대한 간단한 지침을 제공하여 이글의 주제에 대한 모든 것을 효과적으로 처리할 수 있도록 하는 것입니다. 이 글에서는 다음의 주제들을 다룹니다:
이 글이 MetaTrader5 트레이딩 시스템을 원활하게 구축하는 데 도움이 되길 바랍니다. 여러분은 이 글에서 다루는 모든 애플리케이션을 사용하기 전에 반드시 테스트하여 수익성이 있는지 또는 거래에 적합한지 확인해야 합니다. 이 글의 주된 목적은 주문, 거래 및 포지션 작업과 관련하여 두 가지 다른 방법을 사용하여 거래 시스템을 만드는 예제를 제공하는 것입니다.
주문, 포지션 및 거래 조건
이 부분에서는 주문을 효과적으로 처리하는 방법을 이해하는 데 도움이 되는 중요한 용어에 대해 설명합니다. MetaTrader 5에서 주문과 관련된 세 가지 용어의 차이점에 대해 알아 보겠습니다. 이러한 용어는 주문, 거래, 포지션이며 이들 모두 거래를 체결하기 위한 단계로 간주할 수 있습니다.
주문: 특정 랏 또는 수량으로 특정 가격에 매수 또는 매도 거래를 개시하라는 거래 서버에 접수된 요청입니다. 주문에는 마켓 주문과 펜딩 주문의 두 가지 유형이 있습니다.
- 마켓 주문: 현재 시장가로 즉시 체결될 수 있는 주문입니다.
- 펜딩 주문: 해당 호가 수준에서 거래를 체결할 가격과 거래 체결 시간에 대해 미리 정해진 조건에 따라 거래를 체결하는 주문입니다.
이러한 펜딩 주문은 다음 중 하나일 수 있습니다:
- 바이 스탑: 현재 시장가보다 높은 특정 가격에 펜딩 매수 주문을 넣습니다.
- 바이 리밋: 현재 시장의 가격보다 낮은 특정 가격에 바이 리밋 주문을 넣습니다.
- 셀 스탑: 현재 시장의 가격보다 낮은 특정 가격에 매도 펜딩 주문을 넣습니다.
- 셀 리밋: 현재 시장의 가격보다 높은 특정 가격에 매도 펜딩 주문을 넣습니다.
주문이 접수되면 마켓 주문이든 펜딩 주문이든 상관없이 MetaTrader 5의 도구 상자의 매매 탭에서 확인할 수 있습니다. 다음은 그 예입니다:
주문이 실행되지 않고 종료되거나 취소된 경우 도구 상자의 거래 내역 탭에서 해당 주문을 확인할 수 있습니다.
MQL5로 현재 포지션을 수정하려면 나중에 주문 수정을 처리할 때와 마찬가지로 주문을 처리해야 합니다.
거래: 거래 주문이 체결되거나 체결될 때의 결과입니다. 거래 실행에 따른 인/아웃 액션으로 찾을 수 있습니다. 한 랏의 매수 주문이 체결되었다고 가정해 보겠습니다. 그 후 포지션의 일부 0.5 랏을 청산한 다음 나머지 0.5 랏을 청산했습니다. 따라서 거래는 다음과 같습니다:
- 1 바이 인
- 0.5 셀 아웃
- 0.5 셀 아웃
MetaTrader 5 도구 상자의 거래 내역 탭에서 마우스 오른쪽 버튼으로 클릭하고 선택하여 이러한 거래를 찾을 수 있습니다.
포지션: 금융자산의 매수 또는 매도를 기준으로 한 매수 또는 매도 거래의 순차익입니다. 매매 탭에서 활성 거래로 표시되거나 포지션을 선택하면 거래 내역 탭에서 확인할 수 있습니다.
매수 주문의 체결 가격은 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
경고: 이 자료들에 대한 모든 권한은 MetaQuotes(MetaQuotes Ltd.)에 있습니다. 이 자료들의 전부 또는 일부에 대한 복제 및 재출력은 금지됩니다.
이 글은 사이트 사용자가 작성했으며 개인의 견해를 반영합니다. Metaquotes Ltd는 제시된 정보의 정확성 또는 설명 된 솔루션, 전략 또는 권장 사항의 사용으로 인한 결과에 대해 책임을 지지 않습니다.




안녕하세요,
좋은 글이었어요, 타이브.
작은 버그 1개를 발견했습니다:
TRADE_ACTION_SLTP 아래 상자에 요청.sl을 두 번 작성했는데, 두 번째 요청은 줄 끝의 주석에 표시된 대로 요청.tp여야 합니다.
감사합니다,
Gunther
안녕하세요,
친절한 의견에 감사드립니다. 맞습니다, 실수이며 검토하겠습니다.
감사합니다,
귀하의 코드를 사용하여 상품에 대한 간단한 주문을 작성하고 있습니다!
double price = 94500;
double stopLoss = 가격 - (500 * _Point);
더블 테이크프로핏 = 가격 + (1000 * _포인트);
울롱 티켓 = trade.OrderOpen(
"SiM4", // 기호
GetLastError() = 0을 반환하고 주문이 체결되지 않고 거래가 없습니다
브로커에서 주문할 때 특별한 액세스 토큰을 지정해야 하나요?
주문이 체결되지 않았고 트랜잭션이 없음
브로커에서 주문할 때 특별한 액세스 토큰을 지정해야 하나요?
안녕하세요 압델 마부드입니다,
이 튜토리얼을 작성해 주셔서 감사합니다.
이 튜토리얼은 주문 배치 만 제공합니다. 기사에 포지션 청산(이익실현 또는 손절매)에 대한 코드가 있나요?
감사합니다,
아마드 주니아르