最后由 Jiayee85 于 2026-3-15 17:17 编辑
上一篇我们拆解了MT4自带的Moving Average这个EA(传送门:https://www.eahub.cn/thread-179123-1-1.html),发现这个原厂自带的EA过了20年依然能够盈利,但是EA本身也存在一些问题,那么我们就针对这些问题进行一一调整。
1.最小仓位不能小于0.1手
这是原代码中这一段语句造成的
if(lot<0.1) lot=0.1;
很简单,修改一下就可以了,改成如下
if(lot<0.01) lot=0.01;
这样最小仓位就可以开到0.01手,让账户资金利用更灵活。
2.魔术码为固定默认值,一次只能交易一个品种或者图表
这是原代码中这一段语句造成的
#define MAGICMA 20131111
我们只需要把预设值改成外设值,就可以每次在加载EA的时候设置不一样的魔术码,这样就能在不同的品种和图表上加载使用这个EA了。
改成如下:
input int MAGICMA =2026888;
记得每个图表加载EA的时候要修改魔术码,可以是任意值,只要不重复就行。
3.没有初始止盈和止损,订单开仓以后可能会影响持仓的心态,而且只能通过平仓信号平仓有点不够灵活
这是原代码中这一段语句造成的,源代码中止损止盈为0
res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,0,0,"",MAGICMA,0,Red); // 发送卖出订单
res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,0,0,"",MAGICMA,0,Blue); // 发送买入订单
这里很简单,只需要在程序发送订单时,我们把初始止损和止盈加进去就可以了
首先在参数外设区域加上止损和止盈,方便EA进行测试和使用
input double TakeProfit =200; // 固定初始止盈
input double StopLoss =200; // 固定初始止损
然后把上面的订单发送语句修改一下就可以了
res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,Bid+StopLoss*Point,Bid-TakeProfit*Point,"",MAGICMA,0,Red); // 发送卖出订单
res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,Ask-StopLoss*Point,Ask+TakeProfit*Point,"",MAGICMA,0,Blue); // 发送买入订单
这样在EA开仓的时候就会有初始止损和止盈,搭配好其它参数,已经可以实现不同的交易逻辑,比如小止损大止盈的趋势策略,比如大止损小止盈的剥头皮策略,比如小止损小止盈的刷单策略。
4.没有移动止损功能,获利的订单有可能变为亏损,我个人是不太用,因为已经有主动平仓功能,其实不太用得到,但是本着“可以不用,不能没有”的原则,我们还是把它加上,然后设置一个是否开启移动止损功能的开关
在输入参数区域增加以下代码
//--- 新增移动止损参数
input bool UseTrailingStop = true; // 启用移动止损开关
input int TrailingStop = 100; // 移动止损点数
input int TrailingStep = 20; // 移动步长点数
input double ActivationProfit = 50; // 激活移动止损所需最小盈利(点数)
然后在模块区域增加移动止损模块
//+------------------------------------------------------------------+
//| 移动止损功能 |
//+------------------------------------------------------------------+
void TrailingStopCheck()
{
//--- 如果移动止损未启用,直接返回
if(!UseTrailingStop) return;
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break;
if(OrderMagicNumber()!=MAGICMA || OrderSymbol()!=Symbol()) continue;
//--- 多单移动止损逻辑
if(OrderType()==OP_BUY)
{
// 计算当前盈利点数
double currentBProfit = (Bid - OrderOpenPrice()) / Point;
// 检查是否达到激活盈利
if(currentBProfit < ActivationProfit) continue;
// 计算新的止损价格
double newBStopLoss = NormalizeDouble(Bid - TrailingStop * Point, Digits);
// 确保新止损价格合理:高于当前止损且低于当前价格
if(newBStopLoss > OrderStopLoss() && newBStopLoss < Bid - 5*Point)
{
// 修改止损
if(!OrderModify(OrderTicket(), OrderOpenPrice(), newBStopLoss, OrderTakeProfit(), 0, Blue))
Print("修改多单止损失败,错误码: ", GetLastError());
}
}
//--- 空单移动止损逻辑
if(OrderType()==OP_SELL)
{
// 计算当前盈利点数
double currentSProfit = (OrderOpenPrice() - Ask) / Point;
// 检查是否达到激活盈利
if(currentSProfit < ActivationProfit) continue;
// 计算新的止损价格
double newSStopLoss = NormalizeDouble(Ask + TrailingStop * Point, Digits);
// 确保新止损价格合理:低于当前止损且高于当前价格
if((OrderStopLoss()==0 || newSStopLoss < OrderStopLoss()) && newSStopLoss > Ask + 5*Point)
{
// 修改止损
if(!OrderModify(OrderTicket(), OrderOpenPrice(), newSStopLoss, OrderTakeProfit(), 0, Red))
Print("修改空单止损失败,错误码: ", GetLastError());
}
}
}
}
然后在主函数onTick里加上移动止损模块就搞定了
//--- 新增:在每次跳动点检查移动止损
TrailingStopCheck();
//---
5.如果价格在均线上下震荡,会频繁亏损。没有完美的策略,趋势策略就是这样的,不要指望趋势策略能解决震荡行情。
那怎么办?
常见的解决思路有这几个:
放大图表周期或者均线,用大周期来规避小周期的震荡;
连续亏损几单后,暂停EA交易或者减少仓位,用来熬过震荡行情;
使用其它指标来过滤一些交易信号,提高胜率;
使用大止损来规避震荡行情带来的亏损;
使用震荡交易策略,用利润对冲亏损。
我们这个版本先使用连续亏损几单后,暂停EA交易的方式来处理震荡行情。这个功能还有个好处,就是当EA失效以后可以用来进行风险管理,不用担心EA失效以后一直给账户带来亏损。
由于篇幅的原因,代码我就不写在正文里了,我把修改好的代码上传到附件,大家可以自行下载或者私信给我。
6.还有最后一个问题,就是不能同时持有多空方向的订单,这样会错过很多交易信号,要想同时持有多单和空单,就得开两个EA,很麻烦,所以需要修改
这个简单,修改持仓管理模块CalculateCurrentOrders就可以了
由于篇幅的原因,代码我就不写在正文里了,我把修改好的代码上传到附件,大家可以自行下载或者私信给我。
好,这样关于单均线交易策略的EA就基本完善了,现在我们测试一下效果。
就是这么简单的策略,稍微调整一下就能这么优秀!!
注意,回测只是为了验证EA效果,并不能代表未来盈利能力!
可以看到亏损次数到达预期后,EA暂停功能成功运行。
至此,这个系统自带的均线策略,拆解和优化暂时告一段落,大家可以通过修改代码的开仓,平仓逻辑来实现不同的交易策略。
希望大家多多尝试,多多讨论。有问题欢迎评论留言或私信关注,以后我会定期分享和拆解优秀的EA给大家。
|