AK-47 Scalper EA:MetaTrader 5的高效交易助手

Mike 2023.06.12 03:06 32 0 0
附件

大家好,今天来聊聊一款非常实用的交易助手——AK-47 Scalper EA,它专为MetaTrader 5平台设计,能够帮助我们有效捕捉市场机会。

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点
double   Pips2Double;    // 止损 15点
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/ 专家Tick函数

//+------------------------------------------------------------------+
//| 专家Tick函数 |
//+------------------------------------------------------------------+
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)  //检查开盘价与当前Bid的距离
         && CheckStopLoss(OpenPrice,  SL, TP)                       //检查止损和止盈的距离
         && 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)   //检查开盘价与当前Bid的距离
         && CheckStopLoss(OpenPrice,  SL, TP)                                             //检查止损和止盈的距离
         && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_BUY))  //检查资金是否满足交易
      {
         if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))// 使用"ORDER_TIME_GTC"时过期日期 = 0
         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具有“追踪止损”功能, SL会在每次价格变动时调整(下移)

//+------------------------------------------------------------------+
//| 追踪止损 |
//+------------------------------------------------------------------+
void TrailingStop() {

   double SL_in_Pip = 0;

   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      if(m_position.SelectByIndex(i)) {    // 根据索引选择订单以便进一步访问其属性        
         if((m_position.Magic() == InpMagicNumber) && (m_position.Symbol() == m_symbol.Name())) {
            // 买单
            if(m_position.PositionType() == POSITION_TYPE_BUY) {
               //--计算SL在价格变化时
               SL_in_Pip = NormalizeDouble(Bid - m_position.StopLoss(), _Digits) / Pips2Double;
               if(SL_in_Pip > InpSL_Pips) {
                  double newSL = NormalizeDouble(Bid - InpSL_Pips * Pips2Double, _Digits);
                  
                  if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) {
                     Print(__FUNCTION__,"--> 修改订单错误 ", m_trade.ResultComment());
                   continue  
              }
       }
            }

            //卖单
            else if(m_position.PositionType() == POSITION_TYPE_SELL) {
               //--计算SL在价格变化时
               SL_in_Pip = NormalizeDouble(m_position.StopLoss() - Bid, _Digits) / Pips2Double;
               if(SL_in_Pip > InpSL_Pips){
                  double newSL = NormalizeDouble(Bid + (InpSL_Pips) * Pips2Double, _Digits);
                  if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) {
                     Print(__FUNCTION__,"--> 修改订单错误 ", m_trade.ResultComment());
                     //continue;  
                }
               }
            }
         }
      }
   }
   //--- 修改挂单
   for(int i=OrdersTotal()-1; i>=0; i--) {// 返回当前订单数
      if(m_order.SelectByIndex(i)) {      // 根据索引选择挂单以便进一步访问其属性
         if(m_order.Symbol() == m_symbol.Name() && m_order.Magic()==InpMagicNumber) {
            if(m_order.OrderType() == ORDER_TYPE_BUY_STOP) {
               SL_in_Pip = NormalizeDouble(Bid - m_order.StopLoss(), _Digits) / Pips2Double;
                  
               if(SL_in_Pip < InpSL_Pips/2) {
                  double newOP = NormalizeDouble(Bid + (InpSL_Pips/2) * Pips2Double, _Digits);
                  double newTP =  NormalizeDouble(newOP + InpTP_Pips * Pips2Double, _Digits);
                  double newSL = NormalizeDouble(Bid - (InpSL_Pips/2) * Pips2Double, _Digits);                  
                  if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) {
                     Print(__FUNCTION__,"--> 修改挂单错误!", m_trade.ResultComment());
                     continue  
              }
           //continue;  
               }
             }
         else if(m_order.OrderType() == ORDER_TYPE_SELL_STOP) {
               SL_in_Pip = NormalizeDouble(m_order.StopLoss() - Ask, _Digits) / Pips2Double;
           
               if(SL_in_Pip < InpSL_Pips/2){
                  double newOP = NormalizeDouble(Ask - (InpSL_Pips/2) * Pips2Double, _Digits);
                  double newTP =  NormalizeDouble(newOP - InpTP_Pips * Pips2Double, _Digits);
                  double newSL = NormalizeDouble(Ask + (InpSL_Pips/2) * Pips2Double, _Digits);
                  
                  if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) {
                     Print(__FUNCTION__,"--> 修改挂单错误!", m_trade.ResultComment());
                     //continue;  
                }
                     //continue;  
                }
             }
            }
            }
      }
  }
列表
评论 0