![Expert Advisor의 한계 및 검증](https://c.mql5.com/i/articles/overlay.png)
Expert Advisor의 한계 및 검증
소개
자동 거래를 위한 알고리즘을 생성할 때 거래 신호를 만들기 위한 가격을 처리할 수 있을 뿐만 아니라 Expert Advisors의 운영에 부과된 제한 사항에 대한 많은 보조 정보를 얻을 수 있어야 합니다. 이 문서에서는 다음을 수행하는 방법에 대해 설명합니다.
- 거래 세션에 대한 정보를 얻으십시오.
- 포지션을 열 수 있는 자산이 충분한지 확인하십시오.
- 기호로 총 거래량을 제한합니다.
- 총 주문 수에 제한을 가합니다.
- 진입 가격과 손절매 사이의 잠재적 손실을 계산합니다.
- 새로운 바가 있는지 확인하십시오.
거래 및 견적 세션
거래 세션에 대한 정보를 받으려면 SymbolInfoSessionTrade() 함수를 사용해야 하며, 호가 세션의 경우 해당 SymbolInfoSessionQuote() 함수를 사용해야 합니다. 두 함수는 같은 방식으로 작동합니다. 지정된 요일에 대해 지정된 인덱스가 있는 세션이 있는 경우(세션의 인덱싱은 0부터 시작) 함수는 true를 반환합니다. 세션의 시작 및 종료 시간은 링크에 의해 전달된 네 번째 및 다섯 번째 매개변수에 기록됩니다.
//--- check if there is a quotation session with the number session_index bool session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);지정된 날짜의 모든 세션을 찾으려면 false를 반환할 때까지 이 함수를 루프에서 호출합니다.
//+------------------------------------------------------------------+ //| Display information about quotation sessions | //+------------------------------------------------------------------+ void PrintInfoForQuoteSessions(string symbol,ENUM_DAY_OF_WEEK day) { //--- start and end of session datetime start,finish; uint session_index=0; bool session_exist=true; //--- go over all sessions of this day while(session_exist) { //--- check if there is a quotation session with the number session_index session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish); //--- if there is such session if(session_exist) { //--- display the day of week, the session number and the time of start and end Print(DayToString(day),": session index=",session_index," start=", TimeToString(start,TIME_MINUTES)," finish=",TimeToString(finish-1,TIME_MINUTES|TIME_SECONDS)); } //--- increase the counter of sessions session_index++; } }
요일은 ENUM_DAY_OF_WEEK 열거 값을 매개변수로 받는 사용자 정의 함수 DayToString()을 사용하여 문자열 형식으로 표시됩니다.
//+------------------------------------------------------------------+ //| Receive the string representation of a day of week | //+------------------------------------------------------------------+ string DayToString(ENUM_DAY_OF_WEEK day) { switch(day) { case SUNDAY: return "Sunday"; case MONDAY: return "Monday"; case TUESDAY: return "Tuesday"; case WEDNESDAY: return "Wednesday"; case THURSDAY: return "Thursday"; case FRIDAY: return "Friday"; case SATURDAY: return "Saturday"; default: return "Unknown day of week"; } return ""; }
SymbolInfoSession.mq5 스크립트의 최종 코드는 글 하단에 첨부되어 있습니다. 여기서는 주요 부분만 보여드리겠습니다.
void OnStart() { //--- the array where the days of week are stored ENUM_DAY_OF_WEEK days[]={SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}; int size=ArraySize(days); //--- Print("Quotation sessions"); //--- go over all the days of week for(int d=0;d<size;d++) { PrintInfoForQuoteSessions(Symbol(),days[d]); } //--- Print("Trading sessions"); //--- go over all the days of week for(int d=0;d<size;d++) { PrintInfoForTradeSessions(Symbol(),days[d]); } }
확인 여백
포지션을 열거나 늘리는 데 필요한 증거금의 양을 알아보려면 OrderCalcMargin() 함수를 사용할 수 있습니다. 전달되는 첫 번째 매개변수는 ENUM_ORDER_TYPE 열거의 값입니다. 구매 작업의 경우 ORDER_TYPE_BUY 매개변수로 호출해야 합니다. 판매하려면 ORDER_TYPE_SELL 매개변수를 사용하십시오. 이 함수는 랏 수와 시가에 따른 마진 금액을 반환합니다.
void OnStart() { //--- the variable to receive the value of margin double margin; //--- to receive information about the last tick MqlTick last_tick; //--- try to receive the value from the last tick if(SymbolInfoTick(Symbol(),last_tick)) { //--- reset the last error code ResetLastError(); //--- calculate margin value bool check=OrderCalcMargin(type,Symbol(),lots,last_tick.ask,margin); if(check) { PrintFormat("For the operation %s %s %.2f lot at %G required margin is %.2f %s",OrderTypeToString(type), Symbol(),lots,last_tick.ask,margin,AccountInfoString(ACCOUNT_CURRENCY)); } } else { Print("Unsuccessful execution of the SymbolInfoTick() function, error ",GetLastError()); } }
OrderCalcMargin() 함수를 사용하면 시장가 주문뿐만 아니라 보류 중인 주문에 대해서도 마진 값을 계산할 수 있습니다. Check_Money.mq5 스크립트를 사용하여 모든 유형의 주문에 대해 반환되는 값을 확인할 수 있습니다.
OrderCalcMargin() 함수는 보류 중인 주문의 증거금 크기를 계산하기 위한 것입니다. 일부 거래 시스템에서는 보류 중인 주문에 대해서도 자금 지원이 필요할 수 있기 때문입니다. 일반적으로 보류 주문의 증거금 크기는 롱 및 숏 포지션의 증거금 크기에 대한 계수를 통해 계산됩니다.
식별자 | 설명 | 재산 유형 |
SYMBOL_MARGIN_LONG | 롱 포지션에 대한 증거금 부과율 | 더블 |
SYMBOL_MARGIN_SHORT | 숏 포지션에 대한 증거금 부과율 | 더블 |
SYMBOL_MARGIN_LIMIT | 지정가 주문에 대한 증거금 부과율 | 더블 |
SYMBOL_MARGIN_STOP | 중지 주문에 대한 증거금 부과율 | 더블 |
SYMBOL_MARGIN_STOPLIMIT | 지정가 주문에 대한 증거금 부과율 | 더블 |
간단한 코드를 사용하여 해당 계수의 값을 얻을 수 있습니다.
//--- Calculate the rates of margin charging for different types of orders PrintFormat("Rate of margin charging on long positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LONG)); PrintFormat("Rate of margin charging on short positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_SHORT)); PrintFormat("Rate of margin charging on Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LIMIT)); PrintFormat("Rate of margin charging on Stop orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOP)); PrintFormat("Rate of margin charging on Stop Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOPLIMIT));
Forex 기호의 경우 보류 중인 주문에 대한 증거금 부과 비율은 일반적으로 0과 같습니다. 즉, 증거금 요구 사항이 없습니다.
Check_Money.mq5 스크립트 실행 결과.
마진 충전 방식에 따라 자금 관리 시스템이 변경될 수 있으며, 보류 중인 주문에 마진이 필요한 경우 거래 시스템 자체에 일부 제한이 발생할 수 있습니다. 그렇기 때문에 이러한 매개변수는 Expert Advisor 작업의 자연스러운 한계이기도 합니다.
회계 가능한 손익
보호 정지 수준을 설정할 때 트리거할 준비가 되어 있어야 합니다. 잠재적 손실 위험은 금전적 측면에서 고려해야 합니다. OrderCalcProfit()은 이를 위한 것입니다. 이미 고려한 OrderCalcMargin() 함수와 매우 유사하지만 계산을 위해 시가와 종가가 모두 필요합니다.
ENUM_ORDER_TYPE 열거의 두 값 중 하나를 첫 번째 매개변수로 지정하십시오. ORDER_TYPE_BUY 또는 ORDER_TYPE_SELL; 다른 유형의 주문은 오류가 발생합니다. 마지막 매개변수에서 참조를 사용하여 변수를 전달해야 합니다. 이 참조에 OrderCalcProfit() 함수가 기록 성공한 경우의 이익/손실 값을 기록합니다.
특정 수준의 진입 및 퇴장으로 롱 포지션을 청산할 때 손익을 계산하는 CalculateProfitOneLot() 함수를 사용하는 예:
//+------------------------------------------------------------------+ //| Calculate potential profit/loss for buying 1 lot | //+------------------------------------------------------------------+ double CalculateProfitOneLot(double entry_price,double exit_price) { //--- receive the value of profit to this variable double profit=0; if(!OrderCalcProfit(ORDER_TYPE_BUY,Symbol(),1.0,entry_price,exit_price,profit)) { Print(__FUNCTION__," Failed to calculate OrderCalcProfit(). Error ",GetLastError()); } //--- return(profit); }
이 함수의 계산 결과가 그림에 나와 있습니다.
OrderCalcProfit() 함수를 사용하여 차트에 잠재적 손실을 계산하고 표시하는 예.
전체 코드는 첨부된 Expert Advisor CalculateProfit_EA.mq5에서 찾을 수 있습니다.
새로운 바가 있는지 확인하기
많은 거래 시스템의 개발은 거래 신호가 새로운 바가 나타날 때만 계산된다고 가정합니다. 모든 거래 행동은 한 번만 수행됩니다. MetaTrader 5 클라이언트 터미널의 전략 테스터의 "Only open price" 모드는 이러한 자동 거래 시스템을 확인하는 데 좋습니다.
"공개 가격만" 모드에서 모든 지표 계산 및 Expert Advisor의 OnTick() 함수 호출은 테스트 중에 바당 한 번만 수행됩니다. 가장 빠른 거래 모드입니다. 그리고 일반적으로 거래 시스템을 생성하는 중요하지 않은 가격 변동에 대해 가장 내결함성이 있습니다. 물론 동시에 Expert Advisor에서 사용되는 지표는 올바르게 작성되어야 하며 새로운 바가 올 때 값이 왜곡되어서는 안 됩니다.
"공개 가격만" 모드의 전략 테스터를 사용하면 바당 한 번만 실행되는 Expert Advisor에 대해 걱정할 필요가 없습니다. 그리고 그것은 매우 편리합니다. 그러나 데모 또는 실제 계정에서 실시간 모드로 작업하는 동안 트레이더는 Expert Advisor의 활동을 제어하여 수신된 신호당 하나의 거래 작업만 수행하도록 해야 합니다. 이 목적을 위한 가장 쉬운 방법은 현재 형성되지 않은 바의 열림을 추적하는 것입니다.
마지막 바를 여는 시간을 얻으려면 SeriesInfoInteger() 기호, 시간 프레임 및 SERIES_LASTBAR_DATE 속성. 현재 바가 열리는 시간과 변수에 저장된 바의 시간을 지속적으로 비교하여 새로운 바가 나타나는 순간을 쉽게 감지할 수 있습니다. 다음과 같이 보일 수 있는 사용자 정의 함수 isNewBar()를 생성할 수 있습니다.
//+------------------------------------------------------------------+ //| Return true if a new bar appears for the symbol/period pair | //+------------------------------------------------------------------+ bool isNewBar() { //--- remember the time of opening of the last bar in the static variable static datetime last_time=0; //--- current time datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); //--- if it is the first call of the function if(last_time==0) { //--- set time and exit last_time=lastbar_time; return(false); } //--- if the time is different if(last_time!=lastbar_time) { //--- memorize time and return true last_time=lastbar_time; return(true); } //--- if we pass to this line then the bar is not new, return false return(false); }
기능 사용 예는 첨부된 Expert Advisor CheckLastBar.mq5에 나와 있습니다.
M1 시간대에 새 바가 표시된다는 CheckLastBar Expert Advisor의 메시지입니다.
보류 중인 주문 수 제한
한 계정에 동시에 할 수 있는 활성 보류 주문의 수를 제한해야 하는 경우 고유한 사용자 정의 함수를 작성할 수 있습니다. 이름을 지정하겠습니다. IsNewOrderAllowed(); 그것은 다른 보류 주문을 할 수 있는지 확인합니다. Automated Trading Championship의 규칙을 준수하도록 작성해 보겠습니다.
//+------------------------------------------------------------------+ //| Checks if it is allowed to place another order | //+------------------------------------------------------------------+ bool IsNewOrderAllowed() { //--- get the allowed number of pending orders on an account int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); //--- if there is no limitations, return true; you can send an order if(max_allowed_orders==0) return(true); //--- if we pass to this line, then there are limitations; detect how many orders are already active int orders=OrdersTotal(); //--- return the result of comparing return(orders<max_allowed_orders); }
기능은 간단합니다. max_allowed_orders 변수에 허용된 주문 수를 가져옵니다. 값이 0이 아니면 현재 주문 수와 비교합니다. 그러나 이 기능은 또 다른 가능한 제한을 고려하지 않습니다. 즉, 특정 기호에 의해 허용된 총 오픈 포지션 및 보류 중인 주문량에 대한 제한입니다.
특정 기호로 랏 수 제한
특정 기호로 열린 포지션의 크기를 얻으려면 먼저 PositionSelect() 함수를 사용하여 포지션을 선택해야 합니다. 그리고 그 후에야 PositionGetDouble()을 사용하여 열린 포지션의 볼륨을 요청할 수 있습니다. double 유형의 다양한 선택된 포지션의 속성을 반환합니다. 주어진 기호로 포지션 볼륨을 가져오는 PostionVolume() 함수를 작성해 보겠습니다.
//+------------------------------------------------------------------+ //| Returns the size of position by a specific symbol | //+------------------------------------------------------------------+ double PositionVolume(string symbol) { //--- try to select a positions by a symbol bool selected=PositionSelect(symbol); //--- the position exists if(selected) //--- return the position volume return(PositionGetDouble(POSITION_VOLUME)); else { //--- report about the unsuccessful attempt to select the position Print(__FUNCTION__," Failed to execute PositionSelect() for the symbol ", symbol," Error ",GetLastError()); return(-1); } }
기호로 보류 중인 주문을 하기 위해 거래를 요청하기 전에 해당 기호(SYMBOL_VOLUME_LIMIT)에 의한 미결 포지션 및 보류 중인 주문의 총량에 대한 제한을 확인해야 합니다. 제한이 없는 경우 보류 중인 주문의 볼륨은 SymbolInfoDouble() 볼륨을 사용하여 수신할 수 있는 최대 허용 볼륨을 초과할 수 없습니다.
double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT); if(max_volume==0) volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
그러나 이 접근 방식은 지정된 기호로 현재 보류 중인 주문의 양을 고려하지 않습니다. 이 값을 계산하는 함수를 작성해 보겠습니다.
//+------------------------------------------------------------------+ //| Returns the size of position by a specified symbol | //+------------------------------------------------------------------+ double PositionVolume(string symbol) { //--- try to select a position by a symbol bool selected=PositionSelect(symbol); //--- the position exist if(selected) //--- return the position volume return(PositionGetDouble(POSITION_VOLUME)); else { //--- return zero if there is no position return(0); } }
오픈 포지션의 양과 미결 주문의 양을 고려하여 최종 확인은 다음과 같습니다.
//+------------------------------------------------------------------+ //| Returns maximum allowed volume for an order by a symbol | //+------------------------------------------------------------------+ double NewOrderAllowedVolume(string symbol) { double allowed_volume=0; //--- get the limitation on the maximum volume of an order double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); //--- get the limitation of volume by a symbol double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT); //--- get the volume of open position by a symbol double opened_volume=PositionVolume(symbol); if(opened_volume>=0) { //--- if we already used available volume if(max_volume-opened_volume<=0) return(0); //--- volume of the open position doen't exceed max_volume double orders_volume_on_symbol=PendingsVolume(symbol); allowed_volume=max_volume-opened_volume-orders_volume_on_symbol; if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume; } return(allowed_volume); }
이 섹션에서 언급한 기능이 포함된 Check_Order_And_Volume_Limits.mq5 Expert Advisor의 전체 코드는 글에 첨부되어 있습니다.
Automated Trading Championship 2010 참가자의 계정에서 Check_Order_And_Volume_Limits Expert Advisor를 사용하여 확인하는 예.
볼륨의 정확성 확인
모든 거래 로봇의 중요한 부분은 거래 작업을 수행하기 위해 올바른 볼륨을 선택하는 기능입니다. 여기서 우리는 자금 관리 및 위험 관리 시스템에 대해 이야기하지 않고 해당 심볼의 속성에 따라 올바른 볼륨에 대해 이야기할 것입니다.
식별자 | 설명 | 재산 유형 |
SYMBOL_VOLUME_MIN | 거래에 대한 최소 볼륨 | 더블 |
SYMBOL_VOLUME_MAX | 거래에 대한 최대 볼륨 | 더블 |
SYMBOL_VOLUME_STEP | 거래 실행을 위한 최소 볼륨 변경 단계 | 더블 |
이러한 검증을 수행하기 위해 사용자 정의 함수 CheckVolumeValue()를 작성할 수 있습니다.
//+------------------------------------------------------------------+ //| Check the correctness of volume of an order | //+------------------------------------------------------------------+ bool CheckVolumeValue(double volume,string &description) { //--- Minimum allowed volume for trade operations double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN); if(volume<min_volume) { description=StringFormat("Volume is less than the minimum allowed SYMBOL_VOLUME_MIN=%.2f",min_volume); return(false); } //--- Maximum allowed volume for trade opertations double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX); if(volume>max_volume) { description=StringFormat("Volume is greater than the maximum allowed SYMBOL_VOLUME_MAX=%.2f",max_volume); return(false); } //--- get the minimal volume change step double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP); int ratio=(int)MathRound(volume/volume_step); if(MathAbs(ratio*volume_step-volume)>0.0000001) { description=StringFormat("Volume is not a multiple of minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f", volume_step,ratio*volume_step); return(false); } description="Correct value of volume "; return(true); }
글에 첨부된 CheckVolumeValue.mq5 스크립트를 사용하여 이 기능의 작동을 확인할 수 있습니다.
볼륨이 올바른지 확인하는 CheckVolumeValue.mq5의 메시지입니다.
결론
이 글에서는 자신의 자동 거래 시스템을 만들 때 직면할 수 있는 Expert Advisor 작업의 가능한 제한 사항에 대한 기본 확인을 설명합니다. 이러한 예는 거래 계정에 대한 Expert Advisor의 운영 중에 확인해야 하는 모든 가능한 조건을 다루지는 않습니다. 그러나 이 예제가 초보자가 MQL5 언어에서 가장 인기 있는 검증을 구현하는 방법을 이해하는 데 도움이 되기를 바랍니다.
MetaQuotes 소프트웨어 사를 통해 러시아어가 번역됨.
원본 기고글: https://www.mql5.com/ru/articles/22
![자신만의 추적 손절매 만드는 법](https://c.mql5.com/2/0/Trailing_Stop_MQL5.png)
![하나의 지표를 다른 지표에 적용하기](https://c.mql5.com/2/0/indikators_001.png)
![MQL5에서 다중 색상 표시기 만들기](https://c.mql5.com/2/0/paint_indicator_MQL5__1.png)
![최후의 성전](https://c.mql5.com/2/0/Point_and_Figure_chart_MQL5.png)