MQL5教程 06 EA开发实战

一、调用多指标多周期EA示例

shuju.mqh:

class shuju
  {
   public:
      shuju()
        {
        }     
      ~shuju()
        {
        }
      void MA(
         double &ma[],
         int count,
         string               symbol,            // 交易品种名称 
         ENUM_TIMEFRAMES      period,            // 周期 
         int                  ma_period,         // 平均周期 
         int                  ma_shift,          // 平移 
         ENUM_MA_METHOD       ma_method,         // 平滑类型 
         ENUM_APPLIED_PRICE   applied_price      // 价格或者处理程序类型 
        );
      void Bands( 
         double &Upper[],
         double &Lower[],
         double &Middle[],
         int count,
         string              symbol,            // 交易品种名称 
         ENUM_TIMEFRAMES     period,            // 周期 
         int                 bands_period,      // 平均线计算周期 
         int                 bands_shift,       // 指标平移 
         double              deviation,         // 标准差数 
         ENUM_APPLIED_PRICE  applied_price      // 价格或处理器类型 
        );
      void Stochastic( 
         double &data0[],
         double &data1[],
         int count,
         string           symbol,          // 交易品种名称 
         ENUM_TIMEFRAMES  period,          // 周期 
         int              Kperiod,         // K线周期 (用于计算的柱数) 
         int              Dperiod,         // D线周期 (开始平滑周期) 
         int              slowing,         // 最终平滑 
         ENUM_MA_METHOD   ma_method,       // 平滑类型 
         ENUM_STO_PRICE   price_field      // 随机计算法 
        );
      int getrates(MqlRates &rates[],int count,string symbol,ENUM_TIMEFRAMES tf);
  };

void shuju::MA(
   double               &ma[],
   int                  count,            // 复制总数
   string               symbol,           // 交易品种名称 
   ENUM_TIMEFRAMES      period,           // 周期 
   int                  ma_period,        // 平均周期 
   int                  ma_shift,         // 平移 
   ENUM_MA_METHOD       ma_method,        // 平滑类型 
   ENUM_APPLIED_PRICE   applied_price     // 价格或者处理程序类型 
  ){
  
   int ma_h = iMA(symbol,period,ma_period,ma_shift,ma_method,applied_price);
   ArraySetAsSeries(ma,true);
   CopyBuffer(ma_h,0,0,count,ma);
   IndicatorRelease(ma_h);
   
  }
  
void shuju::Bands( 
   double &Upper[],
   double &Lower[],
   double &Middle[],
   int count,
   string              symbol,            // 交易品种名称 
   ENUM_TIMEFRAMES     period,            // 周期 
   int                 bands_period,      // 平均线计算周期 
   int                 bands_shift,       // 指标平移 
   double              deviation,         // 标准差数 
   ENUM_APPLIED_PRICE  applied_price      // 价格或处理器类型 
  ){
  
   int h = iBands(symbol,period,bands_period,bands_shift,deviation,applied_price);
   ArraySetAsSeries(Upper, true);
   ArraySetAsSeries(Lower, true);
   ArraySetAsSeries(Middle, true);
   CopyBuffer(h,0,0,count,Middle);
   CopyBuffer(h,1,0,count,Upper);
   CopyBuffer(h,2,0,count,Lower);
   IndicatorRelease(h);
  }
  
void shuju::Stochastic( 
   double &data0[],
   double &data1[],
   int count,
   string           symbol,          // 交易品种名称 
   ENUM_TIMEFRAMES  period,          // 周期 
   int              Kperiod,         // K线周期 (用于计算的柱数) 
   int              Dperiod,         // D线周期 (开始平滑周期) 
   int              slowing,         // 最终平滑 
   ENUM_MA_METHOD   ma_method,       // 平滑类型 
   ENUM_STO_PRICE   price_field      // 随机计算法 
  ){
  
   int h = iStochastic(symbol,period,Kperiod,Dperiod,slowing,ma_method,price_field);
   ArraySetAsSeries(data0, true);
   ArraySetAsSeries(data1, true);
   CopyBuffer(h,0,0,count,data0);
   CopyBuffer(h,1,0,count,data1);
   IndicatorRelease(h);
  
  }
  
int shuju::getrates(MqlRates &rates[],int count,string symbol,ENUM_TIMEFRAMES tf)
  {
   ArraySetAsSeries(rates, true);
   return(CopyRates(symbol,tf,0,count,rates));
  }

jiaoyi.mqh:

class jiaoyi
  {
   public:
      ulong buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      ulong buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      ulong sell(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      ulong sellplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      void  closeallbuy(string symbol);
      void  closeallsell(string symbol);
  };
  
ulong jiaoyi::buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};
   request.action = TRADE_ACTION_DEAL;
   request.symbol = symbol;
   request.type   = ORDER_TYPE_BUY;
   request.volume = lots;
   request.deviation    = 100;
   request.type_filling = ORDER_FILLING_IOC;
   request.price        = SymbolInfoDouble(symbol,SYMBOL_ASK);
   // SYMBOL_TRADE_STOPS_LEVEL 设置止损/止盈时,与当前价格的最小距离限制(以点为单位)
   if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.sl = SymbolInfoDouble(symbol,SYMBOL_ASK) - slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.tp = SymbolInfoDouble(symbol,SYMBOL_ASK) + tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   request.comment = com;
   request.magic   = magic;
   // --- 发送请求
   if(!OrderSend(request, result))
      PrintFormat("OrderSend error %d", GetLastError()); // 如果不能发送请求,输出错误代码
   // --- 显示操作信息
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
   
   return(result.order);
  }
  
ulong jiaoyi::buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   ulong ticket = 0;
   int total = PositionsTotal();
   
   for(int i=total-1; i>=0; i--)
     {
      if(PositionGetTicket(i)>0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
            return(0);
        }
     }
     
   ticket = buy(symbol,lots,slpoint,tppoint,com,magic);
   return(ticket);
  }
  
ulong jiaoyi::sell(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};
   request.action = TRADE_ACTION_DEAL;
   request.symbol = symbol;
   request.type   = ORDER_TYPE_SELL;
   request.volume = lots;
   request.deviation    = 100;
   request.type_filling = ORDER_FILLING_IOC;
   request.price        = SymbolInfoDouble(symbol,SYMBOL_BID);

   if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.sl = SymbolInfoDouble(symbol,SYMBOL_BID) + slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.tp = SymbolInfoDouble(symbol,SYMBOL_BID) - tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   request.comment = com;
   request.magic   = magic;
   // --- 发送请求
   if(!OrderSend(request, result))
      PrintFormat("OrderSend error %d", GetLastError());
   // --- 显示操作信息
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
   
   return(result.order);
  }
  
ulong jiaoyi::sellplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   ulong ticket = 0;
   int total = PositionsTotal();
   
   for(int i=total-1; i>=0; i--)
     {
      if(PositionGetTicket(i)>0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
            return(0);
        }
     }
     
   ticket = sell(symbol,lots,slpoint,tppoint,com,magic);
   return(ticket);
  }
  
void jiaoyi::closeallbuy(string symbol)
  {
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket>0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
           {
            MqlTradeRequest request = {};
            MqlTradeResult  result  = {};
            request.action   = TRADE_ACTION_DEAL;                    // 交易操作类型
            request.symbol   = symbol;                               // 交易品种
            request.volume   = PositionGetDouble(POSITION_VOLUME);   // 交易量 
            request.type     = ORDER_TYPE_SELL;                      // 订单类型
            request.price    = SymbolInfoDouble(symbol,SYMBOL_BID);  // 持仓价格
            request.deviation= 100;                                  // 允许价格偏差
            request.type_filling=ORDER_FILLING_IOC;
            request.position = ticket;
            
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError()); 
           }
        }
     }
  }
  
void jiaoyi::closeallsell(string symbol)
  {
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket>0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
           {
            MqlTradeRequest request = {};
            MqlTradeResult  result  = {};
            request.action   = TRADE_ACTION_DEAL;                    // 交易操作类型
            request.symbol   = symbol;                               // 交易品种
            request.volume   = PositionGetDouble(POSITION_VOLUME);   // 交易量 
            request.type     = ORDER_TYPE_BUY;                       // 订单类型
            request.price    = SymbolInfoDouble(symbol,SYMBOL_ASK);  // 持仓价格
            request.deviation= 100;                                  // 允许价格偏差
            request.type_filling=ORDER_FILLING_IOC;
            request.position = ticket;
            
            if(!OrderSend(request,result))
               PrintFormat("OrderSend error %d",GetLastError()); 
           }
        }
     }
  }

EA:

#include <myClass/jiaoyi.mqh>
#include <myClass/shuju.mqh>

jiaoyi jy;
shuju  sj;

input double LOTS  = 0.01;    // 开仓手数
input int sl_point = 700;    // 止损点数
input int tp_point = 700;    // 止盈点数
input int MAGIC    = 12345;   // 幻数
input int little_period = 5;  // 小均线周期
input int large_period  = 10; // 大均线周期
input int bollinger_period  = 20;   // 布林带周期
input double bollinger_deviation = 2; // 布林带偏差
input int InpKPeriod = 5; // K period
input int InpDPeriod = 3; // D period
input int InpSlowing = 3; // Slowing

int OnInit()
  {
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   
  }

void OnTick()
  {
   double m30_ma_xiao[];   // 30分钟小周期MA
   sj.MA(m30_ma_xiao,4,Symbol(),PERIOD_M30,little_period,0,MODE_SMA,PRICE_CLOSE);
   double m30_ma_da[];     // 30分钟大周期MA
   sj.MA(m30_ma_da,4,Symbol(),PERIOD_M30,large_period,0,MODE_SMA,PRICE_CLOSE);
   
   double h4_ma_xiao[];    // H4小周期MA
   sj.MA(h4_ma_xiao,4,Symbol(),PERIOD_H4,little_period,0,MODE_SMA,PRICE_CLOSE);
   double h4_ma_da[];      // H4大周期MA
   sj.MA(h4_ma_da,4,Symbol(),PERIOD_H4,large_period,0,MODE_SMA,PRICE_CLOSE);
   
   double m30_bands_up[], m30_bands_low[], m30_bands_mid[];
   sj.Bands(m30_bands_up,m30_bands_low,m30_bands_mid,4,Symbol(),PERIOD_M30,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
   double h4_bands_up[], h4_bands_low[], h4_bands_mid[];
   sj.Bands(h4_bands_up,h4_bands_low,h4_bands_mid,4,Symbol(),PERIOD_H4,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
  
   double m30_k[], m30_d[];
   sj.Stochastic(m30_k,m30_d,4,Symbol(),PERIOD_M30,InpKPeriod,InpDPeriod,InpSlowing,MODE_SMA,STO_LOWHIGH);
   double h4_k[], h4_d[];
   sj.Stochastic(h4_k,h4_d,4,Symbol(),PERIOD_H4,InpKPeriod,InpDPeriod,InpSlowing,MODE_SMA,STO_LOWHIGH);
   
   MqlRates m30_rate[];
   sj.getrates(m30_rate,4,Symbol(),PERIOD_M30);
   MqlRates h4_rate[];
   sj.getrates(h4_rate,4,Symbol(),PERIOD_H4);
   
   // 开多单:H4K线下穿布林带下轨,且M30小周期均线在大周期均线之上,且M30指标KDJ金叉
   if(h4_rate[0].low<h4_bands_low[0] && m30_ma_xiao[0]>m30_ma_da[0] && m30_k[1]>m30_d[1] && m30_k[2]<m30_d[2])
      jy.buyplus(Symbol(),LOTS,sl_point,tp_point,"buy",MAGIC);
   // 平仓多单:在M30指标KDJ死叉
   if(m30_k[1]<m30_d[1] && m30_k[2]>m30_d[2])
      jy.closeallbuy(Symbol());
   
   // 开空单
   if(h4_rate[0].high>h4_bands_up[0] && m30_ma_xiao[0]<m30_ma_da[0] && m30_k[1]<m30_d[1] && m30_k[2]>m30_d[2])
      jy.sellplus(Symbol(),LOTS,sl_point,tp_point,"sell",MAGIC);   
   // 平仓空单
   if(m30_k[1]>m30_d[1] && m30_k[2]<m30_d[2])
      jy.closeallsell(Symbol());
   
  }

二、获取ZigZag顶点值

shuju.mqh:

class shuju
  {
   public:
      shuju()
        {
        }     
      ~shuju()
        {
        }
      void ZigZag(double &data0[],int count,ENUM_TIMEFRAMES period,int ExtDepth,int ExtDeviation,int ExtBackstep);
      void gettime(datetime &time[],int count);
      void getlow(double &Low[],int count);
  };

void shuju::ZigZag(double &data0[],int count,ENUM_TIMEFRAMES period,int ExtDepth,int ExtDeviation,int ExtBackstep)
  {
   int h = iCustom(Symbol(),period,"Examples/ZigZag",ExtDepth,ExtDeviation,ExtBackstep);
   ArraySetAsSeries(data0,true);
   CopyBuffer(h,0,0,count,data0);
   IndicatorRelease(h);
  }
  
void shuju::gettime(datetime &time[],int count)
  {
   ArraySetAsSeries(time,true);
   CopyTime(Symbol(),0,0,count,time);
  }
  
void shuju::getlow(double &Low[],int count)
  {
   ArraySetAsSeries(Low,true);
   CopyLow(Symbol(),0,0,count,Low);
  }

EA:

#include <myClass/shuju.mqh>

shuju  sj;

input int InpDepth    =12;  // Depth
input int InpDeviation=5;   // Deviation
input int InpBackstep =3;   // Back Step
input int geshu = 10;

double zigzag[][4];   // 只计入顶点值

int OnInit()
  {
   ArrayResize(zigzag, geshu);   // 设置新的第一维大小
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   
  }

void OnTick()
  {
   // ZigZag指标的顶点值为对应K线的最高/最低价,非顶点值为0
   double zigzagzhi[];
   int bars = Bars(Symbol(),0);  // 返回K嫌数量
   sj.ZigZag(zigzagzhi,bars,PERIOD_CURRENT,InpDepth,InpDeviation,InpBackstep);
   datetime time[];
   sj.gettime(time, bars);
   double low[];
   sj.getlow(low, bars);

   int counter = 0;
   for(int i=0; i<bars; i++)
     {
      if(counter>(geshu-1))
        {
         break;
        }
      if(zigzagzhi[i]>0)
        {
         zigzag[counter][0] = zigzagzhi[i];
         zigzag[counter][1] = i;
         zigzag[counter][2] = (double)time[i];
         if(zigzagzhi[i] <= low[i]) // 低点
           {
            zigzag[counter][3] = 1;
           }
         else  // 高点
           {
            zigzag[counter][3] = 2;
           }
         counter++;
        }
     }
  }

三、逆势加仓EA

jiaoyi.mqh:

class jiaoyi
  {
   public:
      int danshu(string symbol,ENUM_POSITION_TYPE type);
      ulong buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      ulong buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic);
      ulong zuijindan(string symbol,ENUM_POSITION_TYPE type,double &openprice,datetime &opentime,double &openlots,double &opensl,double &opentp,int magic);
      double formatlots(string symbol,double lots);
      void modifysltp(ENUM_POSITION_TYPE type,double sl,double tp);
  };
  
int jiaoyi::danshu(string symbol,ENUM_POSITION_TYPE type)
  {
   int count = 0;
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      ulong ticket = PositionGetTicket(i);
      if(ticket > 0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==type)
            count++;
        }
     }
     
   return(count);
  }
  
ulong jiaoyi::buy(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   MqlTradeRequest request = {};
   MqlTradeResult  result  = {};
   request.action = TRADE_ACTION_DEAL;
   request.symbol = symbol;
   request.type   = ORDER_TYPE_BUY;
   request.volume = lots;
   request.deviation    = 100;
   request.type_filling = ORDER_FILLING_IOC;
   request.price        = SymbolInfoDouble(symbol,SYMBOL_ASK);
   // SYMBOL_TRADE_STOPS_LEVEL 设置止损/止盈时,与当前价格的最小距离限制(以点为单位)
   if(slpoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.sl = SymbolInfoDouble(symbol,SYMBOL_ASK) - slpoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   if(tppoint>SymbolInfoInteger(symbol,SYMBOL_TRADE_STOPS_LEVEL))
     {
      request.tp = SymbolInfoDouble(symbol,SYMBOL_ASK) + tppoint*SymbolInfoDouble(symbol,SYMBOL_POINT);
     }
   request.comment = com;
   request.magic   = magic;
   // --- 发送请求
   if(!OrderSend(request, result))
      PrintFormat("OrderSend error %d", GetLastError()); // 如果不能发送请求,输出错误代码
   // --- 显示操作信息
   PrintFormat("retcode=%u  deal=%I64u  order=%I64u",result.retcode,result.deal,result.order);
   
   return(result.order);
  }
  
ulong jiaoyi::buyplus(string symbol,double lots,int slpoint,int tppoint,string com,int magic)
  {
   ulong ticket = 0;
   int total = PositionsTotal();
   
   for(int i=total-1; i>=0; i--)
     {
      if(PositionGetTicket(i)>0)
        {
         if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY && PositionGetInteger(POSITION_MAGIC)==magic && PositionGetString(POSITION_COMMENT)==com)
            return(0);
        }
     }
     
   ticket = buy(symbol,lots,slpoint,tppoint,com,magic);
   return(ticket);
  }
  
ulong jiaoyi::zuijindan(string symbol,ENUM_POSITION_TYPE type,double &openprice,datetime &opentime,double &openlots,double &opensl,double &opentp,int magic=0)
  {
   openprice = 0;
   opentime  = 0;
   openlots  = 0;
   opensl    = 0;
   opentp    = 0;
   ulong ticket = 0;
   int   total  = PositionsTotal();
   for(int i=total; i>=0; i--)
     {
      if(PositionGetTicket(i) > 0)
         {
            if(PositionGetString(POSITION_SYMBOL)==symbol && PositionGetInteger(POSITION_TYPE)==type && PositionGetInteger(POSITION_MAGIC)==magic)
              {
                 openprice=PositionGetDouble(POSITION_PRICE_OPEN);
                 opentime=(datetime)PositionGetInteger(POSITION_TIME);
                 openlots=PositionGetDouble(POSITION_VOLUME);
                 opensl=PositionGetDouble(POSITION_SL);
                 opentp=PositionGetDouble(POSITION_TP);
                 ticket=PositionGetInteger(POSITION_TICKET);
                 break;
              }
         }
     }
     
   return(ticket);
  }
  
double jiaoyi::formatlots(string symbol,double lots)
  {
   double final_lots = 0;
   double minilots=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
   double steplots=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
   
   if(lots<minilots)
      return(0);
   else
     {
      double temp = MathFloor(lots/minilots)*minilots;
      final_lots  = temp + MathFloor((lots-temp)/steplots)*steplots;
     }
   
   return(final_lots);
  }
  
void jiaoyi::modifysltp(ENUM_POSITION_TYPE type,double sl,double tp)
  {
   int total = PositionsTotal();
   for(int i=total-1; i>=0; i--)
     {
      if(PositionGetTicket(i)>0)
        {
         if(type==POSITION_TYPE_BUY)
           {
            // 止损止盈不等于原单子,才做修改。
            if((NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))||NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))))
              {
               MqlTradeRequest request= {};
               MqlTradeResult  result = {};
               request.action   = TRADE_ACTION_SLTP;
               request.position = PositionGetTicket(i);
               request.symbol   = Symbol();
               request.sl       = NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               request.tp       = NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(sl<0)
                  request.sl = NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(tp<0)
                  request.tp = NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(!OrderSend(request,result))
                  PrintFormat("OrderSend error %d",GetLastError());
              }
           }
         if(type==POSITION_TYPE_SELL)
           {
            if((NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))||NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))!=NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS))))
              {
               MqlTradeRequest request= {};
               MqlTradeResult  result = {};
               request.action   = TRADE_ACTION_SLTP;
               request.position = PositionGetTicket(i);
               request.symbol   = Symbol();
               request.sl       = NormalizeDouble(sl,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               request.tp       = NormalizeDouble(tp,(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(sl<0)
                  request.sl = NormalizeDouble(PositionGetDouble(POSITION_SL),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(tp<0)
                  request.tp = NormalizeDouble(PositionGetDouble(POSITION_TP),(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS));
               if(!OrderSend(request,result))
                  PrintFormat("OrderSend error %d",GetLastError());
                 }
           }
        }
     }
  }

shuju.mqh:

class shuju
  {
   public:
      shuju()
        {
        }     
      ~shuju()
        {
        }
      void getrates(MqlRates &rates[],int count);
      void shuju::Bands( 
         double &Upper[],
         double &Lower[],
         double &Middle[],
         int count,
         string              symbol,            // 交易品种名称 
         ENUM_TIMEFRAMES     period,            // 周期 
         int                 bands_period,      // 平均线计算周期 
         int                 bands_shift,       // 指标平移 
         double              deviation,         // 标准差数 
         ENUM_APPLIED_PRICE  applied_price      // 价格或处理器类型 
        );
      double getask();
  };

void shuju::getrates(MqlRates &rates[],int count)
  {
   ArraySetAsSeries(rates, true);
   CopyRates(Symbol(),PERIOD_CURRENT,0,count,rates);
  }
  
void shuju::Bands( 
   double &Upper[],
   double &Lower[],
   double &Middle[],
   int count,
   string              symbol,            // 交易品种名称 
   ENUM_TIMEFRAMES     period,            // 周期 
   int                 bands_period,      // 平均线计算周期 
   int                 bands_shift,       // 指标平移 
   double              deviation,         // 标准差数 
   ENUM_APPLIED_PRICE  applied_price      // 价格或处理器类型 
  ){
  
   int h = iBands(symbol,period,bands_period,bands_shift,deviation,applied_price);
   ArraySetAsSeries(Upper, true);
   ArraySetAsSeries(Lower, true);
   ArraySetAsSeries(Middle, true);
   CopyBuffer(h,0,0,count,Middle);
   CopyBuffer(h,1,0,count,Upper);
   CopyBuffer(h,2,0,count,Lower);
   IndicatorRelease(h);
  }
  
double shuju::getask()
  {
   return(SymbolInfoDouble(Symbol(),SYMBOL_ASK));
  }

EA:

#include <myClass/jiaoyi.mqh>
#include <myClass/shuju.mqh>

jiaoyi jy;
shuju  sj;

input double init_lots = 0.1; // 初始下单量
input int    loss_add_interbal_point = 100;  // 亏损加仓间隔点数
input double loss_add_multiple = 2; // 亏损加仓下单倍数
input int    syn_add_max_times = 5; // 同向单最多加仓次数
input int    call_back_tp_point = 200; // 回调止盈点数
input int    bollinger_period = 20;
input double bollinger_deviation =2;
input int    MAGIC = 12345;

datetime buytime=0;
MqlRates rate[];

int OnInit()
  {
   sj.getrates(rate, 4);
   buytime = rate[0].time;
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   
  }

void OnTick()
  {
   // 这里只展示开多单部分
   sj.getrates(rate, 4);
   double bandsup[], bandslow[], bandsmid[];
   sj.Bands(bandsup,bandslow,bandsmid,4,Symbol(),PERIOD_CURRENT,bollinger_period,0,bollinger_deviation,PRICE_CLOSE);
   int buydanshu = jy.danshu(Symbol(), POSITION_TYPE_BUY);
   // 条件 buytime!=rate[0].time 是为了一根K线只开一个单。
   if(buydanshu==0)
     {
      // 上一根K线的开盘价收盘价均脱离布林带下轨,且再上一根K线最低价触碰到布林带下轨,则开多单。
      if(buytime!=rate[0].time && rate[1].open>bandslow[1] && rate[1].close>bandslow[1] && rate[2].low<bandslow[2])
      {
         if(jy.buyplus(Symbol(),init_lots,0,call_back_tp_point,"buy",MAGIC) > 0)
            buytime = rate[0].time;
      }
     }
   else
     {
      double open_price, open_lots, open_sl, open_tp;
      datetime open_time;
      jy.zuijindan(Symbol(),POSITION_TYPE_BUY,open_price,open_time,open_lots,open_sl,open_tp,MAGIC);
      // 修改此前所有单的止盈价为最后一单的止盈价
      jy.modifysltp(POSITION_TYPE_BUY, -1, open_tp); // 止损设为负值,则表示不修改止损
      if(buydanshu<=syn_add_max_times && (open_price-sj.getask()) >= loss_add_interbal_point*Point())
        {
         // 逆势加仓
         jy.buyplus(Symbol(),jy.formatlots(Symbol(), open_lots*loss_add_multiple),0,call_back_tp_point,"buy"+IntegerToString(buydanshu),MAGIC);
        }
     }
  }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值