//+------------------------------------------------------------------+
//| TrendBands.mq4 |
//| Generated by OpenAI Assistant |
//| https://www.openai.com |
//+------------------------------------------------------------------+
#property copyright "OpenAI Assistant"
#property version "1.00"
#property strict
//--- 输入参数
input int BandsPeriod=20; // 布林带周期
input double BandsDeviation=2.0; // 标准差倍数
input int ATRPeriod=14; // ATR周期
input double VolatilityThreshold=0.05; // 波动率阈值(5%)
input bool UseVolumeFilter=true; // 启用成交量过滤
input int VolumeLookback=14; // 成交量回溯周期
input double VolumeMultiplier=1.5; // 成交量倍数
input int StopLoss=50; // 止损点数
input int TakeProfit=100; // 止盈点数
input bool UseTrailingStop=true; // 启用追踪止损
input int TrailingStopPoints=20; // 追踪止损点数
//--- 全局变量
int handleBands, handleATR, handleVolMA;
double prevBandsWidth;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
handleBands = iBands(_Symbol, PERIOD_H1, BandsPeriod, 0, BandsDeviation, PRICE_CLOSE);
handleATR = iATR(_Symbol, PERIOD_H1, ATRPeriod);
handleVolMA = iMA(_Symbol, PERIOD_H1, VolumeLookback, 0, MODE_SMA, VOLUME_TICK);
if(handleBands == INVALID_HANDLE ||
handleATR == INVALID_HANDLE ||
handleVolMA == INVALID_HANDLE)
{
Alert("指标初始化失败!");
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 检查当前持仓
if(PositionSelect(_Symbol)) return;
// 获取指标值
double upper[1], middle[1], lower[1];
CopyBuffer(handleBands, 1, 0, 1, upper);
CopyBuffer(handleBands, 0, 0, 1, middle);
CopyBuffer(handleBands, 2, 0, 1, lower);
// 获取收盘价和成交量
double close[1];
CopyClose(_Symbol, PERIOD_H1, 0, 1, close);
// 计算布林带宽度
double bandsWidth = (upper[0] - lower[0]) / middle[0];
// 波动率过滤
if(bandsWidth <= VolatilityThreshold) return;
// 成交量过滤
if(UseVolumeFilter)
{
double volume[1], volMA[1];
CopyBuffer(handleVolMA, 0, 0, 1, volMA);
CopyTickVolume(_Symbol, PERIOD_H1, 0, 1, volume);
if(volume[0] < (volMA[0] * VolumeMultiplier)) return;
}
// 交易信号
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
if(close[0] > middle[0]) // 买入信号
{
double sl = ask - StopLoss * _Point;
double tp = ask + TakeProfit * _Point;
OrderSend(_Symbol, OP_BUY, 0.1, ask, 3, sl, tp, "Buy Order", 0);
}
else if(close[0] < middle[0]) // 卖出信号
{
double sl = bid + StopLoss * _Point;
double tp = bid - TakeProfit * _Point;
OrderSend(_Symbol, OP_SELL, 0.1, bid, 3, sl, tp, "Sell Order", 0);
}
// 追踪止损
if(UseTrailingStop)
{
CheckTrailingStop();
}
}
//+------------------------------------------------------------------+
//| 追踪止损功能 |
//+------------------------------------------------------------------+
void CheckTrailingStop()
{
for(int i = PositionsTotal()-1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol)
{
ulong ticket = PositionGetInteger(POSITION_TICKET);
double currentProfit = PositionGetDouble(POSITION_PROFIT);
double currentStop = PositionGetDouble(POSITION_SL);
double positionType = PositionGetInteger(POSITION_TYPE);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
if(positionType == POSITION_TYPE_BUY)
{
double newSl = SymbolInfoDouble(_Symbol, SYMBOL_BID) - TrailingStopPoints * _Point;
if(newSl > currentStop && newSl > openPrice)
{
PositionModify(ticket, newSl, PositionGetDouble(POSITION_TP));
}
}
else if(positionType == POSITION_TYPE_SELL)
{
double newSl = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + TrailingStopPoints * _Point;
if(newSl < currentStop && newSl < openPrice)
{
PositionModify(ticket, newSl, PositionGetDouble(POSITION_TP));
}
}
}
}
}
|