English Русский 中文 Español Deutsch 日本語 Português Français Italiano Türkçe
Expert Advisor 작성시 MQL5 Standard Trade Class 라이브러리 사용

Expert Advisor 작성시 MQL5 Standard Trade Class 라이브러리 사용

MetaTrader 5트레이딩 시스템 | 5 7월 2021, 16:05
362 0
Samuel Olowoyo
Samuel Olowoyo

소개

새로운 MQL5 프로그램은 MQL5 Expert Advisors, Indicators 및 Scripts를 트레이더와 개발자가 가능한 한 쉽게 개발할 수 있도록 많은 내장 표준 클래스 라이브러리와 함께 제공됩니다.

이러한 클래스 라이브러리는 MetaTrader 5 클라이언트 터미널 폴더의 MQL5 폴더에있는 \Include\ 폴더에서 사용할 수 있습니다. 클래스 라이브러리는 배열, ChartObjects, 차트, 파일, 인디케이터, 스트링즈트레이드 클래스 등 다양한 범주로 나뉩니다.

이 글에서는 내장된 트레이트 클래스를 사용하여 Expert Advisor를 작성하는 방법을 자세히 설명합니다. Expert Advisor는 규정된 조건이 충족될 때 열린 포지션의 청산 및 수정을 포함하는 전략을 기반으로 합니다.

클래스가 무엇이며 어떻게 사용할 수 있는지 이미 알고 있다면 새로운 MQL5 언어가 제공해야 하는 또 다른 기회의 세계에 오신 것을 환영합니다.

반면에 MQL5를 완전히 처음 사용하는 경우; 초보자를위한 MQL5에서 Expert Advisor를 작성하기 위한 단계별 가이드, MQL5 객체 지향 프로그래밍 접근 방식을 사용하여 Expert Advisor 작성하기 또는 새로운 MQL5 언어에 대한 소개를 제공하는 기타 글을 먼저 읽어볼 것을 권장합니다. 필요한 지식을 제공하는 많은 이 이미 작성되어 있으니까요.


1. 트레이드 클래스

트레이드 클래스 폴더는 개인적인 용도로 EA를 개발하려는 트레이더나 Expert Advisors(EA)를 개발할 때 휠을 다시 발명할 필요가 없는 프로그래머를 위해 그들의 삶을 더 쉽게 만들어주고자 구성된 여러 클래스로 구성됩니다.

클래스를 사용할 때 클래스의 내부 작업(즉, 개발자가 수행하는 작업을 수행하는 방법)을 알 필요가 없습니다. 집중해야 하는 것은 클래스가 문제를 해결하는 데 사용됩니다. 이것이 빌트인 클래스 라이브러리를 사용하는 것이 그것을 사용하려는 모든 사람들에게 매우 쉽게 만드는 이유입니다. 이 글에서는 Expert Advisor 개발 과정에서 필요한 주요 클래스를 살펴 보겠습니다.

강의에 대해 논의할 때 강의의 내부 세부 사항에 신경 쓰지 않고 강의가 할 수 있는 일과 수익성이 높은 EA를 개발하는 데있어 우리의 사명을 달성하는 데 사용할 수있는 방법에 대해 자세히 논의 할 것입니다. 그것들을 차례로 논의합시다.

1.1 СAccountInfo 클래스

CAccountInfo 는 사용자가 모든 계정 속성 또는 현재 개설된 클라이언트 터미널에서 거래 계정 정보에 쉽게 액세스 할 수 있도록하는 클래스입니다.

더 잘 이해하기 위해 EA에서 사용할 수있는이 클래스의 주요 멤버 함수를 살펴 보겠습니다. 클래스를 사용하기 전에 먼저 해당 클래스의 개체를 만들어야 하므로 CAccountInfo 클래스를 사용하려면 클래스의 개체를 만들어야 합니다.

이름을 myaccount로 하겠습니다.

//--- The AccountInfo Class Object
CAccountInfo myaccount;

클래스의 객체를 생성하려면 클래스 이름 다음에 객체에 부여 할 이름을 사용해야 합니다.

이제 myaccount 개체를 사용하여 CAccountInfo 클래스의 공개 멤버 함수에 액세스 할 수 있습니다.

방법
기술
사용 예
myaccount.Login()

이 함수는 터미널에서 현재 개설 된 거래에 대한 계좌 번호를 얻고 싶을 때 사용됩니다.

// returns account number, example 7770
long accountno = myaccount.Login()
myaccount.TradeModeDescription()이 함수는 터미널에서 현재 활성화된 계정의 거래 모드에 대한 설명을 가져 오는 데 사용됩니다.
// returns Demo trading account, 
// or Real trading account or Contest trading account
string  acc_trading_mode = myaccount.TradeModeDescription();
myaccount.Leverage()

이 함수는 터미널에서 현재 활성화된 계정의 거래 모드에 대한 설명을 가져 오는 데 사용됩니다.

// returns leverage given to the active account
long acc_leverage = myaccount.Leverage(); 
myaccount.TradeAllowed() 

이 함수는 단말기의 활성 계좌에서 거래가 허용되는지 확인하는 데 사용됩니다. 거래가 허용되지 않으면 계좌는 거래 할 수 없습니다.

if (myaccount.TradeAllowed())
{
    // trade is allowed
}
else
{
  // trade is not allowed
}
myaccount.TradeExpert()이 함수는 Expert Advisors가 터미널에서 현재 활성화된 계좌로 거래를 할 수 있는지 확인하는 데 사용됩니다.
if (myaccount.TradeExpert())
{
   // Expert Advisor trade is allowed
}
else
{
   // Expert Advisor trade is not allowed
}
myaccount.Balance()이 함수는 터미널의 활성 계정에 대한 계정 잔액을 제공합니다.
// returns account balance in the deposit currency
double acс_balance =  myaccount.Balance(); 
myaccount.Profit() 

이 함수는 터미널에서 활성 계정의 현재 수익을 얻는 데 사용됩니다.

// returns account profit in deposit currency
double acс_profit =  myaccount.Profit();
myaccount.FreeMargin() 

이 함수는 터미널에서 활성 계정여유 마진을 얻는 데 사용됩니다.

// returns free margin for active account
double acс_free_margin = myaccount.FreeMargin();
myaccount.Currency()  

이 함수는 터미널에서 활성 계정의 입금 통화를 가져 오는 데 사용됩니다.

string acс_currency = myaccount.Currency();
myaccount.OrderProfitCheck(const string symbol, ENUM_ORDER_TYPE  trade_operation, double volume, double price_open, double price_close)이 함수는 전달된 매개 변수를 기반으로 평가된 수익을 가져옵니다. 입력 매개 변수는 심볼, 거래 운영 유형, 거래량 및 시가/종가입니다.
double op_profit=myaccount.OrderProfitCheck(_Symbol,ORDER_TYPE_BUY,
1.0,1.2950,1.3235);
Print("The amount of Profit for deal buy EURUSD",
      "at 1.2950 and sell at 1.3235 is: ",op_profit);
myaccount.MarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double  volume,double price)이 함수는 주문을 시작하는 데 필요한 마진을 얻는 데 사용됩니다. 이 함수에는 기호 (통화 쌍), 주문 유형, 거래할 랏 (또는 볼륨) 및 주문 가격의 네 가지 입력 매개 변수가 있습니다. 이 함수는 거래를 할 때 매우 중요합니다.
// depending on the type of position to open - in our case buy
double price=SymbolInfoDouble(_Symbol,SYMBOL_ASK); 
double margin_req=myaccount.MarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.FreeMarginCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double volume,double price)이 함수는 주문시 해당 활성 계정에 남아있는 여유 마진 금액을 가져 오는데 사용됩니다. 여기에는 기호 (통화 쌍), 주문 유형, 거래할 랏 (또는 볼륨) 및 주문 가격의 네 가지 입력 매개 변수가 있습니다.
double acс_fm=myaccount.FreeMarginCheck(_Symbol,ORDER_TYPE_BUY,LOT,price);
myaccount.MaxLotCheck(const string symbol,ENUM_ORDER_TYPE trade_operation,double price) 

이 함수는 터미널에서 활성 계정에 대한 주문을 할 수있는 최대 랏를 얻는데 사용됩니다. 기호, 주문 유형 및 주문 개시 가격의 세 가지 입력 매개 변수가 있습니다.

double max_lot=myaccount.MaxLotCheck(_Symbol,ORDER_TYPE_BUY,price);

1.2 СSymbolInfo 클래스

CSymbolInfo 클래스를 사용하면 사용자가 현재 심볼의 모든 속성에 빠르게 액세스 할 수 있습니다.

클래스를 사용하려면 클래스의 객체를 만들어야 합니다. 이 경우 mysymbol이라고 합니다.

// the CSymbolInfo Class object CSymbolInfo mysymbol;

 Expert Advisor를 작성하는 과정에서 사용될 수있는이 클래스의 대부분의 함수를 살펴 보겠습니다.

 방법 기술사용 예
mysymbol.Name(string  name)

이 함수는 클래스 객체의 심볼을 설정하는 데 사용됩니다. 기호 이름을 입력 매개 변수로 사용합니다.

// set the symbol name for our CSymbolInfo class Object
mysymbol.Name(_Symbol);
mysymbol.Refresh() 이 함수는 모든 심볼 데이터를 새로 고치는 데 사용됩니다. 클래스에 대한 새 심볼 이름을 설정할 때도 자동으로 호출됩니다.
mysymbol.Refresh();
mysmbol.RefreshRates()이 함수는 최신 시세 데이터를 확인하는 데 사용됩니다. 성공하면 true를, 실패하면 false를 반환합니다. 이것은 당신이 없이는 할 수 없는 유용한 함수입니다.
//--- Get the last price quote using the CSymbolInfo 
// class object function
   if (!mysymbol.RefreshRates())
   {
      // error getting latest price quotes 
   }
mysymbol.IsSynchronized()

이 함수는 단말기에 설정된 심볼의 현재 데이터가 서버의 데이터와 동기화되어 있는지 확인하는 함수입니다. 데이터가 동기화되면 true를 반환하고 그렇지 않으면 false 를 반환합니다.

// check if symbol data are synchronized with server
  if (!mysymbol.IsSynchronized())
   {
     // error! Symbol data aren't synchronized with server
   }
mysymbol.VolumeHigh() 

이 함수는 설정된 기호에 대한 하루의 최대 볼륨을 가져 오는데 사용됩니다.

long max_vol = mysymbol.VolumeHigh();
mysymbol.VolumeLow() 

이 함수는 설정된 심볼에 대한 하루의 최소 볼륨을 가져 오는데 사용됩니다.

long min_vol = mysymbol.VolumeLow();
mysymbol.Time() 

이 함수는 설정된 기호에 대한 마지막 가격 견적 시간을 가져 오는 데 사용됩니다.

datetime qtime = mysymbol.Time();
mysymbol.Spread()이 함수는 설정된 심볼에 대한 현재 스프레드 값 (포인트 단위)을 가져 오는데 사용됩니다.
int spread = mysymbol.Spread();
mysymbol.StopsLevel()이 함수는 설정된 심볼에 대해 손절매를 할 수있는 현재 종가의 최소 수준 (포인트)을 얻는 데 사용됩니다. Trailing Stop 또는 주문 /위치 수정 사용을 고려할 때 매우 유용한 함수입니다.
int stp_level = mysymbol.StopsLevel();
mysymbol.FreezeLevel()이 함수는 설정된 심볼에 대한 동결 거래 동작 거리 (포인트)를 구하는 데 사용됩니다.
int frz_level = mysymbol.FreezeLevel();
mysymbol.Bid()

이 함수는 설정된 심볼에 대한 현재 BID 가격을 가져 오는 데 사용됩니다.

double bid =  mysymbol.Bid();
mysymbol.BidHigh()이 함수는 하루의 최고/최고 입찰가를 가져 오는 데 사용됩니다.
double max_bid = mysymbol.BidHigh();
mysymbol.BidLow()이 함수는 설정된 심볼에 대한 일의 최소/최저 BID 가격을 가져 오는데 사용됩니다.
double min_bid = mysymbol.BidLow();
msymbol.Ask()이 함수는 설정된 심볼에 대한 현재 ASK 가격을 가져 오는 데 사용됩니다.
double ask = mysymbol.Ask();
mysymbol.AskHigh()이 함수는 설정된 심볼에 대한 하루의 최고/최고 ASK 가격을 가져 오는 데 사용됩니다.
double max_ask = mysymbol.AskHigh();
mysymbol.AskLow()이 함수는 하루의 최소/최저 ASK 가격을 가져 오는 데 사용됩니다.
double min_ask = mysymbol.AskLow();
mysymbol.CurrencyBase()이 함수는 설정된 기호의 기본 통화를 가져 오는데 사용됩니다.
// returns "USD" for USDJPY or USDCAD
string base_currency = mysymbol.CurrencyBase();
mysymbol.ContractSize()이 함수는 설정된 심볼을 거래하기 위해 계약 크기에 대한 금액을 가져 오는데 사용됩니다.
double cont_size =  mysymbol.ContractSize();
mysymbol.Digits() 이 함수는 설정된 기호의 소수점 이하 자릿수를 구하는 데 사용됩니다.
int s_digits = mysymbol.Digits();
mysymbol.Point() 이 함수는 설정된 심볼에 대해 1점 값을 가져 오는데 사용됩니다.
double s_point =  mysymbol.Point();
mysymbol.LotsMin()이 함수는 기호에 대한 거래를 성사시키는 데 필요한 최소 거래량을 얻는데 사용됩니다.
double min_lot =  mysymbol.LotsMin();
mysymbol.LotsMax()이 함수는 기호에 대한 거래를 성사시키는 데 필요한 최대 거래량을 얻는 데 사용됩니다.
double max_lot =  mysymbol.LotsMax();
mysymbol.LotsStep()이 함수는 기호에 대한 거래를 성사시키기 위해 볼륨 변경의 최소 단계를 얻는데 사용됩니다.
double lot_step = mysymbol.LotsStep();
mysymbol.NormalizePrice(double price) 이 함수는 설정된 기호의 올바른 숫자로 정규화 된 가격을 가져 오는 데 사용됩니다.
// A normalized current Ask price
double n_price = mysymbol.NormalizePrice(mysymbol.Ask()); 
mysymbol.Select() 이 함수는 시장 감시 창에서 심볼이 선택되었는지 확인하는 데 사용됩니다. symbol이 선택되면 true를 반환하고 그렇지 않으면 false를 반환합니다.
if (mysymbol.Select())
{
  //Symbol successfully selected
}
else
{
  // Symbol could not be selected
}
mysymbol.Select(bool select)이 함수는 Market watch 창에서 기호를 선택하거나 Market watch 창에서 기호를 제거하는데 사용됩니다. 차트가 이미 오픈 된 포지션을 가지고있을 때 차트가 오픈되었을 때 시장 감시 창에서 심볼을 제거하면 거짓이 반환된다는 점에 유의해야 합니다.
if (!mysymbol.Select())
{
   //Symbol not selected, Select the symbol
    mysymbol.Select(true);
}
else
{
 // Symbol already selected, 
 // remove Symbol from market watch window
    mysymbol.Select(false);
}
mysymbol.MarginInitial() 이 함수는 마진 통화로 1 랏의 볼륨으로 포지션을 오픈하는데 필요한 금액을 얻는데 사용됩니다.
double init_margin = mysymbol.MarginInitial() ; 
mysymbol.TradeMode()이 함수는 기호에 허용된 주문 실행 유형을 가져 오는데 사용됩니다.
if (mysymbol.TradeMode() == SYMBOL_TRADE_MODE_FULL)
{
 // Full trade allowed for this symbol,
 // no trade restrictions 
}
mysymbol.TradeModeDescription()이 함수는 기호에 허용된 주문 실행 유형의 설명을 가져 오는데 사용됩니다.
Print("The trade mode for this symbol is",
       mysymbol.TradeModeDescription());

1.3 The СHistoryOrderInfo Class

The CHistoryOrderInfo 는 주문 내역 속성을 매우 쉽게 처리 할 수 있는 또 다른 클래스입니다.

이 클래스의 객체를 생성하면 객체를 사용하여 즉각적인 문제를 해결하는데 필요한 중요한 공용 멤버 함수에 액세스 할 수 있습니다.

myhistory 클래스의 개체 이름을 지정하겠습니다. 

// The CHistoryOrderInfo Class object
CHistoryOrderInfo myhistory;

이 클래스의 몇 가지 주요 함수를 살펴 보겠습니다.

이 클래스를 사용하여 내역의 주문에 대한 세부 정보를 얻으려면 먼저 내역의 총 주문을 가져온 다음 주문 티켓을 클래스 개체 myhistory에 전달해야 합니다.

//Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))  // get all history orders
{
// Get total orders in history
int tot_hist_orders = HistoryOrdersTotal(); 

이제 사용 가능한 총 내역 주문을 반복하고 클래스 객체를 사용하여 각 내역 주문의 세부 정보를 가져옵니다.

ulong h_ticket; // Order ticket

for (int j=0; j<tot_hist_orders; j++)
{
  h_ticket = HistoryOrderGetTicket(j));

  if (h_ticket>0)
  {
    // First thing is to now set the order Ticket to work with by our class object 
방법
 기술사용 예
myhistory.Ticket(ulong 티켓)이 함수는 속성 또는 세부 정보를 얻으려는 주문 티켓을 선택하는데 사용됩니다.
myhistory.Ticket(h_ticket);
myhistory.Ticket() 이 함수는 주문에 대한 주문 티켓을 얻는 데 사용됩니다.
ulong o_ticket = myhistory.Ticket();
myhistory.TimeSetup()이 함수는 주문이 수행된 시간 또는 설정을 얻는데 사용됩니다.
datetime os_time = myhistory.TimeSetup();
myhistory.OrderType()이 함수는 주문 유형 (ORDER_TYPE_BUY 등)을 얻는 데 사용됩니다.
if (myhistory.OrderType() == ORDER_TYPE_BUY)
{
// This is a buy order
}
myhistory.State()이 함수는 주문의 현재 상태를 가져 오는데 사용됩니다.
주문이 취소, 수락, 거부 또는 접수 된 경우
if(myhistory.State() == ORDER_STATE_REJECTED)
{
// order was rejected, not placed.
}
myhistory.TimeDone()이 함수는 주문이 접수, 취소 또는 거부된 시간을 가져 오는데 사용됩니다.
datetime ot_done =  myhistory.TimeDone();
myhistory.Magic()이 함수는 주문을 시작한 Expert Advisor ID를 가져 오는데 사용됩니다.
long o_magic = myhistory.Magic();
myhistory.PositionId()이 함수는 주문시 포함된 포지션의 ID를 가져 오는데 사용됩니다.
long o_posid = myhistory.PositionId();
myhistory.PriceOpen()이 함수는 주문 개시 가격을 가져 오는데 사용됩니다.
double o_price =  myhistory.PriceOpen();
myhistory.Symbol()이 함수는 주문의 기호 속성 (통화 쌍)을 가져 오는데 사용됩니다.
string o_symbol =  myhistory.Symbol();
      

내역상 총 주문 루프 내에서 이러한 함수를 사용했다는 사실을 잊지 마십시오.

1.4 СOrderInfo 클래스

COrderInfo 는 모든 보류 주문 속성에 쉽게 액세스 할 수있는 클래스입니다. 이 클래스의 객체가 생성되면 이 클래스의 공용 멤버 함수에 사용할 수 있습니다.

이 클래스의 사용법은 위에서 설명한 CHistoryOrderInfo 클래스와 다소 유사합니다.

클래스의 객체를 만들어 보겠습니다. myorder라고 합니다.

// The OrderInfo Class object
COrderInfo myorder;

이 클래스를 사용하여 보류중인 주문의 세부 정보를 얻으려면 먼저 사용 가능한 총 주문을 가져온 다음 주문 티켓으로 선택해야 합니다.

// Select all history orders within a time period
if (HistorySelect(0,TimeCurrent()))   // get all history orders
   {    
     // get total orders
     int o_total = OrdersTotal();

총 주문을 반복하고 생성한 객체를 사용하여 해당 속성을 얻습니다.

for (int j=0; j<o_total; j++)
{
 // we must confirm if the order is available for us to get its details using the Select function of the COrderInfo Class
방법
기술
사용 예
myorder.Select(ulong ticket) 이 함수는 주문을 쉽게 조작할 수 있도록 티켓 번호로 주문을 선택하는 데 사용됩니다.
if (myorder.Select(OrderGetTicket(j)) 
   { // order has been selected and can now be manipulated.
   }
myorder.Ticket() 이 함수는 선택한 주문에 대한 주문 티켓을 가져 오는데 사용됩니다.
ulong o_ticket = myorder.Ticket();
myorder.TimeSetup()이 함수는 이 주문이 설정된 시간을 가져 오는데 사용됩니다.
datetime o_setup = myorder.TimeSetup();
myorder.Type()이 함수는 ORDER_TYPE_BUY_STOP 등과 같은 주문 유형을 가져 오는데 사용됩니다.
if (myorder.Type() == ORDER_TYPE_BUY_LIMIT)
{
// This is a Buy Limit order, etc
}
myorder.State()이 함수는 주문 상태를 가져 오는데 사용됩니다.
주문이 취소, 수락, 거부 또는 접수 된 경우
if (myorder.State() ==ORDER_STATE_STARTED)
{
// order has been checked 
// and may soon be treated by the broker
}
myorder.TimeDone()이 함수는 주문이 접수, 거부 또는 취소 된 시간을 가져 오는데 사용됩니다.
datetime ot_done = myorder.TimeDone();
myorder.Magic()이 함수는 주문을 시작한 Expert Advisor의 ID를 가져 오는데 사용됩니다.
long o_magic =  myorder.Magic();
myorder.PositionId()이 함수는 주문시 포함된 포지션의 ID를 얻는데 사용됩니다.
long o_posid = myorder.PositionId();
myorder.PriceOpen()이 함수는 주문의 시가를 가져 오는데 사용됩니다.
double o_price = myorder.PriceOpen();
myorder.손절매()이 함수는 주문의 Stop 손실을 얻는데 사용됩니다.
double  s_loss = myorder.StopLoss();
myorder.이익 실현()이 함수는 주문의 이익을 얻는데 사용됩니다.
double t_profit = myorder.TakeProfit();
myorder.PriceCurrent()이 함수는 주문한 심볼의 현재 가격을 가져 오는데 사용됩니다.
double cur_price =  myorder.PriceCurrent();
myorder.Symbol()이 함수는 주문한 기호의 이름을 가져 오는데 사용됩니다.
string o_symbol = myorder.Symbol();
myorder.StoreState()이 함수는 주문의 현재 세부 정보를 저장하거나 저장하는데 사용되므로 나중에 변경된 사항이 있는지 비교할 수 있습니다.
myorder.StoreState();
myorder.CheckState()이 함수는 저장 또는 저장된 주문의 세부 사항이 변경되었는지 확인하는데 사용됩니다.
if (myorder.CheckState() == true)
{
// Our order status or details have changed
}


1.5 CDealInfo 클래스

CDealInfo 클래스는 거래 속성 또는 정보의 모든 내역에 대한 액세스를 제공합니다. 이 클래스의 개체를 만든 후에는 CHistoryOrderInfo 클래스와 유사한 방식으로 이 개체를 사용하여 내역의 거래에 대한 모든 정보를 가져옵니다.

따라서 가장 먼저 할 일은이 클래스의 객체를 만들고 이름을 mydeal으로 지정하는 것입니다.

// The DealInfo Class object
CDealInfo myinfo; 

우리는 내역상 총 거래를 얻는 것으로 시작합니다

if (HistorySelect(0,TimeCurrent()))
   {    
    // Get total deals in history
    int tot_deals = HistoryDealsTotal(); 

이제 사용 가능한 총 내역 주문을 반복하고 클래스 객체를 사용하여 각 내역 주문의 세부 정보를 가져옵니다.

ulong d_ticket; // deal ticket
for (int j=0; j<tot_deals; j++)
    {
     d_ticket = HistoryDealGetTicket(j);
     if (d_ticket>0)  
     {
      // First thing is to now set the deal Ticket to work with by our class object 
방법
기술사용 예
mydeal.Ticket(ulong ticket)이 함수는 우리가 생성한 객체에서 나중에 사용할 거래 티켓을 설정하는데 사용됩니다.
mydeal.Ticket(d_ticket);
mydeal.Ticket() 이 함수는 거래 티켓을 얻는데 사용됩니다.
ulong deal_ticket = mydeal.Ticket();
mydeal.Order()이 함수는 거래가 실행된 주문에 대한 주문 티켓을 가져 오는데 사용됩니다.
long deal_order_no =  mydeal.Order();
mydeal.Time() 이 함수는 거래가 실행된 시간을 가져 오는데 사용됩니다
datetime d_time = mydeal.Time();
mydeal.Type()이 함수는 DEAL_TYPE_SELL 등 거래 유형을 가져 오는데 사용됩니다.
if (mydeal.Type() == DEAL_TYPE_BUY)
{
// This deal was executed as a buy deal type
}
mydeal.Entry()  이 함수는 DEAL_ENTRY_IN 또는 DEAL_ENTRY_OUT 등 거래의 방향을 얻는 데 사용됩니다.
if (mydeal.Entry() == DEAL_ENTRY_IN)
{
// This was an IN entry deal
}
mydeal.Magic()  이 함수는 거래를 실행한 Expert Advisor의 ID를 얻는데 사용됩니다.
long d_magic = mydeal.Magic();
mydeal.PositionId() 이 함수는 거래가 속한 포지션에 대한 고유한 포지션 식별자를 가져 오는데 사용됩니다.
long d_post_id = mydeal.PositionId();
mydeal.Price() 이 함수는 거래가 실행된 가격을 가져 오는데 사용됩니다.
double d_price = mydeal.Price();
mydeal.Volume() 이 함수는 거래량 (랏)을 가져 오는데 사용됩니다.
double d_vol = mydeal.Volume();
mydeal.Symbol() 이 함수는 거래가 실행된 기호 (통화 쌍)를 얻는데 사용됩니다.
string d_symbol = mydeal.Symbol();


1.6 CPositionInfo 클래스

The CPositionInfo 클래스는 현재 포지션 속성에 쉽게 액세스 할 수 있도록합니다. 위치 속성을 가져 오는데 사용할 수 있도록 이 클래스의 개체를 만들어야 합니다.

이 클래스의 객체를 만들고 myposition이라고 합니다.

// The object of the CPositionInfo class
CPositionInfo myposition;

이제 이 개체를 사용하여 오픈 포지션 세부 정보를 가져옵니다. 사용 가능한 총 오픈 포지션을 확보하는 것으로 시작합니다.

int pos_total = PositionsTotal();

이제 세부 사항을 파악하기 위해 모든 오픈 포지션을 살펴볼 때입니다.

for (int j=0; j<pos_total; j++)
    {
방법
 기술사용 예
myposition.선택(const string symbol)이 함수는 작업할 수 있도록 현재 열린 포지션에 해당하는 기호를 선택하는데 사용됩니다.
if (myposition.Select(PositionGetSymbol(j)))
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
OR
// when dealing with the current symbol/chart only
if (myposition.Select(_Symbol)) 
{
 // symbol successfully selected, we can now work 
 // on the current open position for this symbol 
}
myposition.Time()이 함수는 포지션이 열린 시간을 가져 오는데 사용됩니다.
datetime pos_time = myposition.Time();
myposition.Type() 이 함수는 열린 포지션 유형을 가져 오는데 사용됩니다.
if (myposition.Type() == POSITION_TYPE_BUY)
{
// This is a buy position
}
myposition.Magic()이 함수는 포지션을 오픈한 Expert Advisor의 아이디를 획득하는데 사용됩니다.
long pos_magic = myposition.Magic();
myposition.Volume()이 함수는 열린 포지션의 볼륨(랏)을 가져 오는데 사용됩니다.
double pos_vol = myposition.Volume(); // Lots
myposition.PriceOpen()이 함수는 포지션이 오픈된 가격, 즉 포지션 오픈 가격을 가져 오는데 사용됩니다.
double pos_op_price = myposition.PriceOpen();
myposition.손절매()이 함수는 오픈 포지션에 대한 손절매 가격을 얻는데 사용됩니다.
double pos_stoploss = myposition.StopLoss();
myposition.이익 실현()이 함수는 오픈 포지션에 대한 이익 실현 가격을 얻는데 사용됩니다.
double pos_takeprofit = myposition.TakeProfit();
myposition.StoreState()이 함수는 포지션의 현재 상태를 저장하는데 사용됩니다.
// stores the current state of the position
myposition.StoreState();
myposition.CheckState()이 함수는 오픈 포지션의 상태가 변경되었는지 확인하는데 사용됩니다.
if (!myposition.CheckState())
{
  // position status has not changed yet
}
 myposition.Symbol()이 함수는 포지션이 열린 심볼의 이름을 가져 오는데 사용됩니다.
string pos_symbol = myposition.Symbol();


1.7 СTrade 클래스

CTrade 클래스는 MQL5의 거래 작업에 대한 쉬운 액세스를 제공합니다. 이 클래스를 사용하려면 클래스의 객체를 생성한 다음 필요한 거래 작업을 수행하는데 사용해야 합니다.

이 클래스의 객체를 만들고 이름을 mytrade:로 지정합니다.

//An object of the CTrade class
CTrade mytrade;

첫 번째 단계는 개체가 거래 작업을 수행하는데 사용할 대부분의 매개 변수를 설정하는 것입니다.

 방법기술
사용 예
mytrade.SetExpertMagicNumber(ulong magic)이 함수는 클래스가 거래 작업에 사용할 전문가 ID (매직 넘버)를 설정하는 데 사용됩니다.
ulong Magic_No=12345;
mytrade.SetExpertMagicNumber(Magic_No);
mytrade.SetDeviationInPoints(ulong deviation)이 함수는 거래를 할 때 사용할 편차 값 (포인트 단위)을 설정하는데도 사용됩니다.
ulong Deviation=20;
mytrade.SetDeviationInPoints(Deviation); 
mytrade.OrderOpen(const string symbol,
ENUM_ORDER_TYPE
order_type,double volume,

double
limit_price,double price,double sl,
double
tp,ENUM_ORDER_TYPE_TIME type_time,

datetime
expiration,const 문자열 comment="")
이 함수는 보류 주문을 하는데 사용됩니다. 이 함수를 사용하려면 먼저 매개 변수를 준비한 다음 이 함수에 전달해야 합니다.
// define the input parameters
double Lots = 0.1;
double SL = 0;
double TP = 0;
// latest Bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid()-_Point*550;
// place (BuyStop) pending order
mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELLSTOP,Lots,0.0,Oprice,
                  SL,TP,ORDER_TIME_GTC,0);
mytrade.OrderModify(ulong ticket,double price,
double
sl,double tp,
ENUM_ORDER_TYPE_TIME type_time,datetime expiration)
이 함수는 기존 보류 주문을 수정하는데 사용됩니다.
// Select total orders in history and get total pending orders 
// (as shown within the COrderInfo class section). 
// Use the CSymbolInfo class object to get the current ASK/BID price
int Stoploss = 400;
int Takeprofit = 550;
for(int j=0; j<OrdersTotal(); j++)
{
  ulong o_ticket = OrderGetTicket(j);
  if(o_ticket != 0)
  {
   // Stoploss must have been defined
   double SL = mysymbol.Bid() + Stoploss*_Point;   
   // Takeprofit must have been defined  
   double TP = mysymbol.Bid() - Takeprofit*_Point; 
   // lastest ask price using CSymbolInfo class object
   double Oprice = mysymbol.Bid();                 
   // modify pending BuyStop order
   mytrade.OrderModify(o_ticket,Oprice,SL,TP,ORDER_TIME_GTC,0);
  }
}
mytrade.OrderDelete(ulong ticket)이 함수는 보류 주문을 삭제하는 데 사용됩니다.
// Select total orders in history and get total pending orders
// (as shown within the COrderInfo class section). 

int o_total=OrdersTotal();
for(int j=o_total-1; j>=0; j--)
{
   ulong o_ticket = OrderGetTicket(j);
   if(o_ticket != 0)
   {
    // delete the pending Sell Stop order
    mytrade.OrderDelete(o_ticket);
   }
}
mytrade.PositionOpen(const  string symbol,ENUM_ORDER_TYPE order_type,double volume,double price,double sl,double tp,const string comment="")이 함수는 매수 또는 매도 포지션을 열기 위해 사용됩니다. 이 함수를 사용하려면 먼저 모든 필수 매개 변수를 준비한 다음이 함수에 전달해야 합니다.
// define the input parameters and use the CSymbolInfo class
// object to get the current ASK/BID price
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point;   
//Takeprofit must have been defined 
double TP = mysymbol.Ask() + Takeprofit*_Point; 
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lots,
                     Oprice,SL,TP,"Test Buy");
mytrade.PositionModify(const string symbol,
double
sl,double tp)
이 함수는 기존 오픈 포지션에 대한 손절매 및/또는 이익 실현을 수정하는데 사용됩니다. 이 함수를 사용하려면 먼저 CPositionInfo 클래스 개체를 사용하여 수정할 포지션을 선택하고 CSymbolInfo 클래스 개체를 사용하여 현재 BID/ASK 가격을 가져와야 합니다.
if (myposition.Select(_Symbol))
{
  int newStoploss = 250;
  int newTakeprofit = 500;
  double SL = mysymbol.Ask() – newStoploss*_Point;    
  double TP = mysymbol.Ask() + newTakeprofit*_Point;  
  //modify the open position for this symbol
 mytrade.PositionModify(_Symbol,SL,TP);
}
mytrade.PositionClose(const string symbol,
ulong
deviation=ULONG_MAX)
이 함수는 기존 오픈 포지션을 닫는데 사용됩니다.
if (myposition.Select(_Symbol))
{
 //close the open position for this symbol
 mytrade.PositionClose(_Symbol);  
}
mytrade.Buy(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="")   이 함수는 매수 거래를 시작하는데 사용됩니다. 이 함수를 사용할 때 거래할 볼륨 (또는 랏)을 설정하는 것이 좋습니다. tp (이익 실현) 및 sl (손절매)는 나중에 오픈 포지션을 수정하여 설정할 수 있지만 현재 매도 가를 사용합니다. 거래를 시작합니다.
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Ask() – Stoploss*_Point; 
//Takeprofit must have been defined
double TP = mysymbol.Ask() +Takeprofit*_Point;
// latest ask price using CSymbolInfo class object
double Oprice = mysymbol.Ask();
// open a buy trade
mytrade.Buy(Lots,NULL,Oprice,SL,TP,“Buy Trade”);

//OR
mytrade.Buy(Lots,NULL,0.0,0.0,0.0,“Buy Trade”);
// modify position later
mytrade.Sell(double volume,const string symbol=NULL,double price=0.0,double sl=0.0,double tp=0.0,const string comment="") 이 함수는 매도 거래를 시작하는데 사용됩니다. 이 함수를 사용할 때 거래 할 볼륨 (또는 랏)을 설정하는 것이 좋습니다. tp (이익 실현) 및 sl (손절매)는 나중에 개설된 포지션을 수정하여 설정할 수 있지만 현재 입찰 가격을 사용합니다. 거래를 시작합니다. 
double Lots = 0.1;
// Stoploss must have been defined 
double SL = mysymbol.Bid() + Stoploss*_Point;
//Takeprofit must have been defined
double TP = mysymbol.Bid() - Takeprofit*_Point; 
// latest bid price using CSymbolInfo class object
double Oprice = mysymbol.Bid();
// open a Sell trade
mytrade.Sell(Lots,NULL,Oprice,SL,TP,“Sell Trade”); 

//OR
mytrade.Sell(Lots,NULL,0.0,0.0,0.0,“Sell Trade”); 
//(modify position later)
mytrade.BuyStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0,
ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")
 이 함수는 BuyStop 보류 주문을 하는데 사용됩니다. 기본 주문 유형 시간은 ORDER_TIME_GTC이고 만료 시간은 0입니다. 동일한 주문 유형 시간을 염두에 두고 있다면 이 두 변수를 지정할 필요가 없습니다.
double Lot = 0.1;
//Buy price = bar 1 High + 2 pip + spread
 int sprd=mysymbol.Spread();
 double bprice =mrate[1].high + 2*_Point + sprd*_Point;
//--- Buy price
 double mprice=NormalizeDouble(bprice,_Digits); 
//--- Stop Loss
 double stloss = NormalizeDouble(bprice - STP*_Point,_Digits);
//--- Take Profit
 double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits);
//--- open BuyStop order
 mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit); 
mytrade.SellStop(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string  comment="") 이 함수는 설정된 매개 변수로 SellStop 보류 주문을 하는데 사용됩니다. 기본 주문 유형 시간은 ORDER_TIME_GTC이고 만료 시간은 0입니다. 동일한 주문 유형 시간을 염두에 두고 있다면 이 두 변수를 지정할 필요가 없습니다. 
double Lot = 0.1;
//--- Sell price = bar 1 Low - 2 pip 
//--- MqlRates mrate already declared
 double sprice=mrate[1].low-2*_Point;
//--- SellStop price
 double slprice=NormalizeDouble(sprice,_Digits);
//--- Stop Loss
 double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);
//--- Take Profit
 double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits);
//--- Open SellStop Order
 mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit);
mytrade.BuyLimit(double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string  comment="") 이 함수는 설정된 매개 변수로 BuyLimit 주문을 하는데 사용됩니다. 
Usage:
//--- Buy price = bar 1 Open  - 5 pip + spread
double Lot = 0.1;
int sprd=mysymbol.Spread();
//--- symbol spread
double bprice = mrate[1].open - 5*_Point + sprd*_Point;
//--- MqlRates mrate already declared
double mprice=NormalizeDouble(bprice,_Digits);
//--- BuyLimit price
//--- place buyLimit order, modify stoploss and takeprofit later
mytrade.BuyLimit(Lot,mprice,_Symbol); 
mytrade.SellLimit (double volume,double price,const string symbol=NULL,double sl=0.0,double tp=0.0, ENUM_ORDER_TYPE_TIME type_time=ORDER_TIME_GTC,datetime expiration=0,const string comment="")이 함수는 설정된 매개 변수로 매도 제한 주문을하는 데 사용됩니다. 
//--- Sell Limit price = bar 1 Open  + 5 pip
double Lot = 0.1;
//--- MqlRates mrate already declared
double sprice = mrate[1].open + 5*_Point;
//--- SellLimit
double slprice=NormalizeDouble(sprice,_Digits);
//place SellLimit order, modify stoploss and takeprofit later
mytrade.SellLimit(Lot,slprice,_Symbol);

   무역 결과 함수

  
mytrade.ResultRetcode()이 함수는 거래 작업에 대한 결과 코드를 가져 오는데 사용됩니다.
// a trade operation has just been carried out
int return_code = mytrade.ResultRetcode();
mytrade.ResultRetcodeDescription()이 함수는 거래 작업의 반환된 코드에 대한 전체 설명 또는 해석을 가져 오는데 사용됩니다.
string ret_message =  ResultRetcodeDescription();
// display it
Alert("Error code - " , mytrade.ResultRetcode() ,
      "Error message - ", ret_message);
mytrade.ResultDeal()오픈 포지션에 대한 딜 티켓을 가져 오는 함수입니다.
long dl_ticket = mytrade.ResultDeal();
mytrade.ResultOrder()이 함수는 오픈 포지션에 대한 주문 티켓을 얻는데 사용됩니다.
long o_ticket = mytrade.ResultOrder();
mytrade.ResultVolume()이 함수는 열린 포지션에 대한 주문량 (랏)을 가져 오는 데 사용됩니다.
double o_volume = mytrade.ResultVolume();
mytrade.ResultPrice()이 함수는 오픈 포지션에 대한 거래 가격을 가져 오는데 사용됩니다.
double r_price = mytrade.ResultPrice();
mytrade.ResultBid()이 함수는 현재 시장 BID 가격 (재호가 가격)을 가져 오는 데 사용됩니다.
double rq_bid = mytrade.ResultBid;
mytrade.ResultAsk()이 함수는 현재 시장 ASK 가격 (재호가 가격)을 가져 오는 데 사용됩니다.
double rq_ask = mytrade.ResultAsk;
mytrade.PrintRequest() / mytrade.PrintResult() 이 두 함수를 사용하여 저널 탭, 거래 요청 매개 변수 및 결과 매개 변수를 각각 인쇄할 수 있습니다.
// after a trade operation
// prints the trade request parameters
mytrade.PrintRequest(); 
//prints the trade results
mytrade.PrintResult();  

 무역 요청 함수

  
 mytrade.RequestAction()이 함수는 방금 전송된 마지막 거래 요청에 대한 거래 작업 유형을 가져 오는데 사용됩니다.
//determine the Trade operation type for the last Trade request
if (mytrade.RequestAction() == TRADE_ACTION_DEAL)
{
  // this is a market order for an immediate execution
}
else if (mytrade.RequestAction() == TRADE_ACTION_PENDING)
{
  // this is a pending order.
}  
 mytrade.RequestMagic()이 함수는 마지막 요청에서 사용된 Expert Magic 번호를 얻기 위해 사용됩니다.
ulong mag_no = mytrade. RequestMagic();
 mytrade.RequestOrder()
 이 함수는 마지막 요청에 사용된 주문 티켓을 가져 오는데 사용됩니다. 이것은 주로 보류 주문 수정과 관련이 있습니다.
ulong po_ticket =  mytrade.RequestOrder();
mytrade.RequestSymbol()이 함수는 마지막 요청에서 사용된 기호 또는 통화 쌍을 가져 오는데 사용됩니다.
string symb = mytrade.RequestSymbol(); 
mytrade.RequestVolume()이 함수는 마지막 요청에서 배치된 거래량 (랏)을 가져 오는데 사용됩니다. 
double Lot = mytrade.RequestVolume();  
mytrade.RequestPrice()이 함수는 마지막 요청에서 사용된 주문 가격 을 가져 오는데 사용됩니다.
double oprice = mytrade.RequestPrice();   
mytrade.RequestStopLimit()이 함수는 마지막 요청에서 손절매 사용된 가격 을 가져 오는데 사용됩니다.
double limitprice = mytrade.RequestStopLimit(); 
mytrade.RequestSL()이 함수는 마지막 요청에서 손절매 사용된 가격 을 가져 오는데 사용됩니다.
double sloss = mytrade.RequestSL();  
mytrade.RequestTP()이 함수는 마지막 요청에서 사용된 이익 실현 가격을 가져 오는데 사용됩니다.
double tprofit = mytrade.RequestTP();   
mytrade.RequestDeviation()이 함수는 마지막 요청에서 사용된 편차 를 가져 오는데 사용됩니다.
ulong dev = mytrade.RequestDeviation();  
mytrade.RequestType()이 함수는 마지막 요청에서 접수된 주문 유형을 가져 오는데 사용됩니다.
if (mytrade.RequestType() == ORDER_TYPE_BUY)
 {
  // market order Buy was placed in the last request.
mytrade.RequestTypeDescription()이 함수는 마지막 요청에서 접수된 주문 유형의 설명을 가져 오는데 사용됩니다.
Print("The type of order placed in the last request is :",
      mytrade.RequestTypeDescription());  
mytrade.RequestActionDescription()이 함수는 마지막 요청에서 사용된 요청 작업에 대한 설명을 가져 오는데 사용됩니다.
Print("The request action used in the last request is :", 
      mytrade.RequestTypeDescription());
mytrade.RequestTypeFillingDescription()이 함수는 마지막 요청에서 사용한 주문 체결 정책 유형을 가져 오는데 사용됩니다.
Print("The type of order filling policy used",
      " in the last request is :",
      RequestTypeFillingDescription()); 
 

트레이드 클래스 요청 (Trade Class Request) 함수는 주문과 관련된 오류를 식별할 때 매우 유용합니다. 주문할 때 오류 메시지가 표시되는 경우가 있으며 무엇이 잘못되었는지 즉시 확인할 수 없는 경우 약간 혼란스러워집니다. 트레이드 클래스 요청 함수를 사용하면 거래 서버로 전송된 일부 요청 매개 변수를 인쇄하여 우리가 잘못한 것을 식별할 수 있습니다. 이러한 사용법의 예는 아래 코드와 유사합니다.

//--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           { //--- Request is completed or order placed           
             Alert("A Buy order at price:", mytrade.ResultPrice() , ", vol:",mytrade.ResultVolume(),
                  " has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
            mytrade.PrintResult();
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), ", sl:", mytrade.RequestSL(),
                 ", tp:",mytrade.RequestTP(), ", price:", mytrade.RequestPrice(),
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
            mytrade.PrintRequest();
            return;
           }

위의 코드에서 오류가 발생한 경우 요청에 전송된 일부 매개 변수를 식별할 수 있도록 시도했습니다. 예를 들어 올바른 손절매 가격을 지정하지 않은 경우 잘못된 중지 오류가 발생할 수 있으며 mytrade.RequestSL()을 사용하여 손절매 값을 인쇄하면 다음 작업을 수행 할 수 있습니다. 지정된 손절매 가격에 문제가 무엇인지 알 수 있습니다.

각 클래스를 사용하는 방법을 보여주기 위해 시간을 들였으므로 이제 우리가 설명한 함수 중 일부를 실행해볼 차례입니다.

Expert Advisor에서 사용할 모든 함수는 이미 위에 설명되어 있습니다. 작성하려는 코드의 함수 중 하나를 본 후에는 항상 설명을 참조하는 것이 좋습니다. 


2. 트레이드 클래스의 함수 사용

이러한 무역 클래스의 함수를 사용하는 방법을 보여주기 위해 다음 작업을 수행 할 Expert Advisor를 작성합니다.

  • 매수 또는 매도 조건을 확인하고 조건이 충족되면 충족된 조건에 따라 매수 또는 매도 주문을 합니다.
  • 포지션이 열리고 거래가 계속해서 우리 방향으로 진행된다면, 우리는 포지션의 이익 실현 또는 손절매를 수정할 것입니다. 그러나 거래가 우리에게 불리하고 우리의 이익 목표가 달성되지 않은 경우 우리는 포지션을 닫을 것입니다.
  • 당사의 EA는 GBPUSD, AUDUSD, EURUSD 등의 통화로 일일 차트에서 거래하는 데 사용됩니다.

2.1 Expert Advisor 작성

시작하려면 새 MQL5 문서를 시작하고 Expert Advisor(템플릿)를 선택하고 다음 버튼을 클릭합니다.

 새 MQL5 문서 시작


그림 1. 새 MQL5 문서 시작

Expert Advisor의 이름을 입력하고 Finish 버튼을 클릭합니다. 나중에 입력 매개 변수를 수동으로 정의합니다.

새 문서에 이름 지정

그림 2. Expert Advisor 이름 지정

생성된 새 문서는 아래와 유사합니다.

전문가 코드 골격

#property 버전 줄 바로 뒤에 사용할 Trade 클래스를 모두 포함합니다.

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The AccountInfo Class
#include <Trade\AccountInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>

다음으로 입력 매개 변수를 정의합니다.

//+------------------------------------------------------------------+
//|  INPUT PARAMETERS                                              |
//+------------------------------------------------------------------+
input int      StopLoss=100;     // Stop Loss
input int      TakeProfit=240;   // Take Profit
input int      ADX_Period=15;    // ADX Period
input int      MA_Period=15;     // Moving Average Period
input ulong    EA_Magic=99977;   // EA Magic Number
input double   Adx_Min=24.0;     // Minimum ADX Value
input double   Lot=0.1;          // Lots to Trade
input ulong    dev=100;          // Deviation 
input long     Trail_point=32;   // Points to increase TP/SL
input int      Min_Bars = 20;    // Minimum bars required for Expert Advisor to trade
input double   TradePct = 25;    // Percentage of Account Free Margin to trade

이 Expert Advisor 코드에서 사용할 다른 매개 변수도 지정합니다.

//+------------------------------------------------------------------+
//|  OTHER USEFUL PARAMETERS                                         |
//+------------------------------------------------------------------+
int adxHandle;                     // handle for our ADX indicator
int maHandle;                    // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values of +DI, -DI and ADX values for each bars
double maVal[];                  // Dynamic array to hold the values of Moving Average for each bars
double p_close;                    // Variable to store the close value of a bar
int STP, TKP;                   // To be used for Stop Loss, Take Profit 
double TPC;                        // To be used for Trade percent

이제 포함된 각 클래스의 객체를 생성해 보겠습니다.

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The Trade Class Object
CTrade mytrade;
//--- The PositionInfo Class Object
CPositionInfo myposition;
//--- The AccountInfo Class Object
CAccountInfo myaccount;
//--- The SymbolInfo Class Object
CSymbolInfo mysymbol;

다음으로 할 일은 작업을 매우 쉽게 만드는 데 사용할 몇 가지 함수를 정의하는 것입니다.

이러한 함수를 정의한 후에는 OnInit()OnTick() 함수의 필요한 섹션 내에서 해당 함수를 호출합니다.

2.1.1 checkTrading 함수

이 함수는 Expert Advisor가 거래 할 수 있는지 여부를 확인하기 위해 모든 초기 확인을 수행하는 데 사용됩니다. 이 함수가 true를 반환하면 EA는 계속 진행하고, 그렇지 않으면 EA는 어떠한 거래도 수행하지 않습니다.

//+------------------------------------------------------------------+
//|  Checks if our Expert Advisor can go ahead and perform trading   |
//+------------------------------------------------------------------+
bool checkTrading()
{
  bool can_trade = false;
  // check if terminal is syncronized with server, etc
  if (myaccount.TradeAllowed() && myaccount.TradeExpert() && mysymbol.IsSynchronized())
  {
    // do we have enough bars?
    int mbars = Bars(_Symbol,_Period);
    if(mbars >Min_Bars)
    {
      can_trade = true;
    }
  }
  return(can_trade);
}

bool 데이터 유형 can_trade 을 선언하고 false로 설정했습니다. CAccountInfo 클래스의 객체를 사용하여 거래가 허용되는지, 그리고 Expert Advisors가 이 계정에서 거래가 허용되는지 확인했습니다. 또한 CSymbolInfo 클래스의 객체를 사용하여 터미널이 거래 서버와 동기화되었는지 확인합니다.

이 세 가지 조건이 충족되면 현재 바의 총 수가 EA가 거래하는 데 필요한 최소 바보다 큰지 확인합니다. 이 함수가 true를 반환하면 EA는 거래 활동을 수행하고 그렇지 않으면, 이 함수의 조건이 충족될 때까지 어떠한 거래 활동에도 참여하지 않습니다.

보시다시피 표준 트레이드 클래스 라이브러리의 필수 개체를 사용하여 필요한 모든 트레이드 체크 활동을 이 함수에 포함하기로 결정했습니다.

2.1.2 ConfirmMargin 함수

//+------------------------------------------------------------------+
//|  Confirms if margin is enough to open an order
//+------------------------------------------------------------------+
bool ConfirmMargin(ENUM_ORDER_TYPE otype,double price)
  {
   bool confirm = false;
   double lot_price = myaccount.MarginCheck(_Symbol,otype,Lot,price); // Lot price/ Margin    
   double act_f_mag = myaccount.FreeMargin();                        // Account free margin 
   // Check if margin required is okay based on setting
   if(MathFloor(act_f_mag*TPC)>MathFloor(lot_price))
     {
      confirm =true;
     }
    return(confirm);
  }

우리는 CAccountInfo 클래스의 객체를 사용하여 주문을 하기 위해 계정 여유 마진의 특정 비율 만 사용한다는 설정을 기반으로 거래를 하기에 충분한 마진이 있는지 확인합니다.

계정 여유 증거금의 필수 비율이 주문에 필요한 증거금보다 크면 이 함수는 true를 반환하고 그렇지 않으면 거짓을 반환합니다. 이에 따라 함수가 true를 반환하는 경우에만 주문하려고 합니다. 이 함수는 주문 유형을 입력 매개 변수로 사용합니다.

2.1.3 checkBuy 함수

//+------------------------------------------------------------------+
//|  Checks for a Buy trade Condition                                |
//+------------------------------------------------------------------+
bool checkBuy()
{
  bool dobuy = false;
  if ((maVal[0]>maVal[1]) && (maVal[1]>maVal[2]) &&(p_close > maVal[1]))
  {
    // MA increases upwards and previous price closed above MA
    if ((adxVal[1]>Adx_Min)&& (plsDI[1]>minDI[1]))
    {
      // ADX is greater than minimum and +DI is greater tha -DI for ADX
      dobuy = true;
    }
  }
  return(dobuy);
}

우리는 이 함수에서 매수 거래를 개시하기 위한 조건을 마무리하기로 결정했습니다. 여기서는 Class 객체 함수를 사용하지 않았습니다. 이동 평균 인디케이터의 값이 상승하고 이전 바의 종가가 해당 시점의 이동 평균 값보다 높은 상태를 확인하고 있습니다.

또한 ADX 인디케이터의 값이 입력 매개 변수에 설정된 필요한 최소값보다 크고 ADX 인디케이터의 양의 DI 값이 음의 DI 값보다 큰 상황을 원합니다. 이러한 조건이 충족되면 EA가 매수 주문을 시작하기를 원할 것입니다.

2.1.4 checkSell 함수

//+------------------------------------------------------------------+
//|  Checks for a Sell trade Condition                               |
//+------------------------------------------------------------------+
bool checkSell()
{
  bool dosell = false;
  if ((maVal[0]<maVal[1]) && (maVal[1]<maVal[2]) &&(p_close < maVal[1]))
  {
    // MA decreases downwards and previuos price closed below MA
    if ((adxVal[1]>Adx_Min)&& (minDI[1]>plsDI[1]))
    {
      // ADX is greater than minimum and -DI is greater tha +DI for ADX
      dosell = true;
    }
  }
  return(dosell);
} 

이 함수는 CheckBuy 함수의 반대를 정확히 확인합니다. 또한 이 함수에서 클래스 객체를 사용하지 않았습니다. 이 함수는 이동 평균 인디케이터의 값이 하향으로 감소하고 이전 바의 종가가 해당 지점의 이동 평균 값보다 낮은 상태를 확인합니다.

또한 ADX 인디케이터의 값이 입력 매개 변수에 설정된 필수 최소값보다 크고 ADX 인디케이터의 음의 DI 값이 양의 DI 값보다 큰 상황을 원합니다. 이러한 조건이 충족되면 EA가 SELL 주문을 개시하기를 원합니다.

2.1.5 checkClosePos 함수
//+------------------------------------------------------------------+
//|  Checks if an Open position can be closed                        |
//+------------------------------------------------------------------+
bool checkClosePos(string ptype, double Closeprice)
{
   bool mark = false;
   if (ptype=="BUY")
   {
      // Can we close this position
     if (Closeprice < maVal[1]) // Previous price close below MA
      {
         mark = true;
      }
   }
   if (ptype=="SELL")
   {
      // Can we close this position
      if (Closeprice > maVal[1]) // Previous price close above MA
      {
         mark = true;
      }
   }
   return(mark);
}

이 함수는 현재 열린 포지션을 닫을 수 있는지 확인하는 데 사용됩니다. 이 함수는 이전 바의 종가가 해당 시점의 이동 평균 인디케이터 값보다 높거나 낮은 지 모니터링하는 데 사용됩니다 (거래 방향에 따라 다름).

조건 중 하나라도 충족되면 이 함수는 true를 반환하고 EA가 포지션을 마감할 것으로 예상합니다. 이 함수에는 주문 유형 (이번에는 이름 – BUY 또는 SELL)과 이전 바의 종가라는 두 가지 입력 매개 변수가 있습니다.

2.1.6 ClosePosition 함수

//+------------------------------------------------------------------+
//| Checks and closes an open position                               |
//+------------------------------------------------------------------+
bool ClosePosition(string ptype,double clp)
  {
   bool marker=false;
     
      if(myposition.Select(_Symbol)==true)
        {
         if(myposition.Magic()==EA_Magic && myposition.Symbol()==_Symbol)
           {
            //--- Check if we can close this position
            if(checkClosePos(ptype,clp)==true)
              {
               //--- close this position and check if we close position successfully?
               if(mytrade.PositionClose(_Symbol)) //--- Request successfully completed 
                 {
                  Alert("An opened position has been successfully closed!!");
                  marker=true;
                 }
               else
                 {
                  Alert("The position close request could not be completed - error: ",
                       mytrade.ResultRetcodeDescription());
                 }
              }
           }
        }
      return(marker);
     }

위의 함수 (checkclosepos)를 실제로 사용하는 함수입니다. CPositionInfoCTrade 클래스의 개체를 사용합니다. 이 함수는 CPositionInfo 클래스의 객체를 사용하여 EA에서 열린 위치와 현재 기호에 대해 사용 가능한 열린 포지션을 확인합니다. 위치가 발견되면 checkclosepos 함수를 사용하여 닫을 수 있는지 확인합니다.

checkclosepos 함수가 true를 반환하면 이 함수는 CTrade 클래스의 객체를 사용하여 포지션 마감 작업에 대한 결과를 표시합니다. 포지션이 성공적으로 마감되면 이 함수는 true를 반환하고 그렇지 않으면 false를 반환합니다.

이 함수는 두 개의 입력 매개 변수 (포지션 이름, 매수 또는 매도 및 이전 바 종가)를 사용합니다. 이 매개 변수는 실제로 매개 변수를 사용하는 checkclosepos 함수에 전달되었습니다.

2.1.7 CheckModify 함수

//+------------------------------------------------------------------+
//|  Checks if we can modify an open position                        |
//+------------------------------------------------------------------+
bool CheckModify(string otype,double cprc)
{
   bool check=false;
   if (otype=="BUY")
   {
      if ((maVal[2]<maVal[1]) && (maVal[1]<maVal[0]) && (cprc>maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   else if (otype=="SELL")
   {
      if ((maVal[2]>maVal[1]) && (maVal[1]>maVal[0]) && (cprc<maVal[1]) && (adxVal[1]>Adx_Min))
      {
         check=true;
      }
   }
   return(check);
} 

이 함수는 열린 포지션을 수정할 수 있는지 여부를 확인하는 조건을 확인하는 데 사용됩니다. 주문 유형 이름과 이전 바 종가를 입력 매개 변수로 사용합니다.

이 함수는 이동 평균이 여전히 하락하고 있고 이전 바의 종가가 해당 지점의 이동 평균 값보다 낮은 지 확인하는 동안 (매도 포지션의 경우), 이동 평균이 여전히 상승하고 있고 이전 바 종가가 해당 시점의 이동 평균 값보다 여전히 높고 ADX의 값도 필요한 최소값 (매수 포지션의 경우)보다 큰지 확인하는 것입니다. 보유한 포지션 유형에 따라 조건이 충족되면 EA는 포지션 수정을 고려합니다.

이 함수는 견인 입력 매개 변수 (포지션 이름, 매수 또는 매도 및 이전 바 종가)를 사용합니다.

2.1.8 수정 함수

//+------------------------------------------------------------------+
//| Modifies an open position                                        |
//+------------------------------------------------------------------+
   void Modify(string ptype,double stpl,double tkpf)
     {
       //--- New Stop Loss, new Take profit, Bid price, Ask Price
      double ntp,nsl,pbid,pask;                  
      long tsp=Trail_point;
       //--- adjust for 5 & 3 digit prices
      if(_Digits==5 || _Digits==3) tsp=tsp*10;   
       //--- Stops Level
      long stplevel= mysymbol.StopsLevel();      
       //--- Trail point must not be less than stops level
      if(tsp<stplevel) tsp=stplevel;
      if(ptype=="BUY")
        {
          //--- current bid price
         pbid=mysymbol.Bid();           
         if(tkpf-pbid<=stplevel*_Point)
           {
            //--- distance to takeprofit less or equal to Stops level? increase takeprofit
            ntp = pbid + tsp*_Point;
            nsl = pbid - tsp*_Point;
           }
         else
           {
            //--- distance to takeprofit higher than Stops level? dont touch takeprofit
            ntp = tkpf;
            nsl = pbid - tsp*_Point;
           }
        }
      else //--- this is SELL
        {
          //--- current ask price
         pask=mysymbol.Ask();            
         if(pask-tkpf<=stplevel*_Point)
           {
            ntp = pask - tsp*_Point;
            nsl = pask + tsp*_Point;
           }
         else
           {
            ntp = tkpf;
            nsl = pask + tsp*_Point;
           }
        }
      //--- modify and check result
      if(mytrade.PositionModify(_Symbol,nsl,ntp))  
        {
          //--- Request successfully completed    
         Alert("An opened position has been successfully modified!!");
         return;
        }
      else
        {
         Alert("The position modify request could not be completed - error: ",
               mytrade.ResultRetcodeDescription());
         return;
        }

     }

 이 함수는 위의 함수 (checkmodify)를 사용하여 작업을 수행합니다. CSymbolInfoCTrade 클래스의 개체를 사용합니다. 우선, 우리는 새로운 테이크 프로핏, 손절매, 매도 가격 및 매도 호가를 보유하기 위해 4 개의 이중 데이터 유형을 선언했습니다. 그런 다음 입력 매개 변수 섹션에 설정된 Trail_point 값을 유지하기 위해 새로운 long 데이터 유형 tsp를 선언했습니다.

트레일 포인트 값 (tsp)은 5 자리 및 3 자리 가격으로 조정되었습니다. 그런 다음 CSymbolInfo 개체를 사용하여 경유지 수준을 얻고 추가하려는 트레일 지점이 필요한 중지 수준보다 작지 않은지 확인했습니다. 중지 수준보다 작으면 중지 수준 값을 사용합니다. 

포지션 유형에 따라 CSymbolInfo 클래스 객체를 사용하여 경우에 따라 현재 입찰 또는 매도가를 가져옵니다. 현재 입찰 또는 매도가와 초기 이익 실현 가격의 차이가 스탑 수준 (stops level)보다 작거나 같으면 손절매와 이익 실현을 둘 다 조정하고 그렇지 않으면 손절매 가만 조정합니다.

그런 다음 CTrade 클래스 객체를 사용하여 포지션에 대한 손절매와 이익 실현을 수정합니다. 거래 결과 반환 코드에 따라 성공 또는 실패 메시지도 표시됩니다.

우리는 작업을 더 쉽게 만들어 줄 사용자 정의 함수를 정의했습니다. 이제 EA 코드 섹션으로 이동하겠습니다.

2.1.9 OnInit 섹션

//--- set the symbol name for our SymbolInfo Object
   mysymbol.Name(_Symbol);
// Set Expert Advisor Magic No using our Trade Class Object
   mytrade.SetExpertMagicNumber(EA_Magic);
// Set Maximum Deviation using our Trade class object
   mytrade.SetDeviationInPoints(dev);
//--- Get handle for ADX indicator
   adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
   maHandle=iMA(_Symbol,Period(),MA_Period,0,MODE_EMA,PRICE_CLOSE);
//--- What if handle returns Invalid Handle
   if(adxHandle<0 || maHandle<0)
     {
      Alert("Error Creating Handles for MA, ADX indicators - error: ",GetLastError(),"!!");
      return(1);
     }
   STP = StopLoss;
   TKP = TakeProfit;
//--- Let us handle brokers that offers 5 or 3 digit prices instead of 4
   if(_Digits==5 || _Digits==3)
     {
      STP = STP*10;
      TKP = TKP*10;
     }
   
//--- Set trade percent
    TPC = TradePct;
    TPC = TPC/100;
//---

CSymbolInfo 클래스 개체에 대한 현재 기호를 설정하기로 결정했습니다. 또한 CTrade 클래스 객체를 사용하여 Expert Advisor 매직 넘버와 편차 (포인트)를 설정했습니다. 그 후 인디케이터에 대한 핸들을 가져오고 핸들 가져 오기가 실패하면 오류를 표시하기로 결정합니다.

다음으로, 손절매를 조정하고 3 자리 및 5 자리 가격에 대한 이익을 취하기로 결정하고 거래에 사용할 무료 계정 마진 비율을 백분율로 변환합니다.

2.1.10 OnDeinit 섹션

//--- Release our indicator handles
   IndicatorRelease(adxHandle);
   IndicatorRelease(maHandle);

여기에서 모든 인디케이터 핸들을 해제하기로 결정합니다.

2.1.11. OnTick 섹션

//--- check if EA can trade
    if (checkTrading() == false) 
   {
      Alert("EA cannot trade because certain trade requirements are not meant");
      return;
   }
//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];          // To be used to store the prices, volumes and spread of each bar
/*
     Let's make sure our arrays values for the Rates, ADX Values and MA values 
     is store serially similar to the timeseries array
*/
// the rates arrays
   ArraySetAsSeries(mrate,true);
// the ADX values arrays
   ArraySetAsSeries(adxVal,true);
// the MA values arrays
   ArraySetAsSeries(maVal,true);
// the minDI values array
   ArraySetAsSeries(minDI,true);
// the plsDI values array
   ArraySetAsSeries(plsDI,true);

여기서 가장 먼저 할 일은 EA가 거래해야 하는지 여부를 확인하고 확인하는 것입니다. checktrade 함수가 false를 반환하면 EA는 다음 틱을 기다렸다가 다시 확인합니다.

그 후 MQL5 MqlRates 구조를 선언하여 각 ​​바의 가격을 가져온 다음 ArraySetAsSeries 함수를 사용하여 필요한 모든 배열을 설정합니다.

//--- Get the last price quote using the SymbolInfo class object function
   if (!mysymbol.RefreshRates())
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");
      return;
     }

//--- Get the details of the latest 3 bars
   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Error copying rates/history data - error:",GetLastError(),"!!");
      return;
     }

//--- EA should only check for new trade if we have a new bar
// lets declare a static datetime variable
   static datetime Prev_time;
// lest get the start time for the current bar (Bar 0)
   datetime Bar_time[1];
   //copy the current bar time
   Bar_time[0] = mrate[0].time;
// We don't have a new bar when both times are the same
   if(Prev_time==Bar_time[0])
     {
      return;
     }
//Save time into static varaiable, 
   Prev_time = Bar_time[0]; 

CSymbolInfo 클래스 객체를 사용하여 현재 시세를 가져온 다음 현재 바 가격을 mrates 배열에 복사합니다. 그 유효성이 우리는 새로운 바가 있는지 확인하기로 결정합니다.

새로운 바가 있는 경우 EA는 매수 또는 매도 조건이 충족되었는지 확인하고 그렇지 않으면 새로운 바가 있을 때까지 기다립니다.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(adxHandle,0,0,3,adxVal)<3 || CopyBuffer(adxHandle,1,0,3,plsDI)<3
      || CopyBuffer(adxHandle,2,0,3,minDI)<3)
     {
      Alert("Error copying ADX indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(maHandle,0,0,3,maVal)<3)
     {
      Alert("Error copying Moving Average indicator buffer - error:",GetLastError());
      return;
     }
//--- we have no errors, so continue
// Copy the bar close price for the previous bar prior to the current bar, that is Bar 1

   p_close=mrate[1].close;  // bar 1 close price

여기서는 CopyBuffer 함수를 사용하여 인디케이터의 버퍼를 배열로 가져오고 프로세스에서 오류가 발생하면 표시됩니다. 이전 바 종가가 복사되었습니다.

//--- Do we have positions opened already?
  bool Buy_opened = false, Sell_opened=false; 
   if (myposition.Select(_Symbol) ==true)  // we have an opened position
    {
      if (myposition.Type()== POSITION_TYPE_BUY)
       {
            Buy_opened = true;  //It is a Buy
          // Get Position StopLoss and Take Profit
           double buysl = myposition.StopLoss();      // Buy position Stop Loss
           double buytp = myposition.TakeProfit();    // Buy position Take Profit
           // Check if we can close/modify position
           if (ClosePosition("BUY",p_close)==true)
             {
                Buy_opened = false;   // position has been closed
                return; // wait for new bar
             }
           else
           {
              if (CheckModify("BUY",p_close)==true) // We can modify position
              {
                  Modify("BUY",buysl,buytp);
                  return; // wait for new bar
              }
           } 
       }
      else if(myposition.Type() == POSITION_TYPE_SELL)
       {
            Sell_opened = true; // It is a Sell
            // Get Position StopLoss and Take Profit
            double sellsl = myposition.StopLoss();    // Sell position Stop Loss
            double selltp = myposition.TakeProfit();  // Sell position Take Profit
             if (ClosePosition("SELL",p_close)==true)
             {
               Sell_opened = false;  // position has been closed
               return;   // wait for new bar
             }
             else
             {
                 if (CheckModify("SELL",p_close)==true) // We can modify position
                 {
                     Modify("SELL",sellsl,selltp);
                     return;  //wait for new bar
                 }
             } 
       }
    } 

CPositionInfo 클래스 객체를 사용하여 현재 심볼에 대해 열린 포지션이 있는지 확인합니다. 포지션이 존재하고 매수인 경우 Buy_openedtrue로 설정한 다음 CPositionInfo를 사용합니다. 클래스 개체를 사용하여 손절매를 얻고 포지션의 이익을 얻습니다. 앞에서 정의한 ClosePosition 함수를 사용하여 포지션이 닫힐 수 있는지 확인했습니다. 함수가 true를 반환하면 포지션이 마감된 것이므로 Buy_opened를 false로 설정하여 초기 매수 포지션이 방금 마감된 것입니다. EA는 이제 새로운 틱을 기다릴 것입니다.

그러나 함수가 false를 반환하면 포지션이 닫히지 않은 것입니다. 이제 포지션을 수정할 수 있는지 확인할 차례입니다. 이전에 정의한 CheckModify 함수를 사용하여 이를 달성했습니다. 함수가 true를 반환하면 포지션을 수정할 수 있음을 의미하므로 Modify 함수를 사용하여 포지션을 수정합니다.

반면에 포지션이 존재하고 매도인 경우 Sell_openedtrue 그리고 CPositionInfo 클래스 객체를 사용하여 손절매를 얻고 포지션의 이익을 얻습니다. 포지션을 닫거나 수정할 수 있는지 확인하기 위해 BUY 포지션에서 했던 것과 동일한 단계를 반복했습니다.

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);                //--- latest ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit)) 
           {
               //--- Request is completed or order placed
             Alert("A Buy order has been successfully placed with deal Ticket#:",
                  mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                  ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
                  ", price:", mytrade.RequestPrice(), 
                     " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

또는 PositionOpen 함수를 사용할 수 있습니다.

      if(checkBuy()==true)
        {
         //--- any opened Buy position?
         if(Buy_opened)
           {
            Alert("We already have a Buy position!!!");
            return;    //--- Don't open a new Sell Position
           }

         double mprice=NormalizeDouble(mysymbol.Ask(),_Digits);               //--- latest Ask price
         double stloss = NormalizeDouble(mysymbol.Ask() - STP*_Point,_Digits); //--- Stop Loss
         double tprofit = NormalizeDouble(mysymbol.Ask()+ TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_BUY,mprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- open Buy position and check the result
         //if(mytrade.Buy(Lot,_Symbol,mprice,stloss,tprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_BUY,Lot,mprice,stloss,tprofit))
           {
              //--- Request is completed or order placed            
              Alert("A Buy order has been successfully placed with deal Ticket#:",
            mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Buy order request at vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

여기서는 checkbuy 함수를 사용하여 매수 설정을 확인하고true 를 반환하는지 확인합니다. 매수 거래 조건이 충족되었습니다. 이미 BUY 포지션이 있다면 새로 주문하고 싶지 않습니다. 그런 다음 CSymbolInfo 클래스 개체를 사용하여 현재 매도가를 가져오고 필요에 따라 손절매와 이익 실현을 계산했습니다.

우리는 또한 ConfirmMargin 함수을 사용하여 주문에 허용된 계정의 비율이 이 주문에 필요한 증거금보다 큰지 확인합니다. 함수가true를 반환하면 계속 진행하고 거래를 배치하고 그렇지 않으면 거래를 배치하지 않습니다.

CTrade 클래스 객체를 사용하여 주문을하고 동일한 호출 객체를 사용하여 거래 작업 반환 코드를 얻었습니다. 거래 결과에 따라 메시지가 표시됩니다.

      if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         //if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
               //---Request is completed or order placed            
               Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(), 
                    ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                    ", price:", mytrade.RequestPrice(), 
                    " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }

        }

또는 PositionOpen 함수를 사용할 수도 있습니다.

      if(checkSell()==true)
        {
         //--- any opened Sell position?
         if(Sell_opened)
           {
            Alert("We already have a Sell position!!!");
            return;    //--- Wait for a new bar
           }

         double sprice=NormalizeDouble(mysymbol.Bid(),_Digits);             //--- latest Bid price
         double ssloss=NormalizeDouble(mysymbol.Bid()+STP*_Point,_Digits);   //--- Stop Loss
         double stprofit=NormalizeDouble(mysymbol.Bid()-TKP*_Point,_Digits); //--- Take Profit
         //--- check margin
         if(ConfirmMargin(ORDER_TYPE_SELL,sprice)==false)
           {
            Alert("You do not have enough money to place this trade based on your setting");
            return;
           }
         //--- Open Sell position and check the result
         //if(mytrade.Sell(Lot,_Symbol,sprice,ssloss,stprofit))
         if(mytrade.PositionOpen(_Symbol,ORDER_TYPE_SELL,Lot,sprice,ssloss,stprofit))
           {
             //---Request is completed or order placed            
             Alert("A Sell order has been successfully placed with deal Ticket#:",mytrade.ResultDeal(),"!!");
           }
         else
           {
            Alert("The Sell order request at Vol:",mytrade.RequestVolume(),
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                 ", price:", mytrade.RequestPrice(), 
                   " could not be completed -error:",mytrade.ResultRetcodeDescription());
            return;
           }
        }

매수와 마찬가지로 Checksell 함수을 사용하여 매도 설정을 확인했습니다. true 를 반환하고 이미 오픈 된 매도 포지션이 없는 경우 ConfirmMargin 함수를 사용하여 주문을 개시 할 자금이 충분한 지 확인했습니다. ConfirmMargintrue을 반환하면 CTrade 클래스 개체가 주문을하는 데 사용됩니다. 거래 서버의 응답에 따라 거래 결과는 CTrade<10> 클래스 객체 함수를 사용하여 표시됩니다.

지금까지 Expert Advisor 작성시 Trade 클래스 라이브러리를 사용하는 방법을 살펴보았습니다. 다음은 전략 테스터로 Expert Advisor를 테스트하고 성능을 확인하는 것입니다.

EA 코드를 컴파일 한 다음 전략 테스터에로드합니다.

EA 용 보고서 컴파일

         그림 3. Expert Advisor 컴파일 보고서 

기본 설정: 이익 실현-270, 손절매-100 및 트레일 포인트 (TP/SL) - 32를 사용하는 GBPUSD 일일 차트에 다음과 같은 결과가 있습니다.

 

그림 4. Expert Advisor 테스트 보고서 - GBPUSD 일일 차트

 

 

그림 5. Expert Advisor 테스트 그래프 결과 - GBPUSD 일일 차트

                                                                                                                                

그림 6. Expert Advisor 테스트 보고서는 오픈 포지션 수정을 보여줍니다 - GBPUSD 일일 차트

 

그림 7. GBPUSD 일일 차트에 대한 Expert Advisor 테스트 차트 보고서

이익 실현, 손절매 및 트레일 포인트 설정의 다른 설정을 사용하여 다른 심볼 일일 차트에서 EA를 자유롭게 테스트하고 얻을 수있는 것을 확인할 수 있습니다. 

그러나이 Expert Advisor는 테스트 목적으로 만 작성되었음을 이해해야 합니다.

이제 주문/거래 세부 정보를 얻기 위해 다른 클래스 (COrderInfo, CHistoryOrderInfo, 및 CDealInfo) 를 사용하는 방법을 살펴 보겠습니다.

2.2 보류중인 주문 개시/삭제  

이 예에서는 매수 또는 매도 설정 조건이 각각 충족되면 보류 주문 (BuyStop 또는 SellStop)을하는 간단한 Expert Advisor를 작성합니다.

2.2.1 필수 클래스 포함

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\Trade.mqh>
//--- The PositionInfo Class
#include <Trade\PositionInfo.mqh>
//--- The SymbolInfo Class
#include <Trade\SymbolInfo.mqh>
//--- The OrderInfo Class
#include <Trade\OrderInfo.mqh>

이 간단한 Expert Advisor에는 사용할 4 개의 클래스가 포함되어 있습니다. 위의 예에서 설명했습니다.

위에서 설명한 것과 유사하므로 이 Expert Advisor의 모든 섹션을 설명하지는 않지만 이 섹션에서 논의하려는 내용을 설명하는 Expert Advisor의 필수 부분을 살펴 보겠습니다.

유일한 차이점은 전역 범위에서 MqlRates mrate[]를 선언하기로 결정한 것입니다.

//--- Define the MQL5 MqlRates Structure we will use for our trade
   MqlRates mrate[];     // To be used to store the prices, volumes and spread of each bar

클래스를 포함하고 나면 각 클래스의 객체를 생성해야 합니다.

//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECTS                                            |
//+------------------------------------------------------------------+
//--- The CTrade Class Object
CTrade mytrade;
//--- The CPositionInfo Class Object
CPositionInfo myposition;
//--- The CSymbolInfo Class Object
CSymbolInfo mysymbol;
//--- The COrderInfo Class Object
COrderInfo myorder;

CheckBuy()CheckSell() 함수는 앞서 설명한 Expert Advisor에서와 동일합니다.

여기서 우리가 원하는 것은 매수 설정이 있을 때 BUYSTOP 주문을 하고, 매도 설정이있을 때 SELLSTOP 주문을하는 것입니다.

이제 우리가 일을 쉽게 하기 위해 만든 몇 가지 함수를 살펴 보겠습니다.

2.2.2 CountOrders 함수

//+------------------------------------------------------------------+
//|  Count Total Orders for this expert/symbol                             |
//+------------------------------------------------------------------+
int CountOrders()
  {
   int mark=0;

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol) mark++;
        }
     }
   return(mark);
  }

이 함수는 특정 시점에 사용 가능한 총 보류 주문을 가져오는 데 사용됩니다.

myorder.Select() 함수로 주문이 성공적으로 선택되었는지 확인하기 위해 COrderInfo 클래스의 개체를 사용했습니다.

클래스 객체에 의한 매직 리턴과 리턴된 기호가 우리가 찾고있는 것이라면, 주문은 우리의 Expert Advisor에 의해 이루어 졌기 때문에 계수되고 변수 mark에 저장됩니다.

2.2.3 DeletePending 함수

//+------------------------------------------------------------------+
//| Checks and Deletes a pending order                                |
//+------------------------------------------------------------------+
bool DeletePending()
  {
   bool marker=false;
//--- check all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      if(myorder.Select(OrderGetTicket(i)))
        {
         if(myorder.Magic()==EA_Magic && myorder.Symbol()==_Symbol)
           {
            //--- check if order has stayed more than two bars time
            if(myorder.TimeSetup()<mrate[2].time)
              {
               //--- delete this pending order and check if we deleted this order successfully?
                if(mytrade.OrderDelete(myorder.Ticket())) //Request successfully completed 
                  {
                    Alert("A pending order with ticket #", myorder.Ticket(), " has been successfully deleted!!");
                    marker=true;
                  }
                 else
                  {
                    Alert("The pending order # ",myorder.Ticket(),
                             " delete request could not be completed - error: ",mytrade.ResultRetcodeDescription());
                  }

              }
           }
        }
     }
   return(marker);
  }

countorder 함수와 마찬가지로 이 함수도 COrderInfo 클래스 함수를 사용하여 주문 속성을 가져옵니다. 이 함수는 세 개의 바 이전에 설정되었고 (보류 주문 설정 시간이 mrate[2] .time보다 작음) 아직 트리거되지 않은 모든 대기 주문을 확인합니다.

해당 카테고리에 해당하는 주문이 있으면 CTrade 클래스 함수 OrderDelete를 사용하여 주문을 삭제합니다. 이 함수는 성공하면 true를 반환하고 그렇지 않으면 false를 반환합니다.

위의 두 함수는 새로운 거래 설정을 확인하기 전에 새로운 바가 형성된 직후에 사용됩니다. 매 시점마다 3 개 이상의 대기 주문이 접수되지 않았는지 확인하고자 합니다. 이를 위해 다음 코드를 사용합니다.

// do we have more than 3 already placed pending orders
if (CountOrders()>3) 
  {
     DeletePending(); 
     return;  
  }

2.2.4 대기 주문하기

   if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
                 ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
               ", price:", mytrade.RequestPrice(), 
                 " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

또는 OrderOpen 함수를 사용하여 BUYSTOP 주문을 할 수도 있습니다.

   if(checkBuy()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Buy position?
      if(Buy_opened)
        {
         Alert("We already have a Buy position!!!");
         return;    //--- Don't open a new Sell Position
        }
      //Buy price = bar 1 High + 2 pip + spread
      int sprd=mysymbol.Spread();
      double bprice =mrate[1].high + 10*_Point + sprd*_Point;
      double mprice=NormalizeDouble(bprice,_Digits);               //--- Buy price
      double stloss = NormalizeDouble(bprice - STP*_Point,_Digits); //--- Stop Loss
      double tprofit = NormalizeDouble(bprice+ TKP*_Point,_Digits); //--- Take Profit
      //--- open BuyStop order
      //if(mytrade.BuyStop(Lot,mprice,_Symbol,stloss,tprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_BUY_STOP,Lot,0.0,bprice,stloss,tprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A BuyStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The BuyStop order request at vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(),
              ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

BUYSTOP 주문시 시가는 Bar 1 High + 2pip + 스프레드입니다.

차트에 표시된 가격은 입찰 가격이며 매수/매수 주문을 할 때 매도가가 필요하다는 점을 기억하십시오. 그렇기 때문에 Bar 1 High에 스프레드를 추가하여 현재 보유한 가격이 해당 매도가 +2pip가 되도록 결정했습니다. 손절매와 이익 실현은 이미 입력 매개 변수에 정의되어 있습니다.

필요한 모든 매개 변수를 준비했으면 CTrade 클래스 함수 BuyStop 또는 OrderOpen을 사용하여 주문합니다. 여기서 주문 유형은 ORDER_TYPE_BUY_STOP (매수 중지 주문)입니다. 우리는 제한 가격에 동일한 가격을 사용하지만 이것은 BuyLimit 주문이 아닙니다. 또한 주문 유효 시간을 ORDER_TIME_GTC로 설정했습니다. 이는 주문이 취소 될 때까지 유효함을 의미합니다.

ORDER_TIME_GTC 또는 ORDER_TIME_DAY를 사용하면 만료 시간을 지정할 필요가 없으므로 만료 시간을 0으로 설정합니다

   if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      //if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
              ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
                " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

또는 OrderOpen 함수를 사용하여 주문할 수도 있습니다.

   if(checkSell()==true)
     {
      Alert("Total Pending Orders now is :",CountOrders(),"!!");
      //--- any opened Sell position?
      if(Sell_opened)
        {
         Alert("We already have a Sell position!!!");
         return;    //--- Wait for a new bar
        }
      //--- Sell price = bar 1 Low - 2 pip 
      double sprice=mrate[1].low-10*_Point;
      double slprice=NormalizeDouble(sprice,_Digits);            //--- Sell price
      double ssloss=NormalizeDouble(sprice+STP*_Point,_Digits);   //--- Stop Loss
      double stprofit=NormalizeDouble(sprice-TKP*_Point,_Digits); //--- Take Profit
      //--- Open SellStop Order
      //if(mytrade.SellStop(Lot,slprice,_Symbol,ssloss,stprofit))
      if(mytrade.OrderOpen(_Symbol,ORDER_TYPE_SELL_STOP,Lot,0.0,slprice,ssloss,stprofit,ORDER_TIME_GTC,0)) 
        {
         //--- Request is completed or order placed
         Alert("A SellStop order has been successfully placed with Ticket#:",mytrade.ResultOrder(),"!!");
         return;
        }
      else
        {
         Alert("The SellStop order request at Vol:",mytrade.RequestVolume(), 
                ", sl:", mytrade.RequestSL(),", tp:",mytrade.RequestTP(), 
                ", price:", mytrade.RequestPrice(), 
              " could not be completed -error:",mytrade.ResultRetcodeDescription());
         return;
        }
     }

BuyStop 주문과 마찬가지로 시가는 Bar 1 최저가 + 2pip입니다. 여기서는 스프레드를 추가 할 필요가 없습니다. 일반적으로 공매도/매도 주문을 하려면 BID 가격이 필요하기 때문입니다.

또한 동일한 OrderOpen 함수 또는 SellStop 함수를 사용하여 SellStop 주문을 합니다. 여기의 주문 유형은 ORDER_TYPE_SELL_STOP (매도 중지 주문)입니다.

다음은 간단한 Expert Advisor의 결과입니다.

 


그림 8. 보류중인 주문 EA에 대한 테스트 보고서

 

그림 9 - EA 그래프 보고서

 

그림 10. EA 차트 보고서

 

2.3 주문/거래 세부 정보 얻기

이 예에서는 주문이 트리거 된 후 세부 정보를 얻는 방법을 보여줍니다.

이 단계에서는 트리거되고 거래로 전환되었기 때문에 더 이상 보류 중인 주문이 아닙니다.

이 절차를 완전히 이해하기 위해 우리 거래 중 하나의 저널 세부 사항을 살펴 보겠습니다.

주문 처리 절차

그림 11. 주문 처리 절차

  • 1 단계: 조건이 충족 될 때까지 대기중인 주문이 접수됩니다 (주문 대기 중).
  • 2 단계: 조건이 충족되고 보류중인 주문이 트리거되고 거래가 됩니다 (현재 기록에서 보류중인 주문).
  • 3 단계: 거래가 수행되고 포지션이 열렸습니다. (거래는 이제 내역에 있습니다)

2.3.1 주문 속성 얻기 (내역)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The Trade Class
#include <Trade\HistoryOrderInfo.mqh>
//+------------------------------------------------------------------+
//|  CREATE CLASS OBJECT                                             |
//+------------------------------------------------------------------+
//--- The HistoryOrderInfo Class Object
CHistoryOrderInfo myhistory;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all orders in History and get their details
   int buystop=0;
   int sellstop=0;
   int buylimit=0;
   int selllimit=0;
   int buystoplimit=0;
   int sellstoplimit=0;
   int buy=0;
   int sell=0;

   int s_started=0;
   int s_placed=0;
   int s_cancelled=0;
   int s_partial=0;
   int s_filled=0;
   int s_rejected=0;
   int s_expired=0;

   ulong o_ticket;
// Get all history records
   if(HistorySelect(0,TimeCurrent())) // get all history orders
     {
      // Get total orders in history
      for(int j=HistoryOrdersTotal(); j>0; j--)
        {
         // select order by ticket
         o_ticket=HistoryOrderGetTicket(j);
         if(o_ticket>0)
           {
            // Set order Ticket to work with
            myhistory.Ticket(o_ticket);
            Print("Order index ",j," Order Ticket is: ",myhistory.Ticket()," !");
            Print("Order index ",j," Order Setup Time is: ",TimeToString(myhistory.TimeSetup())," !");
            Print("Order index ",j," Order Open Price is: ",myhistory.PriceOpen()," !");
            Print("Order index ",j," Order Symbol is: ",myhistory.Symbol() ," !");
            Print("Order index ",j," Order Type is: ", myhistory.Type() ," !");
            Print("Order index ",j," Order Type Description is: ",myhistory.TypeDescription()," !");
            Print("Order index ",j," Order Magic is: ",myhistory.Magic()," !");
            Print("Order index ",j," Order Time Done is: ",myhistory.TimeDone()," !");
            Print("Order index ",j," Order Initial Volume is: ",myhistory.VolumeInitial()," !");
            //
            //
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP) buystop++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP) sellstop++;
            if(myhistory.Type() == ORDER_TYPE_BUY) buy++;
            if(myhistory.Type() == ORDER_TYPE_SELL) sell++;
            if(myhistory.Type() == ORDER_TYPE_BUY_LIMIT) buylimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_LIMIT) selllimit++;
            if(myhistory.Type() == ORDER_TYPE_BUY_STOP_LIMIT) buystoplimit++;
            if(myhistory.Type() == ORDER_TYPE_SELL_STOP_LIMIT) sellstoplimit++;

            if(myhistory.State() == ORDER_STATE_STARTED) s_started++;
            if(myhistory.State() == ORDER_STATE_PLACED) s_placed++;
            if(myhistory.State() == ORDER_STATE_CANCELED) s_cancelled++;
            if(myhistory.State() == ORDER_STATE_PARTIAL) s_partial++;
            if(myhistory.State() == ORDER_STATE_FILLED) s_filled++;
            if(myhistory.State() == ORDER_STATE_REJECTED) s_rejected++;
            if(myhistory.State() == ORDER_STATE_EXPIRED) s_expired++;
           }
        }
     }
// Print summary
   Print("Buy Stop Pending Orders : ",buystop);
   Print("Sell Stop Pending Orders: ",sellstop);
   Print("Buy Orders : ",buy);
   Print("Sell Orders: ",sell);
   Print("Total Orders in History is :",HistoryOrdersTotal()," !");
   
   Print("Orders type summary");
   Print("Market Buy Orders: ",buy);
   Print("Market Sell Orders: ",sell);
   Print("Pending Buy Stop: ",buystop);
   Print("Pending Sell Stop: ",sellstop);
   Print("Pending Buy Limit: ",buylimit);
   Print("Pending Sell Limit: ",selllimit);
   Print("Pending Buy Stop Limit: ",buystoplimit);
   Print("Pending Sell Stop Limit: ",sellstoplimit);
   Print("Total orders:",HistoryOrdersTotal()," !");

   Print("Orders state summary");
   Print("Checked, but not yet accepted by broker: ",s_started);
   Print("Accepted: ",s_placed);
   Print("Canceled by client: ",s_cancelled);
   Print("Partially executed: ",s_partial);
   Print("Fully executed: ",s_filled);
   Print("Rejected: ",s_rejected);
   Print("Expired: ",s_expired);
  }

이것은 우리의 내역 기록에서 주문의 세부 사항을 얻는 방법을 보여주는 간단한 스크립트입니다. CHistoryOrderInfo 클래스를 포함하고 클래스의 객체를 생성했습니다.

이제 개체를 사용하여 주문의 세부 정보를 얻습니다.

히스토리 주문 스크립트의 결과 

 그림 12. 내역 주문 스크립트 결과

2.3.2 거래 속성 얻기 (내역)

//+------------------------------------------------------------------+
//|  Include ALL classes that will be used                           |
//+------------------------------------------------------------------+
//--- The CDealInfo Class
#include <Trade\DealInfo.mqh>
//+------------------------------------------------------------------+
//|  Create class object                                             |
//+------------------------------------------------------------------+
//--- The CDealInfo Class Object
CDealInfo mydeal;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- Get all deals in History and get their details
    int buy=0;
    int sell=0;
    int deal_in=0;
    int deal_out=0;
    ulong d_ticket;
    // Get all history records
    if (HistorySelect(0,TimeCurrent())) 
    {
      // Get total deals in history
      for (int j=HistoryDealsTotal(); j>0; j--)
      {
         // select deals by ticket
         if (d_ticket = HistoryDealGetTicket(j))
         {
          // Set Deal Ticket to work with
          mydeal.Ticket(d_ticket);
          Print("Deal index ", j ," Deal Ticket is: ", mydeal.Ticket() ," !");
          Print("Deal index ", j ," Deal Execution Time is: ", TimeToString(mydeal.Time()) ," !");
          Print("Deal index ", j ," Deal Price is: ", mydeal.Price() ," !");
          Print("Deal index ", j ," Deal Symbol is: ", mydeal.Symbol() ," !");
          Print("Deal index ", j ," Deal Type Description is: ", mydeal.TypeDescription() ," !");
          Print("Deal index ", j ," Deal Magic is: ", mydeal.Magic() ," !");
          Print("Deal index ", j ," Deal Time is: ", mydeal.Time() ," !");
          Print("Deal index ", j ," Deal Initial Volume is: ", mydeal.Volume() ," !");
          Print("Deal index ", j ," Deal Entry Type Description is: ", mydeal.EntryDescription() ," !");
          Print("Deal index ", j ," Deal Profit is: ", mydeal.Profit() ," !");
          //
          if (mydeal.Entry() == DEAL_ENTRY_IN) deal_in++;
          if (mydeal.Entry() == DEAL_ENTRY_OUT) deal_out++;
          if (mydeal.Type() == DEAL_TYPE_BUY) buy++;
          if (mydeal.Type() == DEAL_TYPE_SELL) sell++;
         }
      }
    }
    // Print Summary
    Print("Total Deals in History is :", HistoryDealsTotal(), " !");
    Print("Total Deal Entry IN is : ", deal_in);
    Print("Total Deal Entry OUT is: ", deal_out);
    Print("Total Buy Deal is : ", buy);
    Print("Total Sell Deal is: ", sell);
  }

이것은 또한 거래 기록의 세부 사항을 얻는 방법을 보여주는 간단한 스크립트입니다.

거래 스크립트의 결과

그림 13. 내역 거래 스크립트 결과


결론

이 글에서는 표준 Trade Class 라이브러리의 주요 함수를 살펴볼 수 있었고 는 이러한 함수 중 일부가 거래하기 전에 포지션 수정, 주문 보류 및 삭제 및 마진 확인을 구현하는 Expert Advisors를 쓰는데 어떻게 사용될 수 있는지를 보여드렸습니다.

또한 주문 및 거래 세부 정보를 얻는 데 사용할 수있는 방법도 시연했습니다. Expert Advisor 작성 과정에서 사용하지 않은 이러한 함수 중 일부는 사용하는 거래 전략 유형에 따라이 예에서 사용한 것보다 더 많이 또는 적게 사용할 수 있습니다.

다양한 함수에 대한 설명 섹션을 수정하고 자신의 Expert Advisor를 작성하는 데 어떻게 활용할 수 있는지 확인하는 것이 좋습니다.

표준 클래스 라이브러리는 트레이더와 개발자 모두에게 편리함을 제공하기 위한 것이므로 반드시 사용해야 합니다.


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

Expert Advisor 작업 중 균형 곡선의 기울기 조절 Expert Advisor 작업 중 균형 곡선의 기울기 조절
무역 시스템에 대한 규칙을 찾고 Expert Advisor에서 프로그래밍하는 것은 작업의 절반입니다. 어쨋든 거래 결과가 누적되므로 Expert Advisor의 운영을 수정해야 합니다. 이 기사에서는 균형 곡선의 기울기를 측정하는 피드백을 생성하여 Expert Advisor의 성능을 향상시킬 수있는 접근 방식 중 하나를 설명합니다.
TesterWithdrawal() 함수를 이용한 수익 인출 모델링 TesterWithdrawal() 함수를 이용한 수익 인출 모델링
이 글에서는 운용 중에 자산의 특정 부분을 인출하는 것을 의미하는 거래 시스템의 위험을 추정하기 위해 TesterWithDrawal() 함수를 사용하는 방법에 대해 설명합니다. 또한 이 함수가 전략 테스터의 지분 하락 계산 알고리즘에 미치는 영향을 설명합니다. 이 함수는 Expert Advisors의 매개 변수를 최적화 할 때 유용합니다.
자동 거래 챔피언십 2010을 위한 Expert Advisor를 신속하게 만드는 방법을 알아보십시오. 자동 거래 챔피언십 2010을 위한 Expert Advisor를 신속하게 만드는 방법을 알아보십시오.
Automated Trading Championship 2010에 참여할 전문가를 양성하기 위해 준비된 Expert Advisor의 템플릿을 사용해 보겠습니다. 기본 클래스, 기능, 템플릿이 이미 개발되었기 때문에 초보 MQL5 프로그래머도 이 작업을 수행할 수 있습니다. 거래 아이디어를 구현하기 위한 최소한의 코드만으로도 충분합니다.
특정 매직 넘버에 의한 총 포지션 볼륨 계산을 위한 최적 방법 특정 매직 넘버에 의한 총 포지션 볼륨 계산을 위한 최적 방법
이 글에서는 지정된 기호와 매직 넘버의 총 포지션 볼륨 계산 문제를 고려합니다. 제안 된 방법은 거래 내역에서 필요한 최소한의 부분만 요청하고 총 포지션이 0 일 때 가장 가까운 시간을 찾아 최근 거래로 계산을 수행합니다. 클라이언트 터미널의 전역 변수 작업도 고려됩니다.