侦云取势 发表于 2025-3-31 13:49:35

布林突破加均线过滤源码

#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property description "Bollinger Bands Squeeze with MA Filter Strategy"

#include <Trade/Trade.mqh>

//--- 输入参数
input int      BandsPeriod = 20;         // 布林带周期
input double   BandsDeviations = 2.0;      // 标准差倍数
input double   WidthMultiplier = 1.1;      // 宽度乘数
input int      LookbackPeriod = 20;      // 回溯周期
input double   LotSize = 0.1;            // 交易手数
input ulong    MagicNumber = 123456;       // 魔术码
input int      Slippage = 3;               // 滑点
input int      TakeProfitPoints = 6000;    // 止盈点数
input int      StopLossPoints = 5000;      // 止损点数
input int      MA1_Period = 5;             // 均线1周期
input int      MA2_Period = 10;            // 均线2周期
input int      MA3_Period = 15;            // 均线3周期
input int      MA4_Period = 20;            // 均线4周期
input int      MA5_Period = 60;            // 均线5周期

//--- 全局变量
int handleBands;
int handleMA1, handleMA2, handleMA3, handleMA4, handleMA5;
CTrade trade;

//+------------------------------------------------------------------+
//| Expert initialization function                                 |
//+------------------------------------------------------------------+
int OnInit()
{
   // 初始化指标句柄
   handleBands = iBands(_Symbol, _Period, BandsPeriod, 0, BandsDeviations, PRICE_CLOSE);
   handleMA1 = iMA(_Symbol, _Period, MA1_Period, 0, MODE_SMA, PRICE_CLOSE);
   handleMA2 = iMA(_Symbol, _Period, MA2_Period, 0, MODE_SMA, PRICE_CLOSE);
   handleMA3 = iMA(_Symbol, _Period, MA3_Period, 0, MODE_SMA, PRICE_CLOSE);
   handleMA4 = iMA(_Symbol, _Period, MA4_Period, 0, MODE_SMA, PRICE_CLOSE);
   handleMA5 = iMA(_Symbol, _Period, MA5_Period, 0, MODE_SMA, PRICE_CLOSE);

   // 检查指标是否创建成功
   if(handleBands == INVALID_HANDLE ||
      handleMA1 == INVALID_HANDLE ||
      handleMA2 == INVALID_HANDLE ||
      handleMA3 == INVALID_HANDLE ||
      handleMA4 == INVALID_HANDLE ||
      handleMA5 == INVALID_HANDLE)
   {
      Print("Failed to initialize indicators!");
      return(INIT_FAILED);
   }

   trade.SetExpertMagicNumber(MagicNumber);
   trade.SetDeviationInPoints(Slippage);
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 持仓检查函数                                                   |
//+------------------------------------------------------------------+
bool HasPosition()
{
   for(int i=PositionsTotal()-1; i>=0; i--)
      if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
         return true;
   return false;
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
   static datetime prevBarTime = 0;
   datetime currentTime = iTime(_Symbol, _Period, 0);

   if(currentTime == prevBarTime) return;
   prevBarTime = currentTime;

   // 获取布林带数据
   double upper[], middle[], lower[];
   ArraySetAsSeries(upper, true);
   ArraySetAsSeries(middle, true);
   ArraySetAsSeries(lower, true);

   if(CopyBuffer(handleBands, 1, 0, LookbackPeriod+1, upper) <= 0 ||
      CopyBuffer(handleBands, 0, 0, LookbackPeriod+1, middle) <= 0 ||
      CopyBuffer(handleBands, 2, 0, LookbackPeriod+1, lower) <= 0)
   {
      Print("Error copying Bollinger Bands data!");
      return;
   }

   // 计算当前布林带宽度
   double currentWidth = upper - lower;

   // 寻找过去N个宽度中的最小值
   double minWidth = DBL_MAX;
   for(int i=1; i<=LookbackPeriod; i++) {
      double w = upper - lower;
      if(w < minWidth) minWidth = w;
   }

   // 获取均线数据(前一根K线的值)
   double ma1, ma2, ma3, ma4, ma5;
   if(CopyBuffer(handleMA1, 0, 0, 2, ma1) < 2 ||
      CopyBuffer(handleMA2, 0, 0, 2, ma2) < 2 ||
      CopyBuffer(handleMA3, 0, 0, 2, ma3) < 2 ||
      CopyBuffer(handleMA4, 0, 0, 2, ma4) < 2 ||
      CopyBuffer(handleMA5, 0, 0, 2, ma5) < 2)
   {
      Print("Failed to copy MA buffers!");
      return;
   }

   // 判断均线排列条件
   bool isLongMA = ma1 > ma2 && ma2 > ma3 && ma3 > ma4 && ma4 > ma5;
   bool isShortMA = ma1 < ma2 && ma2 < ma3 && ma3 < ma4 && ma4 < ma5;

   // 获取价格数据
   double lastClose = iClose(_Symbol, _Period, 1);

   // 交易信号检测
   if(!HasPosition() && currentWidth < minWidth * WidthMultiplier)
   {
      // 多单入场条件
      if(isLongMA && lastClose > upper)
      {
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
         double sl = NormalizeDouble(ask - StopLossPoints * _Point, _Digits);
         double tp = NormalizeDouble(ask + TakeProfitPoints * _Point, _Digits);
         trade.Buy(LotSize, _Symbol, ask, sl, tp, "BB Buy Entry");
      }
      // 空单入场条件
      else if(isShortMA && lastClose < lower)
      {
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
         double sl = NormalizeDouble(bid + StopLossPoints * _Point, _Digits);
         double tp = NormalizeDouble(bid - TakeProfitPoints * _Point, _Digits);
         trade.Sell(LotSize, _Symbol, bid, sl, tp, "BB Sell Entry");
      }
   }
}

页: [1]
查看完整版本: 布林突破加均线过滤源码

人生者,生存也。
生存所需,财(钱)官(权)也。
财自食伤(子孙福德爻)生,
印星生身荫护,官财印全,适合人间生存也。
若命缺财,缺官,则失去生存权。
一旦脱离父母养育,将天天面临,
从绝望中醒来,又从绝望中睡去。来去如烟!