
实现 Deus EA:使用 MQL5 中的 RSI 和移动平均线进行自动交易
概述
在本文中,我们将研究 Deus EA 的基本组件,包括其交易逻辑、参数设置和实现所需的 MQL5 代码。本文旨在为您提供开发和增强交易算法所需的知识和工具。通过使用 Deus EA,您将能够探索自动交易的世界,并能够为您的交易努力发现新的机会。
我们将研究 Deus EA 的功能,这是一种使用 MQL5 构建的自动交易技术。我们的讨论将集中在 Deus EA 如何结合移动平均线和相对强弱指数(RSI)来做出交易选择。通过分析这些指标,EA 确定了市场中的最佳入场和退出点,以最大限度地提高交易盈利能力,同时最大限度地降低风险。
Deus EA 是为 MetaTrader 5 平台设计的自动交易系统,可根据移动平均线和相对强弱指数(RSI)生成买入和卖出信号。通过识别市场趋势和检测超买或超卖情况,它试图增强交易决策。此外,它还包括风险管理工具,如止损、止盈订单和追踪止损。
Deus EA 概述
Deus EA 依靠相对强弱指数 (RSI) 和移动平均线等指标来自动做出交易决策。该 EA 的目标是通过使用这些指标来产生可操作的买入和卖出建议,从而提高交易绩效并有效管理风险。
以下是 Deus EA 的关键要素:
- 技术措施:
- 相对强弱指数(RSI):这个动量振荡指标衡量价格变动的速度和方式,这有助于确定市场何时超买或超卖,并对市场走势做出迅速反应。在我们的案例中,EA 将采用简短的 7 天 RSI 时间范围,超买阈值设置为 35,超卖阈值设置为 15。
- 移动平均线(MA):为了找到一段时间内的趋势,移动平均线将价格数据调平。我们将在 Deus EA 中使用 25 期简单移动平均线(SMA)来过滤交易信号并确定市场的总体方向。
- 买入信号:当价格高于移动平均线和 RSI 时,它显示超卖状态(低于15),表明价格可能上涨,并发出买入订单。
- 卖出信号:如果价格低于移动平均线和 RSI,则表示超买状态(超过 35),表明可能呈下跌趋势,并发出卖出订单。
3.风险管理:
- 止损与止盈:在我们的 EA 中,我们包含可定制的止损水平和止盈参数,每个参数设置为 50 点,以帮助管理风险和锁定利润。
- 追踪止损:我们使用 25 个点的追踪止损来调整止损水平,因为价格走势有利,旨在确保利润,同时只要市场朝着预期的方向发展,交易就会保持开放。
4.订单管理:
- 仓位管理:EA 根据交易信号,在开立新头寸之前关闭任何现有头寸,以确保一次只开立一个头寸。
Deus EA 具有初始化、分时处理、开仓和平仓以及追踪止损调整等功能。它是使用 MetaTrader5 中使用的脚本语言 MQL5 实现的。该编程确保遵循风险管理指南并有效处理交易信号。
Deus 有助于自动化交易程序,减少情绪性决策,并通过使用这些功能来改善交易结果。本文将为理解 Deus EA 的设计思想和功能提供基础。
MQL5 中的实现
首先,我们需要建立交易头寸。我们通过包含一个专门用于开立头寸的文件来开立交易头寸。
#include <Trade\Trade.mqh>
CTrade trade;
在这里,我们使用 include 文件来包含 trade 库。这将使 Deus EA 能够访问交易操作功能。此时,我们还定义了 CTrade 类,它为开展交易活动提供了高级别的支持。由于包含了这个文件,EA 就可以使用 CTrade 类来管理交易。在整个 EA 中,该对象将用于执行各种交易任务,包括开仓、修改仓位和平仓。
在本节中,我们将研究 Deus EA 的关键输入参数。Deus EA 是一种复杂的交易算法,它使用移动平均线和 RSI 指标来寻找交易机会。通过调整这些参数,交易者可以使 EA 的行为最适合他们独特的交易策略和风险承受能力。
输入参数如下:
input double Lots = 0.1; // Lot size input double StopLoss = 50; // Stop loss in points input double TakeProfit = 50; // Take profit in points input double TrailingStop = 25; // Trailing stop in points
- Lots(交易量)
input double Lots = 0.1; // Lot size
每笔交易的交易量由 Lots 选项指定。在此实例中,EA 配置为每次交易 0.1 手。交易者可以通过调整手数来管理其市场风险敞口。较小的手数降低了可能的风险和利润,而较大的手数不仅提高了可能的利润,还增加了风险。为了平衡风险和收益,选择正确的手数至关重要。
2.StopLoss(止损点数)
input double StopLoss = 50; // Stop loss in points
每笔交易的最大允许损失由 StopLoss 选项定义,在我们的例子中,它设置为 50 点。为了阻止未来的损失,如果市场在这一点之后不利于交易,头寸将自动关闭。这将保护您的交易账户免受重大损失。
3.TakeProfit(止盈点数)
input double TakeProfit = 50; // Take profit in points
我们通过 TakeProfit 参数将每笔交易的利润目标设置为 50 点。为了确保利润,当市场向有利于交易的方向发生如此大的变化时,头寸将自动关闭。这将确保在市场状况出现任何潜在逆转之前获得收益,因此,这将提高盈利能力。
4.TrailingStop(追踪止损点数)
input double TrailingStop = 25; // Trailing stop in points
我们通过 TrailingStop 参数引入止损,该参数的变化有利于交易。当市场向有利于交易的方向波动时,最初设定在入场价 25 个点的追踪止损会进行调整以锁定利润。此功能将帮助交易者从长期的市场波动中获利,同时保障他们的收益。
RSI 指标参数:
input int RSI_Period = 7; // RSI period input double RSI_Overbought = 35.0; // RSI overbought level input double RSI_Oversold = 15.0; // RSI oversold level
5.RSI_Period (RSI 计算周期数)
input int RSI_Period = 7; // RSI period
用于生成相对强弱指数 (RSI) 的周期数由 RSI_period 参数指定,在我们的例子中将其设置为 7。衡量价格变动速度和变化的动量振荡指标是 RSI。RSI 对短时间段内(例如 7)的近期价格走势更为敏感,这有助于快速识别超买或超卖的情况。
6.RSI_Overbought (RSI 超买水平)
input double RSI_Overbought = 35.0;
判断超买情况的阈值由 RSI_Overbought 参数定义,设置为 35.0。一般来说,超买水平可能是 70,但使用这种技术,35.0 表示更激进的卖出仓位。当 RSI 高于此阈值时,EA 会触发卖出操作,表明市场可能即将出现下跌逆转。
7.RSI_Oversold(RSI 超卖水平)
input double RSI_Oversold = 15.0; // RSI oversold level
超卖条件阈值由 RSI_Oversold 参数定义,其值为 15.0。尽管这种方法采用了更保守的水平来指示可能的买入机会,但典型的超卖水平可能是 30。当 RSI 跌破该阈值时,EA 会触发买入操作,因为它预感到市场可能出现上行逆转。
移动平均线参数
input int MA_Period = 25; // Moving Average period input ENUM_MA_METHOD MA_Method = MODE_SMA; // Moving Average method input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA
8.MA_Period (移动平均周期数)
input int MA_Period = 25; // Moving Average period
移动平均线 (MA) 的计算周期数由 MA_Period 参数决定,其值为 25。MA 对价格数据进行平滑处理,以发现趋势。25 个周期数的窗口将为市场趋势提供全面的视角,它不仅会消除短期噪音,还会对值得注意的价格变化做出反应。
9.MA_Method (移动平均方法)
Moving Average period input ENUM_MA_METHOD MA_Method = MODE_SMA; // Moving Average method
在这种情况下使用的移动平均线类型,即简单移动平均线(SMA),由 MA_Method 选项决定。SMA 是一个简单的趋势指标,计算给定时期的收盘价平均值。对于不同的敏感度,可以采用指数移动平均线(EMA)等替代技术,但简单移动平均线(SMA)是一种可靠且稳定的趋势指标。
10.MA_Price (应用于 MA 的价格)
input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA
移动平均线计算所使用的价格类型由 MA_Price 选项指定,该选项设置为价格 PRICE_CLOSE。这表明 MA 是使用收盘价确定的,由于收盘价代表交易时段的收盘价,因此经常使用收盘价。通过做出这一决定,MA 可以保证提供对总体市场趋势的可靠指示。
Deus EA 的交易行为和风险管理在很大程度上取决于其输入参数。交易者可以通过调整这些参数来调整 EA,以更好地适应他们独特的交易目标和当前的市场状况,这些参数包括交易量、风险控制、指标周期数和阈值。为了在自动交易中充分利用 Deus EA,理解和适当修改这些设置至关重要。
然后,我们要根据移动平均线和 RSI 指标讨论我们的 EA 新变量。通过了解这些因素,我们将能够了解 EA 如何处理交易执行和分析市场数据。
//--- Variables double rsiValue; // RSI value double maValue; // Moving Average value double Ask; double Bid; double Close; // Initializing Close array with two elements
RSI 值:
double rsiValue; // RSI value
相对强弱指数 (RSI) 的当前值存储在 rsiValue 变量中。作为动量振荡指标,RSI 通过计算价格变化的速率和变化来帮助确定市场何时超买或超卖。
价格类型和指定的 RSI 周期用于确定 RSI 值。Deus EA 使用用户定义的参数和最新的价格数据来计算 RSI。
当 RSI 值低于 RSI_Oversold 水平时,EA 将其解释为买入信号。这意味着市场可能超卖,并可能出现上行逆转。
另一方面,如果 RSI 值超过 RSI_Overbought 水平,则是卖出信号。这意味着市场可能超买,并可能向下回落。
移动平均值:
double maValue; // Moving Average value
移动平均线 (MA) 的当前值存储在 maValue 变量中。通过在预定的时间框架内平滑价格数据,该指标有助于识别趋势。
移动平均线是使用技术、价格类型和选定的周期数来计算的。指定周期数的收盘价用于计算我们的 EA 中的 MA。
趋势:目前的市场趋势得到了 MA 值的支持。当价格高于 MA 时,EA 认为市场处于上涨趋势,而当价格低于 MA 时,EA 认为市场处于下跌趋势。
入场信号:交易信号的产生取决于 RSI 和 MA 值之间的关系。例如,如果之前的收盘价高于 MA 值且 RSI 低于 RSI_Oversold 水平,则买入信号被视为合法。RSI 和 MA 值在 Deus EA 中结合在一起,以帮助其做出明智的交易决策。
double Ask;
资产的当前要价存储在 Ask 变量中,这是交易者购买该资产的价格。它设置了 OpenPosition 函数中买入订单的入场价格。要价是当时购买该资产所能找到的最佳价格,对这一成本的精确监控保证了买入订单的适当提交。
double Bid;
资产的当前出价记录在 Bid 变量中,这是该资产向交易者出售的价格。它设置了 OpenPosition 函数中卖出订单的入场价格。出售资产所能获得的最佳价格反映在出价中,
double Close[];
这个时期的资产收盘价存储在 Close 数组中。在此 EA 中,它被放大以存储最新使用的值。该数组用于产生交易信号并分析价格走势。为了决定是否进入买入或卖出信号,需要将该值与前一时期(Close[1])和最近一时期(Close[0])的收盘价进行比较。这种比较将帮助我们判断价格是上涨还是下跌。
void ApplyTrailingStop();
此函数将有助于实现追踪止损机制。如果当前市场价格有利于仓位的止损,该函数将遍历所有未平仓仓位并修改止损。该函数通过设置追踪止损,确保即使市场价格发生与交易相反的变化,止损仍保持在最有利的位置。
void OpenPosition(CTrade trade, int orderType);
根据订单类型,该方法用于开设新的交易头寸。该函数根据订单类型确定止盈、止损和入场价格。交易是通过使用 CTrade 对象计算的参数来执行的。这将有助于 EA 生成可能对启动市场交易至关重要的信号。
void ClosePositions(int orderType);
通过此函数,可以关闭特定订单类型的交易头寸。所有未平仓头寸都会被迭代,符合指定订单类型的头寸将被该函数关闭。这将有助于消除不再符合交易策略或市场状况的头寸,从而加强交易管理。
//--- Function prototypes void ApplyTrailingStop(); void OpenPosition(CTrade trade, int orderType);
然后,我们将这些函数原型结合起来,使 EA 能够有效地处理交易头寸。OpenPosition 方法根据市场情况开始交易,ClosePositions 函数根据需要控制并关闭交易,ApplyTrailingStop 函数通过修改止损来改善交易管理。所有这些函数的结合使得 EA 能够对市场变化做出快速反应并有效地开展交易。
现在让我们转到 OnInit 函数,Deus EA 使用 OnInit 函数来启动交易。其目的是根据移动平均线和 RSI 指标进行交易。
//+------------------------------------------------------------------+ //| Expert initialization function . | //+------------------------------------------------------------------+ int OnInit() { Print("Deus EA initialized successfully."); return(INIT_SUCCEEDED); }
当终端启动或 EA 加载到图表中时,OnInit 函数都会被调用一次。初始化变量、建立指标句柄以及执行任何其他需要使用此函数的配置操作。然后我们将其各部分分解如下:
Print("Deus EA initialized successfully.");
这行代码的目的是将确认初始化成功完成的消息打印到专家 (EA) 日志中。日志记录是每个 EA 的关键组成部分,这样,我们就将能够验证 EA 是否已加载并初始化且没有任何问题。在调试和确保 EA 已准备好开始处理市场数据和执行交易时它也很有用。
return(INIT_SUCCEEDED); }
return (INIT_SUCCEEDED); 语句用于通知 MetaTrader 平台初始化过程已完成。EA 需要返回 INIT_SUCCEEDED 才能进入下一阶段,例如 OnTick 函数,这是执行主要交易逻辑的地方。如果初始化因任何原因失败,该函数可能会返回 INIT_FAILED,停止 EA 运行并避免运行期间的潜在故障。
然后,我们来看看 OnDeinit 函数,这个函数对于保持 EA 的可靠性和完整性至关重要。我们将讨论此函数的作用。当 EA 重新编译时,它会被从图表中删除。此操作将激活 OnDeinit 函数并为其提供执行清理任务的机会,并确保适当释放资源并完成任何最后一刻的步骤。
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("Deus EA deinitialized. Reason: ", reason); }
OnDeinit 函数中的 reason 参数提供了取消初始化背后的原因。调试和找出 EA 被取消初始化的原因可以得到帮助。我们使用 Deus EA 中的 print 函数来记录这个原因。
void OnDeinit(const int reason) { Print("Deus EA deinitialized. Reason: ", reason); }
您可以通过查看此简单的日志来确定EA是否被明确删除、重新编译或终端关闭的结果,该日志可以在开发和测试阶段提供有见地的信息。
尽管去初始化原因是我们当前的 OnDeinit 实现记录的唯一原因,但此函数可以扩展到任何必要的清理程序。例如,您可能需要关闭任何打开的资源、释放文件句柄或保存当前状态。可以避免资源泄漏,并且可以通过适当的清理来保证EA的干净重新初始化。在可靠性和稳定性至关重要的实时交易情况下,这一点至关重要。正确的处理保证了早期运行的性能问题不会干扰 EA 重新加载或重启的能力。
我们现在转到 OnTick 函数,OnTick 函数对于 EA 的实时决策过程至关重要。每次收到新的价格报价时,都会调用此函数,然后它使 EA 能够评估市场状态并使用预先建立的技术进行交易。以下是 OnTick 函数的主要功能以及它如何组合 Deus EA 的策略组件:
- 获取市场信息;
当 OnTick 函数首次启动时,它帮助获取尽可能多的市场数据。
Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); ArrayResize(Close, 2); Close[0] = iClose(_Symbol, _Period, 0); Close[1] = iClose(_Symbol, _Period, 1);
此代码保存最近的收盘价并获取卖价和买价。为了确保 Close 数组有足够的空间来存储最近的收盘价,使用了 ArrayResize。
- 技术指标的计算;
移动平均线和相对强弱指数由算法计算。
//--- Calculate RSI value rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0); if (rsiValue == WRONG_VALUE) { Print("Error calculating RSI"); return; } //--- Calculate Moving Average value maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0); if (maValue == WRONG_VALUE) { Print("Error calculating Moving Average"); return; }
MA 值有助于确定趋势方向,RSI 值指示超买或超卖情况。在继续检查之前,要确保数字准确。
- 交易信号的生成;计算指标后,该函数寻找买入和卖出信号:
//--- Check for Buy Signal if(rsiValue < RSI_Oversold && Close[1] > maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_SELL); OpenPosition(ORDER_TYPE_BUY); } } //--- Check for Sell Signal if(rsiValue > RSI_Overbought && Close[1] < maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_BUY); OpenPosition(ORDER_TYPE_SELL); } }
当现在的收盘价高于移动平均线且 RSI 低于超卖阈值时,发出买入信号。这种情况预示着可能出现上行逆转。
当现在的收盘价低于移动平均线且 RSI 低于超买阈值时,发出卖出信号。这种情况预示着可能出现下行逆转。
- 追踪止损的应用;为了最大限度地减少损失并确保盈利,OnTick 函数采用了应用追踪止损的逻辑。
//--- Apply trailing stop if specified if (TrailingStop > 0) { ApplyTrailingStop(); }
当设置了追踪止损参数时,此部分确保追踪止损机制已启动。为了锁定收益,ApplyTrailingStop 函数会在价格朝期望方向变动时修改止损水平。
- 开仓和平仓:使用开仓,OpenPosition 函数在确定入场价、止损和止盈水平后尝试开仓。平仓;ClosePositions 函数会迭代所有仓位,并关闭与给定订单类型对应的仓位。
这解释了 Deus EA 如何通过 OnTick 函数动态地适应市场情况。此函数使用 RSI 和 MA 指标产生交易信号和追踪止损以保障盈利。通过这种策略,EA 既能保证保护收益,又能对市场变化做出反应。以下是 OnTick 函数的完整代码:
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); ArrayResize(Close, 2); Close[0] = iClose(_Symbol, _Period, 0); Close[1] = iClose(_Symbol, _Period, 1); //--- Calculate RSI value rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0); if (rsiValue == WRONG_VALUE) { Print("Error calculating RSI"); return; } //--- Calculate Moving Average value maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0); if (maValue == WRONG_VALUE) { Print("Error calculating Moving Average"); return; } //--- Check for Buy Signal if(rsiValue < RSI_Oversold && Close[1] > maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_SELL); OpenPosition(ORDER_TYPE_BUY); } } //--- Check for Sell Signal if(rsiValue > RSI_Overbought && Close[1] < maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_BUY); OpenPosition(ORDER_TYPE_SELL); } } //--- Apply trailing stop if specified if (TrailingStop > 0) { ApplyTrailingStop(); }
既然我们已经完成了 OnTick 函数,现在让我们自由地看一下我们的 EA 的功能函数。对于 Deus EA 根据 RSI 和移动平均指标的信号执行交易来说,open 函数至关重要。该函数可确保准确下达买卖订单,并考虑到风险管理因素。
void OpenPosition(int orderType)
要下达的订单类型由 OpenPosition 函数接受的唯一参数订单类型决定。对于买入和卖出订单,这可能分别是 ORDER_TYPE_BUY 或 ORDER_TYPE_SELL。订单类型决定函数内的订单价格。
double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid;
使用 {Ask} 价格作为买入订单,使用 {Bid} 价格作为卖出订单。
为了控制风险,确保利润,止损(SL)和止盈(TP)阈值确定为:
double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point; double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point;
对于买入订单,止盈设置在订单价格上方,止损设置在订单价格下方。卖单的止盈和止损分别位于订单价格的下方和上方。CTrade 类中的 PositionOpen 函数用于开立真实仓位:
bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus EA");
该技术需要几个参数:
- -{ Symbol}:用于交易的交易品种,例如 EURUSD。
- -{ orderType}:订单类型(卖出或买入)。
- -"Lots":订单的手数大小。
- -{price}:订单的买入价或卖出价。
- -{sI}:计算止损的水平
- -{tp}:确定的获利阈值。
- -“Deus EA”:与订单相关的声明。
在尝试打开该仓位后,该函数会验证结果,并在必要时记录一条消息。
if(result) { Print("Order opened successfully. Type: ", orderType, ", Price: ", price); } else { Print("Failed to open order. Error code: ", GetLastError()); } }
如果订单成功打开,则会打印出确认信息。如果订单无法打开,则使用 GetLastError 来获取问题代码,然后记下该代码以进行故障排除。
开仓函数完整代码如下:
//+------------------------------------------------------------------+ //| Function to open a position | //+------------------------------------------------------------------+ void OpenPosition(int orderType) { double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid; double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point; double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point; bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus EA"); if(result) { Print("Order opened successfully. Type: ", orderType, ", Price: ", price); } else { Print("Failed to open order. Error code: ", GetLastError()); } } )
我们已经完成了一个功能函数,现在让我们看一下另一个功能函数,即平仓函数。为了保证通过交易策略参数终止不需要的仓位,Deus EA 的 ClosePositions 函数至关重要。当满足某些条件时,此功能用于管理特定类型(买入或卖出)的平仓逻辑。让我们来研究一下此函数的操作及其对更广泛计划的意义。
void OpenPosition(int orderType)
要关闭的仓位类型由单个参数 orderType 指定,该参数由 Closepositions 函数采用。ORDER_TYPE_SELL 或 ORDER_TYPE_BUY 是此参数的可能值。此函数循环遍历此时所有未平仓头寸并关闭相关头寸。
for(int i = PositionsTotal() - 1; i >= 0; i--) { if(PositionSelectByIndex(i)) { if(PositionGetInteger(POSITION_TYPE) == orderType) { if(!trade.PositionClose(ticket) { Print("Failed to close position. Error code: ", GetLastError()); } } } }
循环从最后一点开始向后推进。由于关闭一个仓位会降低仓位的总数,因此前向迭代循环可能会被中断,从而需要进行反向迭代。PositionSelectByIndex(i) 用于选择给定索引 {i} 处的仓位。
该函数验证所选位置是否与循环中给定的 {orderType} 匹配。
if(PositionGetInteger(POSITION_TYPE) == orderType)
如果 {orderType} 不等于该值,则不应平仓。如果类型匹配,该函数将尝试平仓。
if(!trade.PositionClose(ticket) { Print("Failed to close position. Error code: ", GetLastError()); } } } }
通过尝试根据其编号 {trade.PositionClose(ticket)}) 来识别仓位,可以关闭仓位。如果平仓失败,则会打印一条错误消息,其中包含通过 GetLastError() 获取的错误代码。这有助于找出无法平仓的原因并有助于排除故障。
当达到一定的利润水平时,Deus EA 可以通过平仓获利仓位来锁定利润。这是通过确保在特定条件下关闭选定的仓位来实现的。
平仓函数完整代码如下:
//+------------------------------------------------------------------+ //| Function to close positions | //+------------------------------------------------------------------+ void ClosePositions(int orderType) { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(PositionSelectByIndex(i)) { if(PositionGetInteger(POSITION_TYPE) == orderType) { if(!trade.PositionClose(ticket) { Print("Failed to close position. Error code: ", GetLastError()); } } } }
最后,让我们转到最后一个功能函数,它是一个应用追踪止损的函数。您可以通过关闭亏损交易来停止进一步的损失。遵循指导原则,例如不要同时持有买入和卖出仓位,以及进行对冲。当市场价格转向有利于未平仓头寸时,追踪止损会修改止损水平。Deus EA 中的 ApplyTrabingStop 方法可确保有效应用此功能。追踪止损限制了潜在损失,同时通过跟踪市场波动锁定了利润。让我们讨论一下该函数的工作原理。
void ApplyTrailingStop()
由于这适用于当前交易品种上的所有未平仓头寸,因此 ApplyTrailingStop 方法不需要任何参数。与 ClosePositions 函数类似,该函数首先迭代所有未平仓头寸:
for (int i = PositionsTotal() - 1; i >= 0; i--) { if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol)
循环从最后一个位置开始向后推进。
-{PositionSelectByIndex(i)}:此函数选择索引{i} 处的条目。使用 {PositionGetSymbol()==_Symbol} 验证该仓位是否与活跃交易品种相关联。
该函数使用追踪止损的距离和当前市场价格来确定新的止损水平:
double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask; double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point;
买入仓位的追踪止损设置在 {Bid} 价格下方。对于卖出交易,追踪止损位于 {Ask} 价格上方。然后,该函数在确定是否合适后,使用 PositionModify 应用新的止损水平:
if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } }
仅当新的止损水平({sI}) 超过现有止损时,您仓位的止损才会发生变化。此外,当新的止损水平低于现有止损水平时,卖出仓位的止损也会更新。
如果仓位修改不成功,则会打印包含错误代码的错误消息。这有助于排除故障,也有助于弄清未使用追踪止损的原因。
应用追踪止损函数的完整代码如下:
//+------------------------------------------------------------------+ //| Function to apply trailing stop | //+------------------------------------------------------------------+ void ApplyTrailingStop() { for (int i = PositionsTotal() - 1; i >= 0; i--) { if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol) { double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask; double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point; if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } }
文章完整代码如下:
//+------------------------------------------------------------------+ //| Deus EA | //| Copyright 2024, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #include <Trade\Trade.mqh> CTrade trade; //--- Input parameters input double Lots = 0.1; // Lot size input double StopLoss = 50; // Stop loss in points input double TakeProfit = 50; // Take profit in points input double TrailingStop = 25; // Trailing stop in points //--- RSI parameters input int RSI_Period = 7; // RSI period input double RSI_Overbought = 35.0; // RSI overbought level input double RSI_Oversold = 15.0; // RSI oversold level //--- Moving Average parameters input int MA_Period = 25; // Moving Average period input ENUM_MA_METHOD MA_Method = MODE_SMA; // Moving Average method input ENUM_APPLIED_PRICE MA_Price = PRICE_CLOSE; // Applied price for MA //--- Variables double rsiValue; // RSI value double maValue; // Moving Average value double Ask; double Bid; double Close[2]; // Initializing Close array with two elements //--- Function prototypes void ApplyTrailingStop(); void OpenPosition(CTrade &trade, int orderType); // Pass CTrade by reference void ClosePositions(int orderType); // pass orderType directly //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { Print("Deus EA initialized successfully."); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { Print("Deus EA deinitialized. Reason: ", reason); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- Update current prices Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK); Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID); ArrayResize(Close, 2); Close[0] = iClose(_Symbol, Period(), 0); Close[1] = iClose(_Symbol, Period(), 1); //--- Calculate RSI value rsiValue = iRSI(_Symbol, _Period, RSI_Period, PRICE_CLOSE, 0); if (rsiValue == WRONG_VALUE) { Print("Error calculating RSI"); return; //--- Calculate Moving Average value maValue = iMA(_Symbol, _Period, MA_Period, 0, MA_Method, MA_Price, 0); if (maValue == WRONG_VALUE) { Print("Error calculating Moving Average"); return; } //--- Check for Buy Signal if(rsiValue < RSI_Oversold && Close[1] > maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_SELL); OpenPosition(ORDER_TYPE_BUY); } } //--- Check for Sell Signal if(rsiValue > RSI_Overbought && Close[1] < maValue) { if(PositionsTotal() == 0) { ClosePositions(ORDER_TYPE_BUY); OpenPosition(ORDER_TYPE_SELL); } } //--- Apply trailing stop if specified if(TrailingStop > 0) { ApplyTrailingStop(); } } //+------------------------------------------------------------------+ //| Function to open a position | //+------------------------------------------------------------------+ void OpenPosition(int orderType) { //--- Determine price stop loss, and take profit levels double price = (orderType == ORDER_TYPE_BUY) ? Ask : Bid; double sl = (orderType == ORDER_TYPE_BUY) ? price - StopLoss * _Point : price + StopLoss * _Point; double tp = (orderType == ORDER_TYPE_BUY) ? price + TakeProfit * _Point : price - TakeProfit * _Point; bool result = trade.PositionOpen(_Symbol, orderType, Lots, price, sl, tp, "Deus EA"); if(result) { Print("Order opened successfully. Type: ", orderType, ", Price: ", price); } else { Print("Failed to open order. Error code: ", GetLastError()); } } //+------------------------------------------------------------------+ //| Function to close positions | //+------------------------------------------------------------------+ void ClosePositions(int orderType) { for(int i = PositionsTotal() - 1; i >= 0; i--) { if(PositionSelectByIndex(i)) { //--- Check if the positions type matches the order type to be closed if(PositionGetInteger(POSITION_TYPE) == orderType) { ulong ticket = PositionGetInteger(POSITION_TICKET); if(!trade.PositionClose(ticket) { Print("Failed to close position. Error code: ", GetLastError()); } } } } } //+------------------------------------------------------------------+ //| Function to apply trailing stop | //+------------------------------------------------------------------+ void ApplyTrailingStop() { for (int i = PositionsTotal() - 1; i >= 0; i--) { if (PositionSelectByIndex(i) && PositionGetSymbol() == _Symbol) { double price = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? Bid : Ask; double sl = (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY) ? price - TrailingStop * _Point : price + TrailingStop * _Point; //--- Trailing stop logic for buy positions if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_BUY && PositionGetDouble(POSITION_SL) < sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } //--- Trailing stop logic for sell positions else if (PositionGetInteger(POSITION_TYPE) == ORDER_TYPE_SELL && PositionGetDouble(POSITION_SL) > sl) { if (!trade.PositionModify(PositionGetInteger(POSITION_TICKET), sl, PositionGetDouble(POSITION_TP))) { Print("Failed to modify position. Error code: ", GetLastError()); } } } }
恭喜我们吧!到目前为止,我们已经实现了 Deus EA 来实现交易自动化。
以下是我们的测试结果;
获得的结果:
测试的是 USDJYP,回测是在 1H 图上从 2024.07.10 到 2024.08.06。模式是每一分时。使用的参数是我们用来研究实现的参数。
这种策略最适合 EUR/USD 和 USD/JPY,但只适合那些不需要高胜率的人。以下是我们用于测试 EA 的参数:
结论
Deus EA 使用移动平均线和相对强弱指数 (RSI) 来生成交易信号,展示了一种集成技术指标来管理和利用市场机会的先进交易策略。本指南详细介绍了交易逻辑、风险控制和支撑 EA 的 MQL5 代码,该代码自动化了交易决策,以提高一致性并减少情绪偏差。
从图中我们可以看出,优化的小参数不仅降低了风险,而且增加了损失。因此,在实时交易中部署 EA 之前,对不同交易品种进行彻底的测试和优化至关重要。这将有助于确保它在不同的市场条件下表现良好,并与特定的交易目标保持一致。
定期监测和调整对于保持 Deus EA 和类似自动化系统的有效性是必要的。本文提供了有效实现和优化 Deus EA 交易所需的基本见解和工具。您将能够从 MQL5 访问所需的任何额外支持。
本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/15431

