top of page

RiskGuard Strategy
Specification Config. 1

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.

Purpose of This Page
 

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.

What the Indicator Must Do
 

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

What the Indicator Must Not Do
 

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.

 

Indicator Name
 

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.

 

Chart Timeframe Independence
 

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.

 

No Retroactive Signals
 

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.

No Duplicate Signals
 

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

No Trade Execution Functions
 

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.

 

Handling Indicator Removal
 

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.

 

Official SendRiskGuardConfig1Signal() Function
 

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);

}

//+------------------------------------------------------------------+

Sending a BUY Signal
 

Example:

 

SendRiskGuardConfig1Signal("BUY");

Sending a SELL Signal
 

Example:

 

SendRiskGuardConfig1Signal("SELL");

Sending a BREAK EVEN Signal
 

Example:

 

SendRiskGuardConfig1Signal("BE");

Sending a CLOSE Signal
 

Example:

 

SendRiskGuardConfig1Signal("CLOSE");

Reading Trading Lines
 

 

  • 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);

What RiskGuard Does After Receiving a Signal
 

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.

 

Magic Numbers Used by RiskGuard
 

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

 

Responsibility and Support
 

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.

 

Technical Support
 

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.

 

Signal Validation
 

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.

 

Strategy Tester Compatibility
 

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.

 

Development and Backtesting Recommendations
 

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.

 

Strategy Logic Protection
 

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.

 

Demo and Live Account Usage
 

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.

Final Checklist
 

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

 

Example Indicators
 

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

Example 1 — RiskGuard_Config1_Demo.mq5
 

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);

}

//+------------------------------------------------------------------+

bottom of page