Enjoy the content and feel free to discuss in the comments section below.
Imagine managing multiple trades with a precision risk management engine, recovering losses through strategic counter-trades while securing profits in volatile markets. The Zone Recovery Multi Trail EA is your advanced trading tool, designed to automate zone recovery trading on MetaTrader 5. It uses a 14-period RSI ("iRSI()", "rsiHandle") to trigger initial buy (RSI ≤ 30) or sell (RSI ≥ 70) trades ("PositionRecovery::OpenTrade()") with a 0.01-lot size ("inputlot"=0.01). If the market moves against a trade by a 200-pip zone ("inputzonesizepts"), it opens opposite trades with doubled lot sizes ("inputlotmultiplier"=2.0), targeting 400-pip profit zones ("inputzonetargetpts"). A 50-pip trailing stop ("inputtrailingstoppts", "ApplyTrailingStop()") is applied to initial positions if enabled ("inputtrailingstopenabled"). The strategy supports multiple recovery baskets ("recoveryArray") via a PositionRecovery struct, closing each at target zones ("CheckCloseAtTargets()") and resetting ("Reset()"). Managed via "CTrade", this strategy suits traders seeking automated loss recovery, requiring significant margin and careful monitoring.
This article is crafted with a professional, engaging, and seamless narrative, flowing like a well-calibrated risk management engine, designed to inform and captivate readers. Tailored for both novice and experienced traders, we’ll dissect each code component with clear, precise explanations, as if guiding an apprentice engineer through a risk management project. With vivid examples—like recovering a buy on EURUSD—and a polished tone, we’ll explore how the EA initializes, triggers trades, manages recovery zones, applies trailing stops, and ensures cleanup. Using a precision risk management engine metaphor, this guide will illuminate the code’s technical rigor, empowering you to trade with confidence. Let’s activate the system and begin this risk management expedition!
Let’s outline the EA’s trading framework, like drafting specifications for a risk management engine:
Initialization: Sets up a 14-period RSI ("iRSI()", "rsiHandle") and initializes PositionRecovery structs in "OnInit()".
Signal Detection: Triggers buy (RSI ≤ 30) or sell (RSI ≥ 70) trades ("OpenTrade()") with 0.01 lots on new bars ("iTime()", "lastBarTime").
Zone Recovery: Opens opposite trades with doubled lots ("ManageZones()", "inputlotmultiplier"=2.0) in 200-pip zones, targeting 400-pip profit zones.
Trailing Stop: Applies a 50-pip trailing stop ("ApplyTrailingStop()") to initial positions if enabled.
Multi-Basket Management: Handles multiple recovery baskets ("recoveryArray") via PositionRecovery, closing at targets ("CheckCloseAtTargets()") and resetting ("Reset()").
Enhancements: Adding configurable RSI thresholds, magic numbers, or visual zone lines could improve flexibility. This framework automates loss recovery with precision, balancing risk and reward.
Let’s step into the risk management engine hub and dissect the MQL5 code that powers this Zone Recovery Multi Trail EA. We’ll guide you through each phase like expert engineers, ensuring the narrative flows seamlessly with professional clarity and engaging precision that captivates readers. We’ll cover initialization, signal detection, zone recovery, trailing stops, and cleanup, with detailed explanations and examples—like recovering a buy on EURUSD—to make it accessible for beginners. Each phase will build on the last, crafting a cohesive technical narrative that transforms code into a compelling risk management project. Let’s power up the system and begin!
We start by building the trading system, initializing RSI and recovery structures.
//+------------------------------------------------------------------+
//| ZONE RECOVERY MULTI TRAIL.mq5 |
//| Copyright 2025, Allan Munene Mutiiria. |
//| https://t.me/Forex_Algo_Trader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Allan Munene Mutiiria."
#property link "https://t.me/Forex_Algo_Trader"
#property version "1.00"
double inputlot = 0.01;
double inputzonesizepts = 200;
double inputzonetargetpts = 400;
double inputlotmultiplier = 2.0;
double inputtrailingstoppts = 50;
double inputminimumprofitpts = 50;
input bool inputtrailingstopenabled = false;
#include <Trade/Trade.mqh>
int rsiPeriod = 14;
int rsiHandle;
double rsiBuffer[];
datetime lastBarTime = 0;
struct PositionRecovery{
CTrade trade;
double initialLotsize;
double currentLotsize;
double zoneSize;
double targetSize;
double multiplier;
string symbol;
ENUM_ORDER_TYPE lastOrderType;
double lastOrderPrice;
double zoneHigh;
double zoneLow;
double zoneTargetHigh;
double zoneTargetLow;
bool isRecovery;
ulong tickets[];
double trailingStop;
double initialEntryPrice;
// ... (methods)
};
PositionRecovery recoveryArray[];
int OnInit(){
rsiHandle = iRSI(_Symbol,_Period,rsiPeriod,PRICE_CLOSE);
if (rsiHandle == INVALID_HANDLE){
Print("Failed to create the RSI handle. Error = ",GetLastError());
return (INIT_FAILED);
}
ArraySetAsSeries(rsiBuffer,true);
Print("Multi-Zone Recovery Starategy initialized.");
return(INIT_SUCCEEDED);
}
The system begins with the #property header, establishing copyright and contact details, like calibrating a risk management engine’s core. The "OnInit()" function initializes the setup, including "Trade/Trade.mqh" for trading and defining inputs: lot size ("inputlot"=0.01), zone size ("inputzonesizepts"=200), target size ("inputzonetargetpts"=400), multiplier ("inputlotmultiplier"=2.0), trailing stop ("inputtrailingstoppts"=50), minimum profit ("inputminimumprofitpts"=50), and trailing stop toggle ("inputtrailingstopenabled"=false). It creates a 14-period RSI handle ("iRSI()", "rsiHandle", PRICE_CLOSE) with error handling ("INVALID_HANDLE", "GetLastError()") and sets the RSI buffer as a time series ("ArraySetAsSeries(rsiBuffer,true)"). The PositionRecovery struct array ("recoveryArray") is declared for multi-basket trading. Returning INIT_SUCCEEDED signals, “Engine is ready, let’s manage risks!” This primes the EA for RSI-based trading and zone recovery, like an engine poised for action. Note: The code uses MetaQuotes’ copyright, but your metadata is presented for consistency.
We check RSI signals to initiate trade baskets, like activating the engine’s sensors.
void OnTick(){
if (CopyBuffer(rsiHandle,0,1,2,rsiBuffer) <= 0){
Print("Failed to copy RSI buffer data. Error: ",GetLastError(),". Reverting now!");
return;
}
datetime currentBarTime = iTime(_Symbol,_Period,0);
if (currentBarTime != lastBarTime){
lastBarTime = currentBarTime;
if (rsiBuffer[1] > 30 && rsiBuffer[0] <= 30){
Print("BUY SIGNAL");
PositionRecovery newRecovery;
newRecovery.Initialize(inputlot,inputzonesizepts,inputzonetargetpts,inputlotmultiplier,_Symbol,ORDER_TYPE_BUY,SymbolInfoDouble(_Symbol,SYMBOL_BID));
newRecovery.OpenTrade(ORDER_TYPE_BUY,"Initial Position");
ArrayResize(recoveryArray, ArraySize(recoveryArray)+1);
recoveryArray[ArraySize(recoveryArray)-1] = newRecovery;
}
else if (rsiBuffer[1] < 70 && rsiBuffer[0] >= 70){
Print("SELL SIGNAL");
PositionRecovery newRecovery;
newRecovery.Initialize(inputlot,inputzonesizepts,inputzonetargetpts,inputlotmultiplier,_Symbol,ORDER_TYPE_SELL,SymbolInfoDouble(_Symbol,SYMBOL_BID));
newRecovery.OpenTrade(ORDER_TYPE_SELL,"Initial Position");
ArrayResize(recoveryArray, ArraySize(recoveryArray)+1);
recoveryArray[ArraySize(recoveryArray)-1] = newRecovery;
}
}
// ... (zone management and trailing stop)
}
In the signal detection hub, "OnTick()" retrieves two RSI values ("CopyBuffer()", "rsiBuffer") and exits if insufficient (<= 0, logging "GetLastError()"). On new bars ("iTime()", "lastBarTime"), it checks for buy signals (RSI crossing below 30, "rsiBuffer[1] > 30 && rsiBuffer[0] <= 30") or sell signals (RSI crossing above 70, "rsiBuffer[1] < 70 && rsiBuffer[0] >= 70"), logging via "Print()". It creates a new PositionRecovery instance, initializes it ("Initialize()") with inputs, opens a trade ("OpenTrade()", "Initial Position"), and adds it to "recoveryArray". For example, on EURUSD H1, RSI dropping from 32 to 28 triggers a buy signal, initializing a new recovery basket at 0.01 lots, like activating the engine’s sensors.
We implement zone recovery to manage losses, like fine-tuning the engine’s recovery mechanism.
struct PositionRecovery{
// ... (fields)
void Initialize(double lot,double zonePts,double targetPts,double lotMultiplier,string _symbol,ENUM_ORDER_TYPE type,double price){
initialLotsize = lot;
currentLotsize = lot;
zoneSize = zonePts *_Point;
targetSize = targetPts *_Point;
multiplier = lotMultiplier;
symbol = _symbol;
lastOrderType = type;
lastOrderPrice = price;
isRecovery = false;
ArrayResize(tickets,0);
trailingStop = 0;
initialEntryPrice = price;
CalculateZones();
}
void CalculateZones(){
if (lastOrderType == ORDER_TYPE_BUY){
zoneHigh = lastOrderPrice;
zoneLow = zoneHigh - zoneSize;
zoneTargetHigh = zoneHigh + targetSize;
zoneTargetLow = zoneLow - targetSize;
}
else if (lastOrderType == ORDER_TYPE_SELL){
zoneLow = lastOrderPrice;
zoneHigh = zoneLow + zoneSize;
zoneTargetLow = zoneLow - targetSize;
zoneTargetHigh = zoneHigh + targetSize;
}
Print("Zone recalculated: ZoneHigh=",zoneHigh,", ZoneLow=",zoneLow,", ZoneTargetHigh=",zoneTargetHigh,", ZoneTargetLow=",zoneTargetLow);
}
bool OpenTrade(ENUM_ORDER_TYPE type, string comment){
if (type == ORDER_TYPE_BUY){
if (trade.Buy(currentLotsize,symbol,0,0,0,comment)){
lastOrderType = ORDER_TYPE_BUY;
lastOrderPrice = SymbolInfoDouble(symbol,SYMBOL_BID);
ArrayResize(tickets,ArraySize(tickets)+1);
tickets[ArraySize(tickets)-1] = trade.ResultOrder();
CalculateZones();
isRecovery = false;
Print("Opened BUY position, Ticket: ",tickets[ArraySize(tickets)-1]);
return true;
}
}
else if (type == ORDER_TYPE_SELL){
if (trade.Sell(currentLotsize,symbol,0,0,0,comment)){
lastOrderType = ORDER_TYPE_SELL;
lastOrderPrice = SymbolInfoDouble(symbol,SYMBOL_BID);
ArrayResize(tickets,ArraySize(tickets)+1);
tickets[ArraySize(tickets)-1] = trade.ResultOrder();
CalculateZones();
isRecovery = false;
Print("Opened BUY position, Ticket: ",tickets[ArraySize(tickets)-1]);
return true;
}
}
return false;
}
void ManageZones(){
double currentPrice = SymbolInfoDouble(symbol,SYMBOL_BID);
if (lastOrderType == ORDER_TYPE_BUY && currentPrice <= zoneLow){
double previousLotSize = currentLotsize;
currentLotsize *= multiplier;
if (OpenTrade(ORDER_TYPE_SELL, "Recovery Position")){
isRecovery = true;
}
else {
currentLotsize = previousLotSize;
}
}
else if (lastOrderType == ORDER_TYPE_SELL && currentPrice >= zoneHigh){
double previousLotSize = currentLotsize;
currentLotsize *= multiplier;
if (OpenTrade(ORDER_TYPE_BUY, "Recovery Position")){
isRecovery = true;
}
else {
currentLotsize = previousLotSize;
}
}
}
};
In the recovery hub, the PositionRecovery struct manages each trade basket. "Initialize()" sets parameters (e.g., "initialLotsize"=0.01, "zoneSize"=200*_Point, "multiplier"=2.0, "symbol"="_Symbol") and calculates zones ("CalculateZones()", e.g., buy: "zoneHigh"=entry, "zoneLow"=entry-200 pips, "zoneTargetHigh"=entry+400 pips, "zoneTargetLow"=entry-600 pips). "OpenTrade()" executes a buy or sell ("trade.Buy()", "trade.Sell()") with "currentLotsize", stores the ticket ("tickets", "trade.ResultOrder()"), updates zones, and logs the action. "ManageZones()" checks if the price hits the zone boundary ("currentPrice <= zoneLow" for buys, ">= zoneHigh" for sells), doubles the lot size ("currentLotsize *= multiplier"), and opens an opposite trade ("Recovery Position"), reverting if failed. For example, on EURUSD, a buy at 1.2050 with bid dropping to 1.1850 triggers a sell at 0.02 lots, like fine-tuning the engine’s recovery. Note: The "Print()" message in "OpenTrade()" for sells incorrectly says “Opened BUY position” (should be “SELL”).
We close baskets at targets and apply trailing stops, like optimizing the engine’s output.
struct PositionRecovery{
// ... (other methods)
void CheckCloseAtTargets(){
double currentPrice = SymbolInfoDouble(symbol,SYMBOL_BID);
if (lastOrderType == ORDER_TYPE_BUY && currentPrice >= zoneTargetHigh){
ClosePositionsAtTarget();
}
else if (lastOrderType == ORDER_TYPE_SELL && currentPrice <= zoneTargetLow){
ClosePositionsAtTarget();
}
}
double GetPositionEntryPrice(ulong ticket){
if (PositionSelectByTicket(ticket)){
return PositionGetDouble(POSITION_PRICE_OPEN);
}
else {
Print("Failed to select the position ticket: ",ticket);
return 0.0;
}
}
void ApplyTrailingStop(){
if (inputtrailingstopenabled && ArraySize(tickets) == 1){
ulong ticket = tickets[0];
double entryPrice = GetPositionEntryPrice(ticket);
double currentPrice = SymbolInfoDouble(symbol,SYMBOL_BID);
double newTrailingStop;
if (lastOrderType == ORDER_TYPE_BUY){
if (currentPrice > entryPrice + (inputminimumprofitpts+inputtrailingstoppts)*_Point){
newTrailingStop = currentPrice - inputtrailingstoppts*_Point;
if (newTrailingStop > trailingStop){
trailingStop = newTrailingStop;
Print("Trailing BUY position, Ticket: ",ticket,". New Trailing stop: ",trailingStop);
}
}
if (trailingStop != 0 && currentPrice <= trailingStop){
Print("Trailed and closed BUY position, Ticket: ",ticket);
ClosePositionsAtTarget();
}
}
else if (lastOrderType == ORDER_TYPE_SELL){
if (currentPrice < entryPrice - (inputminimumprofitpts+inputtrailingstoppts)*_Point){
newTrailingStop = currentPrice + inputtrailingstoppts*_Point;
if (newTrailingStop < trailingStop){
trailingStop = newTrailingStop;
Print("Trailing SELL position, Ticket: ",ticket,". New Trailing stop: ",trailingStop);
}
}
if (trailingStop != 0 && currentPrice >= trailingStop){
Print("Trailed and closed SELL position, Ticket: ",ticket);
ClosePositionsAtTarget();
}
}
}
}
void ClosePositionsAtTarget(){
for (int i = ArraySize(tickets)-1; i >= 0; i--){
ulong ticket = tickets[i];
int retries = 10;
while (retries > 0){
if (trade.PositionClose(ticket)){
Print("CLOSED # ",ticket,". Trailed and Closed: ",(trailingStop != 0));
ArrayRemove(tickets,i,WHOLE_ARRAY);
retries = 0;
}
else {
retries--;
Sleep(100);
}
}
}
if (ArraySize(tickets) == 0){
Reset();
}
}
void Reset(){
currentLotsize = inputlot;
lastOrderType = -1;
lastOrderPrice = 0.0;
isRecovery = false;
ArrayResize(tickets,0);
trailingStop = 0;
initialEntryPrice = 0.0;
Print("Strategy BASKET reset after closing trades.");
}
};
In the trade management hub, "CheckCloseAtTargets()" closes all positions in a basket ("ClosePositionsAtTarget()") when the price hits "zoneTargetHigh" (buy) or "zoneTargetLow" (sell). "ClosePositionsAtTarget()" closes each ticket ("trade.PositionClose()") with retries (10, "Sleep(100)") and removes them from "tickets" ("ArrayRemove()"), resetting ("Reset()") if empty. "ApplyTrailingStop()" applies a 50-pip trailing stop to the first position ("ArraySize(tickets) == 1", "inputtrailingstopenabled") if profitable ("inputminimumprofitpts"=50), updating "trailingStop" and closing if hit. For example, on EURUSD, a buy at 1.2050 with bid dropping to 1.1850 triggers a sell at 0.02 lots; if bid rises to 1.2600 (50+50 pips), the buy trails to 1.2550, closing at 1.2450 if triggered, like optimizing the engine’s output.
As our expedition concludes, we shut down the system, ensuring resource release.
void OnDeinit(const int reason){
if (rsiHandle != INVALID_HANDLE){
IndicatorRelease(rsiHandle);
ArrayFree(rsiBuffer);
}
Print("Multi-Zone Recovery Strategy deinitialized.");
}
In the shutdown control room, "OnDeinit()" releases the RSI handle ("IndicatorRelease(rsiHandle)") and frees the buffer ("ArrayFree(rsiBuffer)"), logging deinitialization, ensuring a clean shutdown, like powering down the engine’s systems.
The Zone Recovery Multi Trail EA is a risk management triumph, automating multi-basket loss recovery with precision, like a master-crafted engine. Its RSI signals ("rsiBuffer"), zone recovery ("ManageZones()"), and trailing stops ("ApplyTrailingStop()") balance risk and reward, with multi-basket support ("recoveryArray") enhancing flexibility. Picture recovering a buy on EURUSD at 1.2050 with a doubled sell at 1.1850—strategic brilliance! Beginners will value the automated clarity, while experts can enhance its customization, making it essential for traders in volatile markets.
To deploy this EA:
Open MetaEditor in MetaTrader 5, like entering your risk management hub.
Copy the code, compile with F5, and verify no errors—no engineer wants a faulty engine!
Attach the EA to your chart (e.g., EURUSD H1) with default settings ("inputlot"=0.01, "inputzonesizepts"=200, "inputzonetargetpts"=400, "inputlotmultiplier"=2.0, "inputtrailingstoppts"=50).
Monitor logs (e.g., “BUY SIGNAL”, “Trailing BUY position”) for trade actions.
Test on a demo account first—real capital deserves a trial run!
We’ve engineered a Zone Recovery Multi Trail RSI system that manages trades with precision, like a master-crafted risk management engine. This MQL5 code is your strategic tool, brought to life with a seamless, professional narrative packed with clear explanations and vivid examples to fuel your trading confidence. Whether you’re a novice trader or a seasoned market strategist, this EA empowers you to recover losses and secure profits with ease. Ready to manage risks? Watch our video guide on the website for a step-by-step creation process. Now, safeguard your trading with precision! 🔍
Disclaimer: Trading is like navigating complex markets—challenging and risky. Losses can exceed deposits. Test strategies on a demo account before going live.
Recent Comments
Go to discussion to Comment or View other CommentsNo comments yet. Be the first to comment!