시스템트레이딩 게시글

AK-47 스캘퍼 EA: MetaTrader 5를 위한 효과적인 트레이딩 시스템

첨부파일
44883.zip (5.94 KB, 다운로드 2회)

안녕하세요, 트레이더 여러분! 오늘은 MetaTrader 5에서 사용할 수 있는 강력한 스캘퍼 EA, "AK-47 EA"에 대해 이야기해보려고 합니다. 이 EA는 스캘핑 전략을 통해 단기 거래에서 수익을 극대화하도록 설계되었습니다.

1. 입력 파라미터

#define ExtBotName "AK-47 EA" // 봇 이름
#define  Version "1.00"

// 입력 클래스 가져오기
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
#include <Trade\OrderInfo.mqh>

//--- 코드 가독성을 위한 미리 정의된 변수 소개
#define Ask    SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define Bid    SymbolInfoDouble(_Symbol, SYMBOL_BID)

//--- 입력 파라미터
input string  EASettings         = "---------------------------------------------"; //-------- <EA 설정> --------
input int      InpMagicNumber    = 124656;   // 매직 넘버
input string  MoneySettings      = "---------------------------------------------"; //-------- <자금 설정> --------
input bool     isVolume_Percent  = true;     // 볼륨 퍼센트 허용
input double   InpRisk           = 3;        // 잔고의 리스크 비율 (%)
input string  TradingSettings    = "---------------------------------------------"; //-------- <거래 설정> --------
input double   Inpuser_lot       = 0.01;     // 로트
input double   InpSL_Pips        = 3.5;      // 손절(핍 단위)
input double   InpTP_Pips        = 7;        // 목표 수익(핍 단위) (0 = 목표 수익 없음)
input int      InpMax_slippage   = 3;        // 허용 최대 슬리피지(핍 단위)
input double   InpMax_spread     = 5;        // 허용 최대 스프레드(포인트 단위) (0 = 변동형)
input string   TimeSettings      = "---------------------------------------------"; //-------- <거래 시간 설정> --------
input bool     InpTimeFilter     = true;     // 거래 시간 필터
input int      InpStartHour      = 2;        // 시작 시간
input int      InpStartMinute    = 30;       // 시작 분
input int      InpEndHour        = 21       // 종료 시간
input int      InpEndMinute      = 0        // 종료 분

2. 로컬 변수 초기화

//--- 변수들
int      Pips2Points;    // 슬리피지  3핍    3=포인트    30=포인트
double   Pips2Double;    // 손절 15핍    0.015      0.0150
bool     isOrder = false;
int      slippage;
long     acSpread;
string   strComment = "";

CPositionInfo  m_position;                   // 거래 포지션 객체
CTrade         m_trade;                      // 거래 객체
CSymbolInfo    m_symbol;                     // 심볼 정보 객체
CAccountInfo   m_account;                    // 계좌 정보 래퍼
COrderInfo     m_order;                      // 미체결 주문 객체

3. 메인 코드

a/ 전문가 초기화 함수

//+------------------------------------------------------------------+
//| 전문가 초기화 함수                                   |
//+------------------------------------------------------------------+
int OnInit() {

   //3 또는 5자리 감지
   // 핍과 포인트
   if(_Digits % 2 == 1) {
      Pips2Double  = _Point*10;
      Pips2Points  = 10;
      slippage = 10* InpMax_slippage;
   }
   else {
      Pips2Double  = _Point;
      Pips2Points  =  1;
      slippage = InpMax_slippage;
   }
     
   if(!m_symbol.Name(Symbol())) // 심볼 이름 설정
      return(INIT_FAILED);
      
   RefreshRates();
//---
   m_trade.SetExpertMagicNumber(InpMagicNumber);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(slippage);
//---
   return(INIT_SUCCEEDED);
}

b/ 전문가 틱 함수

//+------------------------------------------------------------------+
//| 전문가 틱 함수                                             |
//+------------------------------------------------------------------+
void OnTick() {

   if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == false) {
      Comment("LazyBot\n거래가 허용되지 않습니다.");
      return;
   }
     
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.sec = 0;
   
   // 시작 시간 설정
   structTime.hour = InpStartHour;
   structTime.min = InpStartMinute;       
   datetime timeStart = StructToTime(structTime);
   
   // 종료 시간 설정
   structTime.hour = InpEndHour;
   structTime.min = InpEndMinute;
   datetime timeEnd = StructToTime(structTime);
   
   acSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   
   
   strComment = "\n" + ExtBotName + " - v." + (string)Version;
   strComment += "\n서버 시간 = " + TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS) + " - " + DayOfWeekDescription(structTime.day_of_week);
   strComment += "\n거래 시간 = [" + (string)InpStartHour + "h" + (string)InpStartMinute + " --> " +  (string)InpEndHour + "h" + (string)InpEndMinute + "]";
   
   strComment += "\n현재 스프레드 = " + (string)acSpread + " 포인트";
   
   Comment(strComment);
   
   // 값 업데이트
   UpdateOrders();
   
   TrailingStop();
      
   // 거래 조건
   if(InpTimeFilter) {
      if(TimeCurrent() >= timeStart && TimeCurrent() < timeEnd) {
         if(!isOrder) OpenOrder();
      }
   }
   else {
      if(!isOrder) OpenOrder();
   }
   
} //--- 함수 종료

3.1 주문 전송을 위한 신호 계산

//+------------------------------------------------------------------+
//| 신호 계산 및 주문 전송                                  |
//+------------------------------------------------------------------+
void OpenOrder(){
   
   ENUM_ORDER_TYPE OrdType = ORDER_TYPE_SELL;//-1;
  
   double TP = 0;
   double SL = 0;
   string comment = ExtBotName;
   
   // 로트 계산
   double lot1 = CalculateVolume();
   
   if(OrdType == ORDER_TYPE_SELL) {
      double OpenPrice = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      
      TP = OpenPrice - NormalizeDouble(InpTP_Pips * Pips2Double, _Digits);
      SL = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
         
      if(CheckSpreadAllow()                                             // 스프레드 확인
         && CheckVolumeValue(lot1)                                      // 볼륨 확인
         && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_SELL_STOP, OpenPrice)  // OpenPrice에서 Bid까지의 거리 확인
         && CheckStopLoss(OpenPrice,  SL, TP)                       // SL, TP와 OpenPrice 간의 거리 확인
         && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_SELL)) // 명령이 실행 가능한지 확인
      {
         if(!m_trade.SellStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))
         Print(__FUNCTION__,"--> 주문 전송 오류 ", m_trade.ResultComment());
      }
   }
   else if(OrdType == ORDER_TYPE_BUY) {
      double OpenPrice = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      SL = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      
      if(CheckSpreadAllow()                                             // 스프레드 확인
         && CheckVolumeValue(lot1)                                      // 볼륨 확인
         && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_BUY_STOP, OpenPrice)   // OpenPrice에서 Bid까지의 거리 확인
         && CheckStopLoss(OpenPrice,  SL, TP)                              // SL, TP와 OpenPrice 간의 거리 확인
         && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_BUY))  // 명령이 실행 가능한지 확인
      {
         if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))// 만료일이 0일 때는 "ORDER_TIME_GTC" 사용
         Print(__FUNCTION__,"--> 주문 전송 오류 ", m_trade.ResultComment());
      }
   }
   
}

3.2 볼륨 계산

//+------------------------------------------------------------------+
//| 볼륨 계산                                                 |
//+------------------------------------------------------------------+
// 포지션 크기를 계산하고 주문할 로트를 반환하는 함수입니다.
double CalculateVolume() {

   double LotSize = 0;

   if(isVolume_Percent == false) {
      LotSize = Inpuser_lot;
     }
   else {
      LotSize = (InpRisk) * m_account.FreeMargin();
      LotSize = LotSize /100000;
      double n = MathFloor(LotSize/Inpuser_lot);
      //Comment((string)n);
      LotSize = n * Inpuser_lot;
      
      if(LotSize < Inpuser_lot)
         LotSize = Inpuser_lot;

      if(LotSize > m_symbol.LotsMax()) LotSize = m_symbol.LotsMax();

      if(LotSize < m_symbol.LotsMin()) LotSize = m_symbol.LotsMin();
   }
     
//---
   return(LotSize);
}
3.3 EA의

연관 포스트

댓글 (0)