Versione B1.01 del 15/07/2026 BETA
This page contains the complete technical specification required to develop indicators compatible with RiskGuard Config 1.
The only supported method for sending signals is through the official RiskGuard Config 1 Global Variables.
This page defines the mandatory rules for developing an MQL5 indicator compatible with RiskGuard Management Strategy Mode.
This document is intended for:
MQL5 developers
Artificial Intelligence systems
Automatic code generators
Developers creating strategies compatible with RiskGuard
Whenever a rule is marked as mandatory, it must be followed without exception.
The sole purpose of the indicator is to generate trading signals.
All trade execution and risk management are handled entirely by RiskGuard.
The indicator must:
Analyze the market
Generate trading signals
Send BUY, SELL, BREAK EVEN, or CLOSE commands
Optionally read the trading lines created by RiskGuard
Use exclusively the official Config 1 protocol
The indicator must not:
Open trades
Close trades
Modify trades
Calculate position size
Manage risk
Manage Break Even
Manage partial Take Profit levels
Manage Trailing Stop
Manage daily loss limits
Manage Quantum
All of these functions are handled exclusively by RiskGuard.
The indicator name must begin with:
RiskGuard_
Valid examples:
RiskGuard_ORB
RiskGuard_MACD
RiskGuard_Stochastic
RiskGuard_Breakout
Invalid examples:
ORB
MACD
RG_ORB
AutoStrategy
RiskGuard may automatically reject indicators whose names do not begin with the RiskGuard_ prefix.
RiskGuard is designed to operate with a single chart window per symbol, saved as the default template.
The user is free to change the chart timeframe at any time.
The indicator must ensure that changing the chart timeframe does not affect the strategy's behavior.
A chart timeframe change must not:
Modify the strategy logic
Modify the generated signals
Generate new signals
Generate duplicate signals
Generate retroactive signals
If the strategy uses one or more specific timeframes, they must be defined internally within the indicator.
The strategy logic must not depend on the timeframe currently displayed on the chart.
The indicator must generate signals in real time only.
If a trading condition occurred before the indicator was loaded, the signal must be ignored.
Example:
BUY signal at 11:00
Indicator loaded at 15:00
The indicator must not send the retroactive BUY signal.
The same signal must not be sent more than once.
The indicator developer is fully responsible for preventing duplicate signals.
The indicator must ensure that:
Refreshing the chart does not generate duplicate signals
Changing the chart timeframe does not generate duplicate signals
Reinitializing the indicator does not generate duplicate signals
The same trading event is not sent more than once
A RiskGuard-compatible indicator must not execute trading operations directly.
Functions such as the following must not be used:
OrderSend()
Buy()
Sell()
PositionOpen()
PositionClose()
PositionModify()
RiskGuard is the only component authorized to execute trading operations.
When a RiskGuard-compatible indicator is removed from the chart, it is recommended to properly clean up all resources created by the indicator.
For example:
Indicator-specific Global Variables
Chart objects
Boxes
Lines
Labels
Persistent state variables
This helps reduce the risk of:
Duplicate signals
Residual signals
Objects left on the chart
Unexpected behavior when the indicator is reloaded
It is recommended to implement this cleanup logic inside:
OnDeinit()
Particular attention should be given to the following case:
REASON_CHARTCHANGE
MetaTrader reinitializes the indicator whenever the chart timeframe is changed.
In many cases, deleting all variables during REASON_CHARTCHANGE can lead to duplicate signals after the indicator is reloaded.
For this reason, the cleanup logic should be carefully designed according to the behavior of the strategy.
Example:
void OnDeinit(const int reason)
{
if(reason == REASON_CHARTCHANGE)
return;
GlobalVariableDel(LastSignalGVName());
ObjectDelete(0, "MyStrategyBox");
ObjectDelete(0, "MyStrategyLine");
}
The cleanup logic depends entirely on the behavior of the strategy.
Not all indicators require the same OnDeinit() handling.
The developer is responsible for implementing a cleanup strategy that is consistent with the behavior of their own trading strategy.
WARNING
The SendRiskGuardConfig1Signal() function provided on this page is an integral part of the official RiskGuard protocol.
The function must be copied in full without any modifications.
The following actions are not permitted:
Modifying the code
Optimizing the code
Refactoring the code
Rewriting the code
Replacing instructions with equivalent alternatives
Adding instructions
Removing instructions
The function must be reproduced exactly, character for character.
Any modification will make the indicator non-compliant with the RiskGuard specifications.
//+------------------------------------------------------------------+
//| Official RiskGuard signal function Config. 1 |
//| |
//| |
//| DO NOT MODIFY THIS FUNCTION. |
//| This function must remain identical in all RiskGuard-compatible |
//| indicators. |
//+------------------------------------------------------------------+
void SendRiskGuardConfig1Signal(string action)
{
GlobalVariableDel("RG_Strategy_Config1_Buy_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Sell_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Close_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Be_" + _Symbol);
if(action == "BUY")
GlobalVariableSet("RG_Strategy_Config1_Buy_" + _Symbol, 1);
else if(action == "SELL")
GlobalVariableSet("RG_Strategy_Config1_Sell_" + _Symbol, 1);
else if(action == "CLOSE")
GlobalVariableSet("RG_Strategy_Config1_Close_" + _Symbol, 1);
else if(action == "BE")
GlobalVariableSet("RG_Strategy_Config1_Be_" + _Symbol, 1);
else
Print("[RG CONFIG 1] Invalid action: ", action);
}
//+------------------------------------------------------------------+
Example:
SendRiskGuardConfig1Signal("BUY");
Example:
SendRiskGuardConfig1Signal("SELL");
Example:
SendRiskGuardConfig1Signal("BE");
Example:
SendRiskGuardConfig1Signal("CLOSE");
double LineaStopBuySell = ObjectGetDouble(ChartID(), "LineaStopBuySell", OBJPROP_PRICE, 0);
double LineaTakeBuySell = ObjectGetDouble(ChartID(), "LineaTakeBuySell", OBJPROP_PRICE, 0);
double LineaMediaBuySell = ObjectGetDouble(ChartID(), "LineaMediaBuySell", OBJPROP_PRICE, 0);
double LineaStopPrevista = ObjectGetDouble(ChartID(), "LineaStopPrevista", OBJPROP_PRICE, 0);
double LineaMediaPrevista = ObjectGetDouble(ChartID(), "LineaMediaPrevista", OBJPROP_PRICE, 0);
After receiving a signal, RiskGuard may:
Open a Buy market order
Open a Sell market order
Move all Config 1 trades to Break Even
Close all Config 1 trades
The indicator is not responsible for performing any of these operations.
When RiskGuard opens trades through Strategy Mode – Config 1, it always uses the following fixed Magic Number:
30033000
for trades opened in response to a signal generated by a RiskGuard-compatible indicator.
This allows indicator developers to easily identify orders and positions generated by Strategy Mode.
For example, an indicator can check whether there are any orders or positions opened by RiskGuard Strategy by filtering for the following Magic Number:
30033000
All other trades opened directly by RiskGuard (outside of Strategy Mode) use Magic Numbers within the reserved RiskGuard range.
Therefore, if a developer wants to monitor only the activity generated by Strategy Mode – Config 1, they must filter exclusively for the following Magic Number:
30033000
The indicator and RiskGuard are separate components.
RiskGuard has no knowledge of the logic used by the indicator to generate a signal.
After receiving a valid signal, RiskGuard behaves exactly as if the user had clicked one of the "BUY", "SELL", "BE", or "CLOSE" buttons on the Config 1 panel.
RiskGuard does not receive any information about the strategy logic.
RiskGuard provides technical support exclusively for:
RiskGuard installation
RiskGuard configuration
RiskGuard features and functionality
Issues directly related to RiskGuard
RiskGuard does not provide free support for:
Third-party trading strategies
Third-party indicators
Code generated using Artificial Intelligence
User-requested custom modifications
For any issues related to the strategy logic or the behavior of an indicator, the user must contact the indicator developer directly.
Receiving a signal does not guarantee that a trade will be opened.
Before opening a trade, RiskGuard applies all standard validation checks performed by the system.
For example:
Invalid multiple signals
Invalid simultaneous BUY and SELL signals
Invalidated opposite-direction signals
User-defined blocking settings in Config 1
Other internal safety checks
If any of these checks prevent the trade from being opened, the signal is ignored, deleted, and no trade is executed.
RiskGuard can be used within the MetaTrader Strategy Tester.
When RiskGuard loads an indicator through the:
StrategyIndicator
parameter, MetaTrader only allows the user to modify RiskGuard's input parameters.
The strategy indicator's input parameters are not directly accessible from the RiskGuard Strategy Tester settings window.
To allow end users to customize the strategy inputs during testing, the developer should provide an .mq5source file containing, at a minimum, the strategy's input definitions.
Example:
input int SignalHour = 9;
input int SignalMinute = 0;
input int StopDistancePoints = 1000;
This allows users to compile the indicator with their desired parameters and use it together with RiskGuard in the Strategy Tester.
To improve performance during backtesting, it is recommended to completely separate the strategy logic from its graphical representation.
Indicators, lines, moving averages, bands, levels, and any other graphical elements used by the strategy should be displayed:
During normal chart operation
During visual backtesting
When a backtest is run in non-visual mode, it is recommended not to create, update, or draw any graphical elements.
This approach provides several advantages:
Significantly faster backtesting
Reduced platform workload
Elimination of unnecessary graphical processing
Full graphical visualization during development, strategy validation, and live trading
The signal-generation logic must continue to operate normally even when all graphical components are disabled.
Visual elements should therefore serve only as graphical aids and must never be required for generating strategy signals.
In MQL5, the current execution mode can be detected using the program properties, for example:
bool showGraphics = true;
if(MQLInfoInteger(MQL_TESTER) &&
!MQLInfoInteger(MQL_VISUAL_MODE))
{
showGraphics = false;
}
The showGraphics variable can then be checked before creating graphical indicators, visible buffers, objects, lines, labels, or any other elements intended solely for visualization.
Example:
if(showGraphics)
{
// Creazione o aggiornamento degli elementi grafici
}
It is also recommended to:
Create the indicator handles required for calculations even during non-visual backtesting
Avoid adding those indicators graphically to the chart when visual mode is not active
Never use graphical objects to store information required by the strategy
Keep the calculation logic, signal-generation logic, and graphical logic in separate sections
Avoid graphical updates on every tick when they are not actually necessary
During strategy development, it is recommended to begin with a few tests in visual mode, verifying that signals, entries, Stop Losses, and Take Profits are consistent with the elements displayed on the chart.
Once correct operation has been confirmed, longer backtests can be performed in non-visual mode to achieve significantly faster execution.
Developers are free to choose how they distribute their strategy.
Both approaches are fully supported.
Fully Open Strategy
Indicator.mq5
Strategy with Protected Logic
Indicator.mq5 ProtectedLibrary.ex5
The .mq5 file may contain:
The strategy input parameters
The SendRiskGuardConfig1Signal() function
The link to the protected library
The proprietary strategy logic can be kept inside one or more compiled libraries.
This allows end users to modify the strategy inputs during testing without gaining access to the proprietary source code.
For normal use on a Demo or Live account, distributing the .mq5 source file is not required.
The end user can simply use the compiled file:
Indicator.ex5
and modify the strategy inputs directly from the indicator's properties on the chart.
Before considering an indicator fully compatible, verify that:
✓ Its name begins with RiskGuard_
✓ It does not use trade execution functions
✓ It does not generate retroactive signals
✓ It does not generate duplicate signals
✓ Its behavior does not change when the chart timeframe is changed
✓ It uses the official RiskGuard Global Variables protocol
✓ All risk management is handled entirely by RiskGuard
This page includes a complete and fully functional example indicator.
The indicator fully complies with the official RiskGuard Strategy specifications and can be used as a reference for developing custom strategies.
The example demonstrates:
How to structure an indicator compatible with RiskGuard
How to prevent duplicate signals
How to avoid retroactive signals
How to correctly send market signals
An extremely simple example indicator.
This indicator automatically generates a signal at a specific time defined by the user.
Its purpose is to demonstrate the minimum functionality required for an indicator to be compatible with RiskGuard.
Main features:
Generation of one or more signals at specific times
Sending BUY, SELL, BE, and CLOSE commands
Use of broker/server time
Protection against duplicate signals
Protection against retroactive signals
Protection against chart timeframe changes
Compatibility with both normal use and the Strategy Tester
This example is recommended as a starting point for understanding the basic integration logic with RiskGuard.
//+------------------------------------------------------------------+
//| RiskGuard_Config1_Demo.mq5 |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
//| Demo indicator for RiskGuard Strategy - Config. 1 |
//| |
//| This indicator is only an educational example. |
//| It does not open, close or modify trades directly. |
//| |
//| All trading operations are handled exclusively by RiskGuard. |
//| |
//| The purpose of this demo is to show how an external indicator |
//| can send BUY, SELL, BE and CLOSE commands to RiskGuard Config. 1 |
//| using the official RiskGuard protocol. |
//+------------------------------------------------------------------+
enum RG_CONFIG1_ACTION
{
ACTION_NONE = 0,
ACTION_BUY = 1,
ACTION_SELL = 2,
ACTION_BE = 3,
ACTION_CLOSE = 4
};
//--- FIRST DEMO SIGNAL
input string First_Signal_Time = "08:00:00";// Format HH:MM:SS using broker/server time.
input RG_CONFIG1_ACTION First_Signal_Action = ACTION_BUY;// Action sent at First_Signal_Time.
//--- NEXT DEMO SIGNALS
input int Signal_02_Seconds_After_First = 60;// 60 = signal 2 starts 1 minute after the first signal.
input RG_CONFIG1_ACTION Signal_02_Action = ACTION_BUY;// Action for signal 2.
input int Signal_03_Seconds_After_First = 120;// 120 = signal 3 starts 2 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_03_Action = ACTION_BUY;// Action for signal 3.
input int Signal_04_Seconds_After_First = 180;// 180 = signal 4 starts 3 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_04_Action = ACTION_BUY;// Action for signal 4.
input int Signal_05_Seconds_After_First = 240;// 240 = signal 5 starts 4 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_05_Action = ACTION_NONE;// Action for signal 5.
input int Signal_06_Seconds_After_First = 300;// 300 = signal 6 starts 5 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_06_Action = ACTION_NONE;// Action for signal 6.
input int Signal_07_Seconds_After_First = 360;// 360 = signal 7 starts 6 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_07_Action = ACTION_NONE;// Action for signal 7.
input int Signal_08_Seconds_After_First = 420;// 420 = signal 8 starts 7 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_08_Action = ACTION_NONE;// Action for signal 8.
input int Signal_09_Seconds_After_First = 480;// 480 = signal 9 starts 8 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_09_Action = ACTION_NONE;// Action for signal 9.
input int Signal_10_Seconds_After_First = 540;// 540 = signal 10 starts 9 minutes after the first signal.
input RG_CONFIG1_ACTION Signal_10_Action = ACTION_CLOSE;// Action for signal 10.
datetime indicatorStartTime;
//+------------------------------------------------------------------+
int OnInit()
{
indicatorStartTime = TimeCurrent();
Print("[RG DEMO CONFIG 1] Indicator started",
" | Symbol=", _Symbol,
" | StartTime=", TimeToString(indicatorStartTime, TIME_DATE|TIME_SECONDS));
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(reason == REASON_CHARTCHANGE)
return;
CleanupIndicatorResources();
Print("[RG DEMO CONFIG 1] Indicator stopped and resources cleaned | Symbol=", _Symbol);
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
const int &spread[])
{
datetime firstTime = BuildTodayTime(First_Signal_Time);
if(firstTime <= 0)
return rates_total;
CheckSlot(1, firstTime, First_Signal_Action);
CheckSlot(2, firstTime + Signal_02_Seconds_After_First, Signal_02_Action);
CheckSlot(3, firstTime + Signal_03_Seconds_After_First, Signal_03_Action);
CheckSlot(4, firstTime + Signal_04_Seconds_After_First, Signal_04_Action);
CheckSlot(5, firstTime + Signal_05_Seconds_After_First, Signal_05_Action);
CheckSlot(6, firstTime + Signal_06_Seconds_After_First, Signal_06_Action);
CheckSlot(7, firstTime + Signal_07_Seconds_After_First, Signal_07_Action);
CheckSlot(8, firstTime + Signal_08_Seconds_After_First, Signal_08_Action);
CheckSlot(9, firstTime + Signal_09_Seconds_After_First, Signal_09_Action);
CheckSlot(10, firstTime + Signal_10_Seconds_After_First, Signal_10_Action);
return rates_total;
}
//+------------------------------------------------------------------+
//| Checks if a demo signal must be sent to RiskGuard Config. 1 |
//+------------------------------------------------------------------+
void CheckSlot(int slot, datetime targetTime, RG_CONFIG1_ACTION action)
{
if(action == ACTION_NONE)
return;
// Prevent retroactive signals.
if(targetTime < indicatorStartTime)
return;
datetime now = TimeCurrent();
// Works in live market and Strategy Tester.
// The signal is sent at the first available tick after targetTime.
if(now < targetTime)
return;
string lastName = LastSignalGVName(slot);
if(GlobalVariableCheck(lastName))
{
datetime lastValue = (datetime)GlobalVariableGet(lastName);
if(lastValue == targetTime)
return;
}
// Save before sending the command to prevent duplicates.
GlobalVariableSet(lastName, (double)targetTime);
string actionText = ActionToString(action);
if(actionText == "")
return;
if(actionText == "BUY")
SendRiskGuardConfig1Signal("BUY");
else if(actionText == "SELL")
SendRiskGuardConfig1Signal("SELL");
else if(actionText == "BE")
SendRiskGuardConfig1Signal("BE");
else if(actionText == "CLOSE")
SendRiskGuardConfig1Signal("CLOSE");
Print("[RG DEMO CONFIG 1] Signal sent",
" | Slot=", slot,
" | TargetTime=", TimeToString(targetTime, TIME_DATE|TIME_SECONDS),
" | Action=", actionText,
" | Symbol=", _Symbol);
}
//+------------------------------------------------------------------+
string ActionToString(RG_CONFIG1_ACTION action)
{
if(action == ACTION_BUY)
return "BUY";
if(action == ACTION_SELL)
return "SELL";
if(action == ACTION_BE)
return "BE";
if(action == ACTION_CLOSE)
return "CLOSE";
return "";
}
//+------------------------------------------------------------------+
string LastSignalGVName(int slot)
{
return "RG_Demo_Config1_LastSignal_" + _Symbol + "_" + IntegerToString(slot);
}
//+------------------------------------------------------------------+
void CleanupIndicatorResources()
{
for(int i = 1; i <= 10; i++)
GlobalVariableDel(LastSignalGVName(i));
// Delete here any graphic object created by this indicator.
// Example:
// ObjectDelete(0, "RG_Demo_Config1_Box");
// ObjectDelete(0, "RG_Demo_Config1_Label");
}
//+------------------------------------------------------------------+
datetime BuildTodayTime(string signalTime)
{
string parts[];
int count = StringSplit(signalTime, ':', parts);
if(count != 3)
{
Print("[RG DEMO CONFIG 1] Invalid time format: ", signalTime,
" | Correct format: HH:MM:SS");
return 0;
}
int h = (int)StringToInteger(parts[0]);
int m = (int)StringToInteger(parts[1]);
int s = (int)StringToInteger(parts[2]);
if(h < 0 || h > 23 || m < 0 || m > 59 || s < 0 || s > 59)
{
Print("[RG DEMO CONFIG 1] Invalid time value: ", signalTime);
return 0;
}
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
dt.hour = h;
dt.min = m;
dt.sec = s;
return StructToTime(dt);
}
//+------------------------------------------------------------------+
//| Official RiskGuard signal function Config. 1 |
//| |
//| |
//| DO NOT MODIFY THIS FUNCTION. |
//| This function must remain identical in all RiskGuard-compatible |
//| indicators. |
//+------------------------------------------------------------------+
void SendRiskGuardConfig1Signal(string action)
{
GlobalVariableDel("RG_Strategy_Config1_Buy_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Sell_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Close_" + _Symbol);
GlobalVariableDel("RG_Strategy_Config1_Be_" + _Symbol);
if(action == "BUY")
GlobalVariableSet("RG_Strategy_Config1_Buy_" + _Symbol, 1);
else if(action == "SELL")
GlobalVariableSet("RG_Strategy_Config1_Sell_" + _Symbol, 1);
else if(action == "CLOSE")
GlobalVariableSet("RG_Strategy_Config1_Close_" + _Symbol, 1);
else if(action == "BE")
GlobalVariableSet("RG_Strategy_Config1_Be_" + _Symbol, 1);
else
Print("[RG CONFIG 1] Invalid action: ", action);
}
//+------------------------------------------------------------------+