|
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property description "BB策略+MACD+ADX+时间过滤"
#include <Trade/Trade.mqh>
//--- 输入参数
input int BandsPeriod = 20; // 布林带周期
input double BandsDeviations = 2.0; // 标准差倍数
input double WidthMultiplier = 1.1; // 宽度乘数
input int LookbackPeriod = 20; // 回溯周期
input int FastEMA = 12; // MACD快线周期
input int SlowEMA = 26; // MACD慢线周期
input int SignalSMA = 9; // MACD信号线周期
input int ADXPeriod = 14; // ADX周期
input int ADXThreshold = 25; // ADX阈值
input int StartHour = 5; // 开始时间(小时)
input int EndHour = 16; // 结束时间(小时)
input bool EnableMonday = true; // 允许周一交易
input bool EnableTuesday = true; // 允许周二交易
input bool EnableWednesday = true; // 允许周三交易
input bool EnableThursday = true; // 允许周四交易
input bool EnableFriday = true; // 允许周五交易
input bool EnableSaturday = false; // 允许周六交易
input bool EnableSunday = false; // 允许周日交易
input double LotSize = 0.1; // 交易手数
input ulong MagicNumber = 123456; // 魔术码
input int Slippage = 3; // 滑点
input int TakeProfitPoints = 6000; // 止盈点数
input int StopLossPoints = 5000; // 止损点数
//--- 全局变量
int handleBands;
int handleMACD;
int handleADX;
CTrade trade;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 初始化指标
handleBands = iBands(_Symbol, _Period, BandsPeriod, 0, BandsDeviations, PRICE_CLOSE);
handleMACD = iMACD(_Symbol, _Period, FastEMA, SlowEMA, SignalSMA, PRICE_CLOSE);
handleADX = iADX(_Symbol, _Period, ADXPeriod);
if(handleBands == INVALID_HANDLE || handleMACD == INVALID_HANDLE || handleADX == INVALID_HANDLE){
Print("指标初始化失败");
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;
}
//+------------------------------------------------------------------+
//| 时间过滤函数 |
//+------------------------------------------------------------------+
bool TimeFilter()
{
MqlDateTime timeNow;
TimeCurrent(timeNow);
// 星期过滤
switch(timeNow.day_of_week){
case 0: if(!EnableSunday) return false; break;
case 1: if(!EnableMonday) return false; break;
case 2: if(!EnableTuesday) return false; break;
case 3: if(!EnableWednesday) return false; break;
case 4: if(!EnableThursday) return false; break;
case 5: if(!EnableFriday) return false; break;
case 6: if(!EnableSaturday) return false; break;
}
// 时段过滤
int currentHour = timeNow.hour;
if(currentHour < StartHour || currentHour >= EndHour) return false;
return true;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
static datetime prevBarTime = 0;
datetime currentTime = iTime(_Symbol, _Period, 0);
if(currentTime == prevBarTime) return;
prevBarTime = currentTime;
// 获取指标数据
double upper[], lower[], macdBuffer[], adxBuffer[];
ArraySetAsSeries(upper, true);
ArraySetAsSeries(lower, true);
ArraySetAsSeries(macdBuffer, true);
ArraySetAsSeries(adxBuffer, true);
// 复制布林带数据
if(CopyBuffer(handleBands, 1, 0, LookbackPeriod+1, upper) <= 0 ||
CopyBuffer(handleBands, 2, 0, LookbackPeriod+1, lower) <= 0) return;
// 复制MACD数据
if(CopyBuffer(handleMACD, 0, 0, 3, macdBuffer) <= 0) return;
double macdValue = macdBuffer[1];
// 复制ADX数据
if(CopyBuffer(handleADX, 0, 0, 3, adxBuffer) <= 0) return;
double adxValue = adxBuffer[1];
// 计算布林带宽度
double currentWidth = upper[0] - lower[0];
double minWidth = DBL_MAX;
for(int i=1; i<=LookbackPeriod; i++) {
double w = upper[i] - lower[i];
if(w < minWidth) minWidth = w;
}
// 获取价格数据
double lastClose = iClose(_Symbol, _Period, 1);
// 交易信号检测
if(!HasPosition() &&
currentWidth < minWidth * WidthMultiplier &&
adxValue > ADXThreshold &&
TimeFilter())
{
// 多单条件
if(lastClose > upper[1] && macdValue > 0)
{
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = ask - StopLossPoints * _Point;
double tp = ask + TakeProfitPoints * _Point;
trade.Buy(LotSize, _Symbol, ask, sl, tp, "多头入场");
}
// 空单条件
else if(lastClose < lower[1] && macdValue < 0)
{
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl = bid + StopLossPoints * _Point;
double tp = bid - TakeProfitPoints * _Point;
trade.Sell(LotSize, _Symbol, bid, sl, tp, "空头入场");
}
}
}
|
|