|
这是一个叫:ATRfilter1.ex5 和圆点指标.ex5 的mt5指标。
现在用中文,帮我写一个mt5 ea
多头:
多头过滤:ATRfilter1.ex5指标出现绿色时,才能开多单。
多头开单:满足多头过滤后,圆点指标.ex5指标参数最后长度为3慢长度为7出现ptl趋势开始DodgerBlue蓝色圆点,时开多
空头:
空头过滤:ATRfilter1.ex5指标出现红色时,才能开空单。
空头开单:满足空头过滤后.圆点指标.ex5参数last length为3 Slow length为7出现ptl trend start Crimson红色圆点,时开空
出口:
固定收益:盈利16000点清仓亏损5000点清仓,盈利6000点开启移动止盈。利润回撤30%清仓
//+------------------------------------------------------------------+
//| ExpertAdvisor_CN_MultiATR_TimeFilter_CustomPeriods.mq5 |
//| Gemini AI |
//| https://www.google.com |
//+------------------------------------------------------------------+
#property copyright "Gemini AI"
#property link "https://www.google.com"
#property version "1.30" // 版本更新
#property description "EA with customizable multi-period ATRfilter1, PerfectTrendLine, and Time Filter"
//--- 引入交易类库
#include <Trade\Trade.mqh>
CTrade trade;
//--- EA 通用输入参数
input group "交易手数与魔术手"
input double InpLots = 0.01; // 手数
input ulong InpMagicNumber = 12345; // 魔术手
input group "止盈止损设置 (点数)"
input int InpFixedProfitTargetPoints = 16000; // 固定止盈点数
input int InpFixedStopLossPoints = 5000; // 固定止损点数
input int InpTrailingStopStartPoints = 6000; // 移动止盈启动点数
input double InpTrailingStopPullbackPercent = 30.0; // 移动止盈回撤百分比
input group "ATRfilter1 指标参数" // 修改点:将所有三个周期设为输入
input double InpAtrPeriodMain = 14.0; // ATRfilter1 主周期
input double InpAtrPeriodFilter1 = 7.0; // ATRfilter1 过滤周期1
input double InpAtrPeriodFilter2 = 28.0; // ATRfilter1 过滤周期2
input ENUM_APPLIED_PRICE InpAtrAppliedPrice = PRICE_CLOSE; // ATRfilter1 应用价格
input group "圆点指标 (PerfectTrendLine) 参数"
input int InpPtlFastLength = 3; // 圆点指标 快速周期
input int InpPtlSlowLength = 7; // 圆点指标 慢速周期
input group "交易时间过滤"
input int InpTradeStartTimeHour = 6; // 开单开始小时 (0-23)
input int InpTradeEndTimeHour = 10; // 开单结束小时 (0-23, 不包含此小时)
input bool InpTradeOnSunday = false; // 周日是否开单 (服务器时间)
input bool InpTradeOnMonday = true; // 周一是否开单 (服务器时间)
input bool InpTradeOnTuesday = true; // 周二是否开单 (服务器时间)
input bool InpTradeOnWednesday = true; // 周三是否开单 (服务器时间)
input bool InpTradeOnThursday = true; // 周四是否开单 (服务器时间)
input bool InpTradeOnFriday = true; // 周五是否开单 (服务器时间)
input bool InpTradeOnSaturday = true; // 周六是否开单 (服务器时间)
//--- 指标句柄
int ExtATRfilter1HandleMain = INVALID_HANDLE; // 主周期 ATR
int ExtATRfilter1Handle_F1 = INVALID_HANDLE; // 过滤周期1 ATR (重命名句柄以匹配参数)
int ExtATRfilter1Handle_F2 = INVALID_HANDLE; // 过滤周期2 ATR (重命名句柄以匹配参数)
int ExtPerfectTrendLineHandle = INVALID_HANDLE;
//--- 用于移动止盈的静态变量
static double maxProfitLongPoints = 0;
static bool trailingActiveLong = false;
static double maxProfitShortPoints = 0;
static bool trailingActiveShort = false;
//--- 用于新Bar检测
static datetime PrevBarTime = 0;
//+------------------------------------------------------------------+
//| 检查当前小时是否允许交易 |
//+------------------------------------------------------------------+
bool IsTradingHourOK(int currentHour, int startHour, int endHour)
{
if (startHour == endHour)
{
return (startHour == 0);
}
if (startHour < endHour)
{
return (currentHour >= startHour && currentHour < endHour);
}
else
{
return (currentHour >= startHour || currentHour < endHour);
}
}
//+------------------------------------------------------------------+
//| 检查当前是否为允许的开单时间 (小时和星期) |
//+------------------------------------------------------------------+
bool IsTradingAllowedTimeForEntry()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
if (!IsTradingHourOK(dt.hour, InpTradeStartTimeHour, InpTradeEndTimeHour))
{
return false;
}
switch(dt.day_of_week)
{
case SUNDAY: if(!InpTradeOnSunday) return false; break;
case MONDAY: if(!InpTradeOnMonday) return false; break;
case TUESDAY: if(!InpTradeOnTuesday) return false; break;
case WEDNESDAY: if(!InpTradeOnWednesday) return false; break;
case THURSDAY: if(!InpTradeOnThursday) return false; break;
case FRIDAY: if(!InpTradeOnFriday) return false; break;
case SATURDAY: if(!InpTradeOnSaturday) return false; break;
default: return false;
}
return true;
}
//+------------------------------------------------------------------+
//| EA初始化函数 |
//+------------------------------------------------------------------+
int OnInit()
{
trade.SetExpertMagicNumber(InpMagicNumber);
trade.SetMarginMode();
trade.SetTypeFillingBySymbol(_Symbol);
// 加载 ATRfilter1 指标 (主周期)
ExtATRfilter1HandleMain = iCustom(_Symbol, _Period, "ATRfilter1", InpAtrPeriodMain, InpAtrAppliedPrice);
if(ExtATRfilter1HandleMain == INVALID_HANDLE){ Alert("加载 ATR 主周期 (",InpAtrPeriodMain,") 失败!"); return(INIT_FAILED); }
// 加载 ATRfilter1 指标 (过滤周期1) - 修改点:使用新的输入参数 InpAtrPeriodFilter1
ExtATRfilter1Handle_F1 = iCustom(_Symbol, _Period, "ATRfilter1", InpAtrPeriodFilter1, InpAtrAppliedPrice);
if(ExtATRfilter1Handle_F1 == INVALID_HANDLE){ Alert("加载 ATR 过滤周期1 (", InpAtrPeriodFilter1, ") 失败!"); return(INIT_FAILED); }
// 加载 ATRfilter1 指标 (过滤周期2) - 修改点:使用新的输入参数 InpAtrPeriodFilter2
ExtATRfilter1Handle_F2 = iCustom(_Symbol, _Period, "ATRfilter1", InpAtrPeriodFilter2, InpAtrAppliedPrice);
if(ExtATRfilter1Handle_F2 == INVALID_HANDLE){ Alert("加载 ATR 过滤周期2 (", InpAtrPeriodFilter2, ") 失败!"); return(INIT_FAILED); }
// 加载 圆点指标
ExtPerfectTrendLineHandle = iCustom(_Symbol, _Period, "圆点指标", InpPtlFastLength, InpPtlSlowLength);
if(ExtPerfectTrendLineHandle == INVALID_HANDLE){ Alert("加载 圆点指标 失败!"); return(INIT_FAILED); }
string tradingDays = StringFormat("Sun:%s Mon:%s Tue:%s Wed:%s Thu:%s Fri:%s Sat:%s",
(string)InpTradeOnSunday, (string)InpTradeOnMonday, (string)InpTradeOnTuesday,
(string)InpTradeOnWednesday, (string)InpTradeOnThursday, (string)InpTradeOnFriday,
(string)InpTradeOnSaturday);
// 修改点:更新Comment以反映可自定义的过滤周期
Comment("EA已启动\nATR 主:", InpAtrPeriodMain, ", 过滤1:", InpAtrPeriodFilter1, ", 过滤2:", InpAtrPeriodFilter2, // 使用新的输入参数名
"\n圆点指标 快:", InpPtlFastLength, ", 慢:", InpPtlSlowLength,
StringFormat("\n开单时间: %02d:00-%02d:00", InpTradeStartTimeHour, InpTradeEndTimeHour),
"\n开单星期: ", tradingDays);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| EA去初始化函数 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(ExtATRfilter1HandleMain != INVALID_HANDLE) IndicatorRelease(ExtATRfilter1HandleMain);
if(ExtATRfilter1Handle_F1 != INVALID_HANDLE) IndicatorRelease(ExtATRfilter1Handle_F1); // 使用更新后的句柄名
if(ExtATRfilter1Handle_F2 != INVALID_HANDLE) IndicatorRelease(ExtATRfilter1Handle_F2); // 使用更新后的句柄名
if(ExtPerfectTrendLineHandle != INVALID_HANDLE) IndicatorRelease(ExtPerfectTrendLineHandle);
Comment("");
}
//+------------------------------------------------------------------+
//| EA核心逻辑函数 (每个tick执行) |
//+------------------------------------------------------------------+
void OnTick()
{
ManagePositions();
if(!IsTradingAllowedTimeForEntry())
{
return;
}
// 修改点:检查所有三个ATR句柄
if(ExtATRfilter1HandleMain == INVALID_HANDLE || ExtATRfilter1Handle_F1 == INVALID_HANDLE || ExtATRfilter1Handle_F2 == INVALID_HANDLE || ExtPerfectTrendLineHandle == INVALID_HANDLE)
{
Alert("OnTick中检测到指标句柄无效!");
return;
}
datetime BarTime = (datetime)SeriesInfoInteger(_Symbol, _Period, SERIES_LASTBAR_DATE);
bool isNewBar = false;
if(PrevBarTime != BarTime)
{
PrevBarTime = BarTime;
isNewBar = true;
}
if(isNewBar)
{
double atr_color_buffer_main[1];
double atr_color_buffer_f1[1]; // 对应 ExtATRfilter1Handle_F1
double atr_color_buffer_f2[1]; // 对应 ExtATRfilter1Handle_F2
double ptl_arrow_val_buffer[1];
double ptl_arrow_color_buffer[1];
if(CopyBuffer(ExtATRfilter1HandleMain, 1, 1, 1, atr_color_buffer_main) <= 0) return;
int atr_filter_color_main = (int)atr_color_buffer_main[0];
// 修改点:从新的句柄和缓冲区获取过滤周期ATR数据
if(CopyBuffer(ExtATRfilter1Handle_F1, 1, 1, 1, atr_color_buffer_f1) <= 0) return;
int atr_filter_color_f1 = (int)atr_color_buffer_f1[0];
if(CopyBuffer(ExtATRfilter1Handle_F2, 1, 1, 1, atr_color_buffer_f2) <= 0) return;
int atr_filter_color_f2 = (int)atr_color_buffer_f2[0];
bool ptl_data_copied = true;
if(CopyBuffer(ExtPerfectTrendLineHandle, 7, 1, 1, ptl_arrow_val_buffer) <= 0) ptl_data_copied = false;
if(CopyBuffer(ExtPerfectTrendLineHandle, 8, 1, 1, ptl_arrow_color_buffer) <= 0) ptl_data_copied = false;
if(!ptl_data_copied) return;
double ptl_arrow_value = ptl_arrow_val_buffer[0];
int ptl_arrow_color = (int)ptl_arrow_color_buffer[0];
// 多头开单逻辑 - 修改点:使用三个ATR周期的颜色进行判断
bool long_atr_filter_passed = atr_filter_color_main == 1 && atr_filter_color_f1 == 1 && atr_filter_color_f2 == 1;
if(long_atr_filter_passed && ptl_arrow_value != EMPTY_VALUE && ptl_arrow_color == 0)
{
if(CountOpenPositions(POSITION_TYPE_BUY) == 0)
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double sl = price - InpFixedStopLossPoints * _Point;
double tp = price + InpFixedProfitTargetPoints * _Point;
if(trade.Buy(InpLots, _Symbol, price, sl, tp, "Long by EA CustATR TF"))
{
Print("多单开立成功 (自定义ATR周期, 时间过滤): ", trade.ResultRetcodeDescription());
ResetTrailingLong();
} else { Print("多单开立失败 (自定义ATR周期, 时间过滤): ", trade.ResultRetcodeDescription()); }
}
}
// 空头开单逻辑 - 修改点:使用三个ATR周期的颜色进行判断
bool short_atr_filter_passed = atr_filter_color_main == 2 && atr_filter_color_f1 == 2 && atr_filter_color_f2 == 2;
if(short_atr_filter_passed && ptl_arrow_value != EMPTY_VALUE && ptl_arrow_color == 1)
{
if(CountOpenPositions(POSITION_TYPE_SELL) == 0)
{
double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl = price + InpFixedStopLossPoints * _Point;
double tp = price - InpFixedProfitTargetPoints * _Point;
if(trade.Sell(InpLots, _Symbol, price, sl, tp, "Short by EA CustATR TF"))
{
Print("空单开立成功 (自定义ATR周期, 时间过滤): ", trade.ResultRetcodeDescription());
ResetTrailingShort();
} else { Print("空单开立失败 (自定义ATR周期, 时间过滤): ", trade.ResultRetcodeDescription()); }
}
}
}
}
//+------------------------------------------------------------------+
//| 计算当前持仓数量 |
//+------------------------------------------------------------------+
int CountOpenPositions(ENUM_POSITION_TYPE positionType)
{
int count = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
{
if(PositionGetInteger(POSITION_TYPE) == positionType)
{
count++;
}
}
}
return count;
}
//+------------------------------------------------------------------+
//| 管理现有持仓 (止盈, 止损, 移动止盈) |
//+------------------------------------------------------------------+
void ManagePositions()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == InpMagicNumber)
{
double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double current_price = SymbolInfoDouble(_Symbol, (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? SYMBOL_BID : SYMBOL_ASK);
double current_profit_points = 0;
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(position_type == POSITION_TYPE_BUY)
{
current_profit_points = (current_price - open_price) / _Point;
}
else if(position_type == POSITION_TYPE_SELL)
{
current_profit_points = (open_price - current_price) / _Point;
}
if(position_type == POSITION_TYPE_BUY)
{
if(current_profit_points >= InpTrailingStopStartPoints) trailingActiveLong = true;
if(trailingActiveLong)
{
if(current_profit_points > maxProfitLongPoints) maxProfitLongPoints = current_profit_points;
double close_threshold_profit_points = maxProfitLongPoints * (1.0 - InpTrailingStopPullbackPercent / 100.0);
if(current_profit_points < close_threshold_profit_points)
{
if(trade.PositionClose(ticket)){ Print("多单移动止盈平仓成功."); ResetTrailingLong(); }
else { Print("多单移动止盈平仓失败: ", trade.ResultRetcodeDescription()); }
}
}
}
else if(position_type == POSITION_TYPE_SELL)
{
if(current_profit_points >= InpTrailingStopStartPoints) trailingActiveShort = true;
if(trailingActiveShort)
{
if(current_profit_points > maxProfitShortPoints) maxProfitShortPoints = current_profit_points;
double close_threshold_profit_points = maxProfitShortPoints * (1.0 - InpTrailingStopPullbackPercent / 100.0);
if(current_profit_points < close_threshold_profit_points)
{
if(trade.PositionClose(ticket)){ Print("空单移动止盈平仓成功."); ResetTrailingShort(); }
else { Print("空单移动止盈平仓失败: ", trade.ResultRetcodeDescription()); }
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| 重置多头移动止盈状态 |
//+------------------------------------------------------------------+
void ResetTrailingLong()
{
maxProfitLongPoints = 0;
trailingActiveLong = false;
}
//+------------------------------------------------------------------+
//| 重置空头移动止盈状态 |
//+------------------------------------------------------------------+
void ResetTrailingShort()
{
maxProfitShortPoints = 0;
trailingActiveShort = false;
}
//+------------------------------------------------------------------+
|
|