RiskGuard Strategy Specification Config. 2
Versione B2.01 del 15/07/2026 BETA

Questa pagina contiene l'intera specifica tecnica necessaria per creare indicatori compatibili con RiskGuard Config 2.
L'unico metodo supportato per l'invio dei segnali è la funzione SendRiskGuardConfig2Signal().

Scopo della pagina  
Questa pagina definisce le regole obbligatorie per creare un indicatore MQL5 compatibile con la modalità Strategy di RiskGuard Management.

Il documento è destinato a:

	•	Sviluppatori MQL5
	•	Sistemi di Intelligenza Artificiale
	•	Generatori automatici di codice
	•	Creatori di strategie compatibili con RiskGuard

Quando una regola è indicata come obbligatoria deve essere rispettata senza eccezioni.

L'obiettivo dell'indicatore è esclusivamente generare segnali operativi.

Tutta la gestione del trading viene eseguita da RiskGuard.

Cosa deve fare l'indicatore  
L'indicatore deve:

	•	Analizzare il mercato
	•	Generare segnali operativi
	•	Calcolare lo Stop Loss
	•	Calcolare il Take Profit
	•	Calcolare opzionalmente il prezzo di un ordine pendente
	•	Inviare il segnale a RiskGuard tramite la funzione ufficiale SendRiskGuardConfig2Signal()

Cosa non deve fare l'indicatore  
L'indicatore non deve:

	•	Aprire operazioni
	•	Chiudere operazioni
	•	Modificare operazioni
	•	Calcolare il lotto
	•	Gestire il rischio
	•	Gestire Break Even
	•	Gestire Take Profit parziali
	•	Gestire Trailing Stop
	•	Gestire limiti di perdita giornalieri
	•	Gestire Quantum

Tutte queste funzioni sono gestite esclusivamente da RiskGuard.

Nome dell'indicatore  
Il nome dell'indicatore deve iniziare con:

RiskGuard_

Esempi validi:

RiskGuard_ORB
RiskGuard_MACD
RiskGuard_Stochastic
RiskGuard_Breakout

Esempi non validi:

ORB
MACD
RG_ORB
AutoStrategy

RiskGuard può rifiutare automaticamente indicatori che non iniziano con il prefisso RiskGuard_.

Indipendenza dal timeframe del grafico  
RiskGuard è progettato per operare con una sola finestra grafico per ogni simbolo e salvato come modello default.

L'utente può cambiare liberamente il timeframe del grafico in qualsiasi momento.

L'indicatore deve garantire che il cambio timeframe del grafico non alteri il comportamento della strategia.

Il cambio timeframe non deve:

	•	Modificare la logica della strategia
	•	Modificare i segnali generati
	•	Generare nuovi segnali
	•	Generare segnali duplicati
	•	Generare segnali retroattivi

Se la strategia utilizza uno o più timeframe specifici, questi devono essere definiti internamente dall'indicatore.

La logica della strategia non deve dipendere dal timeframe attualmente visualizzato sul grafico.

Divieto di segnali retroattivi  
L'indicatore deve generare segnali esclusivamente in tempo reale.

Se una condizione operativa si è verificata prima del caricamento dell'indicatore, il segnale deve essere ignorato.

Esempio:

Breakout alle ore 11:00.

Indicatore caricato alle ore 15:00.

Comportamento corretto:

Nessun segnale.

Comportamento errato:

Generare alle 15:00 un segnale relativo al breakout delle 11:00.

Divieto di segnali duplicati  
Lo stesso segnale non deve essere inviato più volte.

Lo sviluppatore dell'indicatore è completamente responsabile della prevenzione dei segnali duplicati.

L'indicatore deve garantire che:

	•	Un refresh del grafico non generi duplicati
	•	Un cambio timeframe non generi duplicati
	•	Una reinizializzazione dell'indicatore non generi duplicati
	•	Lo stesso evento operativo non venga inviato più volte

Divieto di funzioni operative  
Un indicatore compatibile con RiskGuard non deve eseguire direttamente operazioni di trading.

Non devono essere utilizzate funzioni come:

OrderSend()
Buy()
Sell()
PositionOpen()
PositionClose()
PositionModify()
 
RiskGuard è l'unico componente autorizzato ad eseguire operazioni.

Gestione della rimozione dell’indicatore  
Quando un indicatore compatibile con RiskGuard viene rimosso dal grafico, è consigliato ripulire correttamente tutte le risorse create dall’indicatore.

Ad esempio:

	•	Global Variables interne all’indicatore
	•	Oggetti grafici
	•	Box
	•	Linee
	•	Label
	•	Variabili di stato persistenti

Questo riduce il rischio di:

	•	segnali duplicati
	•	segnali residui
	•	oggetti lasciati sul grafico
	•	comportamenti inattesi al riavvio dell’indicatore

È consigliato implementare questa logica all’interno di:

OnDeinit()

Particolare attenzione deve essere posta al caso:

REASON_CHARTCHANGE

MetaTrader reinizializza l’indicatore anche durante il cambio timeframe.

In molti casi, cancellare tutte le variabili durante REASON_CHARTCHANGE può causare segnali duplicati dopo il reload.

Per questo motivo, la logica di cleanup deve essere progettata con attenzione in base al comportamento della strategia.

Esempio:

void OnDeinit(const int reason)
  {
   if(reason == REASON_CHARTCHANGE)
      return;

      GlobalVariableDel(LastSignalGVName());       ObjectDelete(0, "MyStrategyBox");       ObjectDelete(0, "MyStrategyLine");

  }

La logica di cleanup dipende interamente dal comportamento della strategia.

Non tutti gli indicatori richiedono la stessa gestione in OnDeinit().

Lo sviluppatore è responsabile di implementare una logica coerente con il comportamento della propria strategia.

Funzione ufficiale SendRiskGuardConfig2Signal()  
ATTENZIONE
 
La funzione SendRiskGuardConfig2Signal() riportata in questa pagina è parte integrante del protocollo ufficiale RiskGuard.
 
La funzione deve essere copiata integralmente senza alcuna modifica.
 
Non è consentito:
 
- modificare il codice
- ottimizzare il codice
- rifattorizzare il codice
- riscrivere il codice
- sostituire istruzioni equivalenti
- aggiungere istruzioni
- rimuovere istruzioni
 
La funzione deve essere riportata identica carattere per carattere.
 
Qualsiasi modifica rende l'indicatore non conforme alle specifiche RiskGuard.

//+------------------------------------------------------------------+
//| Official RiskGuard signal function - Config. 2                   |
//|                                                                  |
//| pendingPrice = 0.0  -> market order                              |
//| pendingPrice > 0.0  -> pending order                             |
//|                                                                  |
//| DO NOT MODIFY THIS FUNCTION.                                     |
//| This function must remain identical in all RiskGuard-compatible  |
//| indicators.                                                      |
//+------------------------------------------------------------------+
void SendRiskGuardConfig2Signal(double stopPrice,
                         double takePrice,
                         double pendingPrice = 0.0)
  {
   //--- Always delete old RiskGuard variables first
   GlobalVariableDel("RG_Strategy_Config2_Symbol_" + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Stop_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Take_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Price_"  + _Symbol);
 
   //--- Normalize prices
   stopPrice = NormalizeDouble(stopPrice, _Digits);
   takePrice = NormalizeDouble(takePrice, _Digits);
 
   if(pendingPrice > 0.0)
      pendingPrice = NormalizeDouble(pendingPrice, _Digits);
 
   bool isPending = (pendingPrice > 0.0);
 
   //--- Create variables in the correct order
   GlobalVariableSet("RG_Strategy_Config2_Stop_" + _Symbol, stopPrice);
   GlobalVariableSet("RG_Strategy_Config2_Take_" + _Symbol, takePrice);
 
   if(isPending)
      GlobalVariableSet("RG_Strategy_Config2_Price_" + _Symbol, pendingPrice);
 
   //--- RG_Strategy_Symbol must always be created last
   GlobalVariableSet("RG_Strategy_Config2_Symbol_" + _Symbol, 1);
 
   //--- Log
   if(isPending)
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Pending signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Price=", DoubleToString(pendingPrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
   else
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Market signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
  }

Invio di un segnale a mercato  
Esempio:

 
SendRiskGuardConfig2Signal(stopPrice, takePrice);

Invio di un segnale pendente  
Esempio:

 
SendRiskGuardConfig2Signal(stopPrice, takePrice, pendingPrice);

Cosa fa RiskGuard dopo aver ricevuto un segnale  
Dopo aver ricevuto un segnale, RiskGuard può:

	•	Validare i prezzi
	•	Determinare automaticamente BUY o SELL
	•	Calcolare il lotto
	•	Calcolare il rischio
	•	Applicare Quantum
	•	Applicare limiti di esposizione
	•	Applicare Break Even
	•	Applicare Take Profit parziali
	•	Applicare Trailing Stop
	•	Aprire ordini a mercato
	•	Aprire ordini pendenti
	•	Gestire le posizioni aperte

L'indicatore non è responsabile di nessuna di queste operazioni.

Magic Number utilizzati da RiskGuard  
Quando RiskGuard apre operazioni tramite la modalità Strategy in "CONFIG. 2", utilizza sempre il seguente Magic Number fisso:

30032999

Questo vale sia per:

	•	ordini a mercato
	•	ordini pendenti

aperti in seguito a un segnale generato da un indicatore compatibile con RiskGuard.

Questo permette allo sviluppatore dell’indicatore di identificare facilmente ordini e posizioni generate dalla modalità Strategy.

Ad esempio, un indicatore può verificare se esistono posizioni o ordini aperti da RiskGuard Strategy filtrando il Magic Number:

30032999

Tutti gli altri trade aperti direttamente da RiskGuard (non tramite Strategy Mode) utilizzano invece Magic Number appartenenti al range riservato RiskGuard.

Per questo motivo, se uno sviluppatore desidera monitorare esclusivamente l’attività generata dalla Strategy Mode "CONFIG. 2", deve filtrare esclusivamente il Magic Number:

30032999

Responsabilità e supporto  
L'indicatore e RiskGuard sono componenti separati.

RiskGuard non conosce la logica utilizzata dall'indicatore per generare il segnale.

Dopo aver ricevuto un segnale valido, RiskGuard si comporta esattamente come se l'utente avesse premuto il pulsante "CALC" nel pannello, inserito manualmente i prezzi e premuto il pulsante "OPEN".

L'unica informazione ricevuta da RiskGuard è:

	•	Prezzo di apertura (solo per ordini pendenti)
	•	Stop Loss
	•	Take Profit

RiskGuard non riceve informazioni sulla logica della strategia.

Supporto tecnico  
RiskGuard fornisce supporto esclusivamente per:

	•	Installazione di RiskGuard
	•	Configurazione di RiskGuard
	•	Funzionamento delle funzioni di RiskGuard
	•	Problemi relativi a RiskGuard

RiskGuard non fornisce supporto gratuito per:

	•	Strategie sviluppate da terze parti
	•	Indicatori sviluppati da terze parti
	•	Codice creato tramite Intelligenza Artificiale
	•	Modifiche personalizzate richieste dagli utenti

Per qualsiasi problema relativo alla logica della strategia o al funzionamento dell'indicatore, l'utente deve contattare direttamente lo sviluppatore dell'indicatore.

Validazione del segnale  
La ricezione di un segnale non garantisce l'apertura di un'operazione.

Prima dell'apertura, RiskGuard applica tutti i controlli normalmente previsti dal sistema.

Ad esempio:

	•	Stop Loss & DD Block
	•	Limiti di esposizione
	•	Controlli sui prezzi
	•	Controlli sul rischio
	•	Altri controlli interni di sicurezza

Se uno dei controlli impedisce l'apertura dell'operazione, il segnale viene ignorato ed eliminato e nessun trade viene aperto.

Compatibilità con Strategy Tester  
RiskGuard può essere utilizzato all'interno dello Strategy Tester di MetaTrader.

Quando RiskGuard carica un indicatore tramite il parametro:

StrategyIndicator

MetaTrader consente di modificare esclusivamente gli input di RiskGuard.

Gli input dell'indicatore strategico non sono accessibili direttamente dalla finestra dello Strategy Tester di RiskGuard.

Per consentire all'utente finale di modificare gli input della strategia durante i test, lo sviluppatore deve fornire un file .mq5
contenente almeno la definizione degli input della strategia.

Esempio:

input int SignalHour = 9;

input int SignalMinute = 0;

input int StopDistancePoints = 1000;

Questo permette all'utente di compilare l'indicatore con i parametri desiderati e utilizzarlo nello Strategy Tester insieme a RiskGuard.

Consigli per lo sviluppo e il backtest
 
Per migliorare le prestazioni durante il backtest, è consigliabile separare completamente la logica della strategia dalla sua rappresentazione grafica.

Gli indicatori, le linee, le medie mobili, le bande, i livelli e tutti gli altri elementi grafici utilizzati dalla strategia dovrebbero essere visualizzati:

	•	durante il normale utilizzo sul grafico;
	•	durante un backtest eseguito in modalità visuale.

Quando invece il backtest viene eseguito senza modalità visuale, è consigliabile non creare, non aggiornare e non disegnare alcun elemento grafico.

Questa soluzione permette di:

	•	velocizzare sensibilmente il backtest;
	•	ridurre il carico sulla piattaforma;
	•	evitare elaborazioni grafiche inutili;
	•	mantenere comunque tutti gli elementi visibili durante lo sviluppo, il controllo della strategia e l’utilizzo reale.

La logica che calcola i segnali deve continuare a funzionare normalmente anche quando la parte grafica è disattivata. Gli elementi visivi devono quindi essere utilizzati esclusivamente come supporto grafico e non devono essere necessari per generare i segnali della strategia.

In MQL5 è possibile verificare la modalità di esecuzione utilizzando le proprietà del programma, ad esempio:

 
bool showGraphics = true;
 
if(MQLInfoInteger(MQL_TESTER) &&
!MQLInfoInteger(MQL_VISUAL_MODE))
{
showGraphics = false;
}
 
La variabile showGraphics può quindi essere controllata prima di creare indicatori grafici, buffer visibili, oggetti, linee, etichette o altri elementi destinati esclusivamente alla visualizzazione.

Esempio:

 
if(showGraphics)
{
// Creazione o aggiornamento degli elementi grafici
}
 
È inoltre consigliabile:

	•	creare gli handle degli indicatori necessari ai calcoli anche nel backtest non visuale;
	•	evitare invece di aggiungerli graficamente al chart quando la modalità visuale non è attiva;
	•	non utilizzare oggetti grafici per memorizzare informazioni indispensabili alla strategia;
	•	mantenere separati il blocco di calcolo, il blocco di generazione dei segnali e il blocco grafico;
	•	evitare aggiornamenti grafici a ogni tick quando non sono realmente necessari.

Durante la creazione della strategia è consigliabile effettuare inizialmente alcuni test in modalità visuale, verificando che segnali, ingressi, Stop Loss e Take Profit siano coerenti con gli elementi mostrati sul grafico. Una volta verificato il corretto funzionamento, i test più lunghi possono essere eseguiti senza modalità visuale per ottenere una maggiore velocità.

Protezione della logica della strategia  
Lo sviluppatore può scegliere liberamente come distribuire la propria strategia.

Sono supportati entrambi gli approcci.

Strategia completamente aperta:

Indicatore.mq5

Strategia con logica protetta:

Indicatore.mq5

LibreriaProtetta.ex5

Il file .mq5 può contenere:

	•	Gli input della strategia
	•	La funzione SendRiskGuardConfig2Signal()
	•	Il collegamento alla libreria

La logica proprietaria può essere mantenuta all'interno di una o più librerie compilate.

In questo modo l'utente finale può modificare gli input della strategia durante i test senza avere accesso al codice proprietario.

Utilizzo su conto Demo o Reale  
Per l'utilizzo normale su conto Demo o Reale non è necessario distribuire il file .mq5.

L'utente può utilizzare normalmente il solo file:

Indicatore.ex5

e modificare gli input direttamente dalle proprietà dell'indicatore sul grafico.

Checklist finale  
Prima di considerare compatibile un indicatore verificare che:

✓ Il nome inizi con RiskGuard_

✓ Non utilizzi funzioni operative

✓ Non generi segnali retroattivi

✓ Non generi segnali duplicati

✓ Il comportamento non cambi al cambio timeframe del grafico

✓ Utilizzi SendRiskGuardConfig2Signal()

✓ La funzione SendRiskGuardConfig2Signal() non sia stata modificata

✓ Stop Loss e Take Profit siano calcolati dall'indicatore

✓ La gestione del rischio sia lasciata interamente a RiskGuard

Indicatori di esempio  
Questa pagina include due indicatori di esempio completi e funzionanti.

Entrambi rispettano integralmente le specifiche ufficiali di RiskGuard Strategy e possono essere usati come riferimento per sviluppare strategie personalizzate.

Gli esempi hanno lo scopo di mostrare:

	•	come strutturare un indicatore compatibile con RiskGuard
	•	come prevenire segnali duplicati
	•	come evitare segnali retroattivi
	•	come inviare correttamente segnali a mercato o pendenti

Esempio 1 — RiskGuard_auto.mq5  
Indicatore di esempio estremamente semplice.

Questo indicatore genera un segnale automatico a un orario specifico definito dall’utente.

L’obiettivo è mostrare il funzionamento minimo richiesto per un indicatore compatibile con RiskGuard.

Funzioni principali:

	•	Generazione di un segnale a un orario preciso
	•	Supporto ordini a mercato o pendenti
	•	Calcolo automatico di Stop Loss e Take Profit
	•	Protezione da segnali duplicati
	•	Protezione da segnali retroattivi
	•	Protezione da cambio timeframe

Questo esempio è consigliato come punto di partenza per comprendere la logica base di integrazione con RiskGuard.

//+------------------------------------------------------------------+
//|                                           RiskGuard_auto.mq5     |
//+------------------------------------------------------------------+
//| RiskGuard Example Strategy Indicator                             |
//|                                                                  |
//| This indicator shows the minimum logic needed to send a trading  |
//| signal from a custom indicator to RiskGuard.                     |
//|                                                                  |
//| The example generates a signal at a specific broker/server time. |
//|                                                                  |
//| Developers can replace the example signal logic with their own   |
//| strategy while keeping SendRiskGuardConfig2Signal() unchanged.          |
//|                                                                  |
//| IMPORTANT                                                        |
//| SendRiskGuardConfig2Signal() is the official RiskGuard integration      |
//| function and should not be modified.                             |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0
 
input int SignalHour          = 11;      // Broker/server hour when the signal must be generated
input int SignalMinute        = 0;       // Broker/server minute when the signal must be generated
input int StopDistancePoints  = 40000;   // Stop Loss distance from entry price, in points
input int TakeDistancePoints  = 40000;   // Take Profit distance from entry price, in points
input int PriceDistancePoints = 0;   // 0 = market order, >0 = pending order distance from current price, in points

//+------------------------------------------------------------------+
//| Last signal Global Variable name                                 |
//+------------------------------------------------------------------+
//| The Global Variable name includes:                               |
//| - RG prefix                                                      |
//| - indicator program name                                         |
//| - symbol                                                         |
//| - variable purpose                                               |
//|                                                                  |
//| This prevents conflicts when the same indicator is used on        |
//| multiple symbols or charts.                                      |
//+------------------------------------------------------------------+
string LastSignalGVName()
  {
   return "RG_" + MQLInfoString(MQL_PROGRAM_NAME) + "_" + _Symbol + "_LastSignal";
  }

//+------------------------------------------------------------------+
//| Check if a signal was already generated in this server minute    |
//+------------------------------------------------------------------+
//| MetaTrader reloads indicators when the chart timeframe changes.  |
//|                                                                  |
//| Without this protection, changing timeframe during the same      |
//| signal minute could generate the same RiskGuard signal again.    |
//|                                                                  |
//| The Global Variable stores TimeCurrent() when the signal is sent. |
//| The comparison ignores seconds and checks only:                  |
//| year, month, day, hour and minute.                               |
//|                                                                  |
//| This means:                                                      |
//| - 11:10:03 and 11:10:25 are treated as the same signal minute    |
//| - 11:10 and 11:45 are treated as different possible signals      |
//+------------------------------------------------------------------+
bool SignalAlreadySentThisMinute()
  {
   string gvName = LastSignalGVName();
 
   if(!GlobalVariableCheck(gvName))
      return false;
 
   datetime lastSignal = (datetime)GlobalVariableGet(gvName);
 
   MqlDateTime lastTm;
   MqlDateTime nowTm;
 
   TimeToStruct(lastSignal, lastTm);
   TimeToStruct(TimeCurrent(), nowTm);
 
   if(lastTm.year == nowTm.year &&
      lastTm.mon  == nowTm.mon  &&
      lastTm.day  == nowTm.day  &&
      lastTm.hour == nowTm.hour &&
      lastTm.min  == nowTm.min)
      return true;
 
   return false;
  }

//+------------------------------------------------------------------+
//| Save last signal timestamp                                       |
//+------------------------------------------------------------------+
//| The exact server timestamp is stored.                            |
//| Seconds are useful for logs/debugging, but duplicate protection  |
//| compares only up to the minute.                                  |
//+------------------------------------------------------------------+
void SaveLastSignal()
  {
   GlobalVariableSet(LastSignalGVName(), (double)TimeCurrent());
  }

//+------------------------------------------------------------------+
//| Official RiskGuard signal function - Config. 2                   |
//|                                                                  |
//| pendingPrice = 0.0  -> market order                              |
//| pendingPrice > 0.0  -> pending order                             |
//|                                                                  |
//| DO NOT MODIFY THIS FUNCTION.                                     |
//| This function must remain identical in all RiskGuard-compatible  |
//| indicators.                                                      |
//+------------------------------------------------------------------+
void SendRiskGuardConfig2Signal(double stopPrice,
                         double takePrice,
                         double pendingPrice = 0.0)
  {
   //--- Always delete old RiskGuard variables first
   GlobalVariableDel("RG_Strategy_Config2_Symbol_" + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Stop_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Take_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Price_"  + _Symbol);
 
   //--- Normalize prices
   stopPrice = NormalizeDouble(stopPrice, _Digits);
   takePrice = NormalizeDouble(takePrice, _Digits);
 
   if(pendingPrice > 0.0)
      pendingPrice = NormalizeDouble(pendingPrice, _Digits);
 
   bool isPending = (pendingPrice > 0.0);
 
   //--- Create variables in the correct order
   GlobalVariableSet("RG_Strategy_Config2_Stop_" + _Symbol, stopPrice);
   GlobalVariableSet("RG_Strategy_Config2_Take_" + _Symbol, takePrice);
 
   if(isPending)
      GlobalVariableSet("RG_Strategy_Config2_Price_" + _Symbol, pendingPrice);
 
   //--- RG_Strategy_Symbol must always be created last
   GlobalVariableSet("RG_Strategy_Config2_Symbol_" + _Symbol, 1);
 
   //--- Log
   if(isPending)
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Pending signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Price=", DoubleToString(pendingPrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
   else
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Market signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
  }

//+------------------------------------------------------------------+
//| OnInit                                                           |
//+------------------------------------------------------------------+
int OnInit()
  {
   Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][OnInit] Indicator started",
         " | Symbol=", _Symbol);
 
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//+------------------------------------------------------------------+
//| Do not delete LastSignal during timeframe changes.               |
//| Otherwise the same signal could be generated again after reload. |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(reason == REASON_REMOVE)
     {
      GlobalVariableDel(LastSignalGVName());
 
      Print("[", MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][OnDeinit] Indicator manually removed",
            " | Symbol=", _Symbol,
            " | LastSignalGV deleted");
     }
  }

//+------------------------------------------------------------------+
//| OnCalculate                                                      |
//+------------------------------------------------------------------+
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[])
  {
   MqlDateTime tm;
   TimeToStruct(TimeCurrent(), tm);
 
   //--- This example uses broker/server time.
   if(tm.hour != SignalHour || tm.min != SignalMinute)
      return(rates_total);
 
   //--- Prevent duplicate signals in the same server minute.
   if(SignalAlreadySentThisMinute())
      return(rates_total);
 
   //--- The current Bid price is used as reference price.
   double price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
 
   if(price <= 0.0)
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][ERROR] Invalid price",
            " | Symbol=", _Symbol);
      return(rates_total);
     }
 
   double stopPrice;
   double takePrice;
   double pendingPrice = 0.0;
 
   //--- Pending order example.
   if(PriceDistancePoints > 0)
     {
      pendingPrice = price + PriceDistancePoints * _Point;
 
      stopPrice = pendingPrice - StopDistancePoints * _Point;
      takePrice = pendingPrice + TakeDistancePoints * _Point;
 
      SendRiskGuardConfig2Signal(stopPrice, takePrice, pendingPrice);
     }
 
   //--- Market order example.
   else
     {
      stopPrice = price - StopDistancePoints * _Point;
      takePrice = price + TakeDistancePoints * _Point;
 
      SendRiskGuardConfig2Signal(stopPrice, takePrice);
     }
 
   //--- Save only after the RiskGuard variables have been created.
   SaveLastSignal();
 
   return(rates_total);
  }
//+------------------------------------------------------------------+

Esempio 2 — RiskGuard_ORB.mq5  
Indicatore di esempio avanzato basato su strategia ORB (Opening Range Breakout).

L’indicatore calcola un range orario definito dall’utente, disegna il box sul grafico e genera un segnale quando una candela chiusa rompe il range verso l’alto o verso il basso.

Questo esempio mostra una struttura più realistica e vicina a una strategia automatica completa.

Funzioni principali:

	•	Calcolo automatico del range ORB
	•	Disegno del box direttamente sul grafico
	•	Rilevazione breakout BUY e SELL su chiusura candela
	•	Supporto ordini a mercato o pendenti
	•	Calcolo dei prezzi di Stop Loss e Take Profit in base al rapporto Risk:Reward
	•	Protezione da segnali duplicati
	•	Protezione da segnali retroattivi
	•	Protezione da cambio timeframe
	•	Rilevazione ordini Strategy tramite Magic Number 30032999

Questo esempio è consigliato per sviluppatori che vogliono costruire strategie più complesse compatibili con RiskGuard.

//+------------------------------------------------------------------+
//|                                      RiskGuard_ORB_Example.mq5   |
//|                                                                  |
//| Example indicator for RiskGuard Strategy Mode - Config. 2        |
//|                                                                  |
//| This indicator does NOT open trades directly.                    |
//| It only sends market or pending signals to RiskGuard using the   |
//| official RiskGuard Config. 2 protocol.                           |
//|                                                                  |
//| RiskGuard manages the order, lot size, risk, Stop Loss,           |
//| Take Profit, Break Even, partial profits, trailing stop,          |
//| daily loss limits, Quantum and all other trading operations.      |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window
#property indicator_plots 0

//+------------------------------------------------------------------+
//| Strategy inputs                                                  |
//+------------------------------------------------------------------+
input int RangeStartHour   = 6;   // ORB range start hour
input int RangeStartMinute = 0;   // ORB range start minute
 
input int RangeEndHour     = 11;  // ORB range end hour
input int RangeEndMinute   = 0;   // ORB range end minute
 
input ENUM_TIMEFRAMES BreakoutTimeframe = PERIOD_M1; // Breakout detection timeframe
 
input double EntryPercent = 0.0;  // 0 = market, 50 = pending at 50% of the box
input double RiskReward   = 2.0;  // Take Profit expressed as Risk:Reward ratio
 
input color BoxColor = clrDodgerBlue; // ORB box color

//+------------------------------------------------------------------+
//| Internal variables                                               |
//+------------------------------------------------------------------+
datetime IndicatorLoadTime = 0;
datetime LastBreakoutBarTime = 0;
 
bool ActivityDetectedAfterSignal = false;
bool ShowGraphics = true;

//+------------------------------------------------------------------+
//| Official RiskGuard signal function - Config. 2                   |
//|                                                                  |
//| pendingPrice = 0.0  -> market order                              |
//| pendingPrice > 0.0  -> pending order                             |
//|                                                                  |
//| DO NOT MODIFY THIS FUNCTION.                                     |
//| This function must remain identical in all RiskGuard-compatible  |
//| indicators.                                                      |
//+------------------------------------------------------------------+
void SendRiskGuardConfig2Signal(double stopPrice,
                         double takePrice,
                         double pendingPrice = 0.0)
  {
   //--- Always delete old RiskGuard variables first
   GlobalVariableDel("RG_Strategy_Config2_Symbol_" + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Stop_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Take_"   + _Symbol);
   GlobalVariableDel("RG_Strategy_Config2_Price_"  + _Symbol);
 
   //--- Normalize prices
   stopPrice = NormalizeDouble(stopPrice, _Digits);
   takePrice = NormalizeDouble(takePrice, _Digits);
 
   if(pendingPrice > 0.0)
      pendingPrice = NormalizeDouble(pendingPrice, _Digits);
 
   bool isPending = (pendingPrice > 0.0);
 
   //--- Create variables in the correct order
   GlobalVariableSet("RG_Strategy_Config2_Stop_" + _Symbol, stopPrice);
   GlobalVariableSet("RG_Strategy_Config2_Take_" + _Symbol, takePrice);
 
   if(isPending)
      GlobalVariableSet("RG_Strategy_Config2_Price_" + _Symbol, pendingPrice);
 
   //--- RG_Strategy_Symbol must always be created last
   GlobalVariableSet("RG_Strategy_Config2_Symbol_" + _Symbol, 1);
 
   //--- Log
   if(isPending)
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Pending signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Price=", DoubleToString(pendingPrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
   else
     {
      Print("[", MQLInfoString(MQL_PROGRAM_NAME), "][INDICATOR][SIGNAL] Market signal variables created",
            " | Symbol=", _Symbol,
            " | Stop=", DoubleToString(stopPrice, _Digits),
            " | Take=", DoubleToString(takePrice, _Digits),
            " | Bid=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_BID), _Digits),
            " | Ask=", DoubleToString(SymbolInfoDouble(_Symbol, SYMBOL_ASK), _Digits));
     }
  }

//+------------------------------------------------------------------+
//| Returns a numeric key for the trading day                        |
//+------------------------------------------------------------------+
int DayKey(datetime timeValue)
  {
   MqlDateTime dateTime;
   TimeToStruct(timeValue, dateTime);
 
   return(dateTime.year * 10000 +
          dateTime.mon  * 100 +
          dateTime.day);
  }

//+------------------------------------------------------------------+
//| Builds today's broker/server time                                |
//+------------------------------------------------------------------+
datetime TodayTime(int hour, int minute)
  {
   MqlDateTime dateTime;
   TimeToStruct(TimeCurrent(), dateTime);
 
   dateTime.hour = hour;
   dateTime.min  = minute;
   dateTime.sec  = 0;
 
   return(StructToTime(dateTime));
  }

//+------------------------------------------------------------------+
//| Internal Global Variable used for duplicate protection           |
//|                                                                  |
//| This is NOT a RiskGuard trade signal.                            |
//|                                                                  |
//| It remembers that the ORB signal for the current day has already |
//| been sent. It must remain available during timeframe changes,    |
//| input changes, refreshes and indicator reinitializations.         |
//+------------------------------------------------------------------+
string LastSignalGVName()
  {
   return("RiskGuard_ORB_LastSignal_" +
          MQLInfoString(MQL_PROGRAM_NAME) +
          "_" +
          _Symbol);
  }

//+------------------------------------------------------------------+
//| Checks if today's ORB signal has already been sent               |
//+------------------------------------------------------------------+
bool AlreadySentToday()
  {
   string globalVariableName = LastSignalGVName();
 
   if(!GlobalVariableCheck(globalVariableName))
      return(false);
 
   int savedDay = (int)GlobalVariableGet(globalVariableName);
 
   return(savedDay == DayKey(TimeCurrent()));
  }

//+------------------------------------------------------------------+
//| Saves today's ORB signal status                                  |
//+------------------------------------------------------------------+
void SaveSignalToday()
  {
   GlobalVariableSet(LastSignalGVName(),
                     (double)DayKey(TimeCurrent()));
  }

//+------------------------------------------------------------------+
//| Returns today's ORB box name                                     |
//+------------------------------------------------------------------+
string BoxName()
  {
   return("RiskGuard_ORB_Box_" +
          MQLInfoString(MQL_PROGRAM_NAME) +
          "_" +
          _Symbol +
          "_" +
          IntegerToString(DayKey(TimeCurrent())));
  }

//+------------------------------------------------------------------+
//| Deletes today's ORB box                                          |
//+------------------------------------------------------------------+
void DeleteBox()
  {
   if(!ShowGraphics)
      return;
 
   ObjectDelete(0, BoxName());
  }

//+------------------------------------------------------------------+
//| Deletes ORB boxes belonging to previous days                     |
//+------------------------------------------------------------------+
void DeleteOldBoxes()
  {
   if(!ShowGraphics)
      return;
 
   string prefix =
      "RiskGuard_ORB_Box_" +
      MQLInfoString(MQL_PROGRAM_NAME) +
      "_" +
      _Symbol +
      "_";
 
   string today = IntegerToString(DayKey(TimeCurrent()));
 
   int totalObjects = ObjectsTotal(0);
 
   for(int i = totalObjects - 1; i >= 0; i--)
     {
      string objectName = ObjectName(0, i);
 
      if(StringFind(objectName, prefix) != 0)
         continue;
 
      if(StringFind(objectName, today) >= 0)
         continue;
 
      ObjectDelete(0, objectName);
     }
  }

//+------------------------------------------------------------------+
//| Checks RiskGuard Strategy positions and pending orders           |
//|                                                                  |
//| RiskGuard Config. 2 Strategy orders use Magic Number 30032999.   |
//+------------------------------------------------------------------+
bool HasRiskGuardStrategyPositionOrOrder()
  {
   const long strategyMagic = 30032999;
 
   for(int i = PositionsTotal() - 1; i >= 0; i--)
     {
      string positionSymbol = PositionGetSymbol(i);
 
      if(positionSymbol != _Symbol)
         continue;
 
      long positionMagic = PositionGetInteger(POSITION_MAGIC);
 
      if(positionMagic == strategyMagic)
         return(true);
     }
 
   for(int i = OrdersTotal() - 1; i >= 0; i--)
     {
      ulong ticket = OrderGetTicket(i);
 
      if(ticket == 0)
         continue;
 
      string orderSymbol = OrderGetString(ORDER_SYMBOL);
 
      if(orderSymbol != _Symbol)
         continue;
 
      long orderMagic = OrderGetInteger(ORDER_MAGIC);
 
      if(orderMagic == strategyMagic)
         return(true);
     }
 
   return(false);
  }

//+------------------------------------------------------------------+
//| Calculates today's ORB range                                     |
//+------------------------------------------------------------------+
bool GetOrbRange(double &rangeHigh,
                 double &rangeLow)
  {
   datetime startTime =
      TodayTime(RangeStartHour, RangeStartMinute);
 
   datetime endTime =
      TodayTime(RangeEndHour, RangeEndMinute);
 
   if(endTime <= startTime)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Invalid ORB time range",
            " | Start=",
            TimeToString(startTime, TIME_DATE | TIME_MINUTES),
            " | End=",
            TimeToString(endTime, TIME_DATE | TIME_MINUTES));
 
      return(false);
     }
 
   MqlRates rangeRates[];
   ArraySetAsSeries(rangeRates, false);
 
   int copiedBars =
      CopyRates(_Symbol,
                BreakoutTimeframe,
                startTime,
                endTime,
                rangeRates);
 
   if(copiedBars <= 0)
      return(false);
 
   rangeHigh = rangeRates[0].high;
   rangeLow  = rangeRates[0].low;
 
   for(int i = 1; i < copiedBars; i++)
     {
      if(rangeRates[i].high > rangeHigh)
         rangeHigh = rangeRates[i].high;
 
      if(rangeRates[i].low < rangeLow)
         rangeLow = rangeRates[i].low;
     }
 
   rangeHigh = NormalizeDouble(rangeHigh, _Digits);
   rangeLow  = NormalizeDouble(rangeLow, _Digits);
 
   if(rangeHigh <= rangeLow)
      return(false);
 
   return(true);
  }

//+------------------------------------------------------------------+
//| Creates or updates today's ORB box                               |
//+------------------------------------------------------------------+
void DrawBox(double rangeHigh,
             double rangeLow)
  {
   if(!ShowGraphics)
      return;
 
   datetime startTime =
      TodayTime(RangeStartHour, RangeStartMinute);
 
   datetime endTime =
      TodayTime(RangeEndHour, RangeEndMinute);
 
   string objectName = BoxName();
 
   if(ObjectFind(0, objectName) < 0)
     {
      if(!ObjectCreate(0,
                       objectName,
                       OBJ_RECTANGLE,
                       0,
                       startTime,
                       rangeHigh,
                       endTime,
                       rangeLow))
        {
         Print("[",
               MQLInfoString(MQL_PROGRAM_NAME),
               "][INDICATOR][ERROR] Unable to create ORB box",
               " | Error=",
               GetLastError());
 
         return;
        }
 
      ObjectSetInteger(0, objectName, OBJPROP_COLOR, BoxColor);
      ObjectSetInteger(0, objectName, OBJPROP_BACK, true);
      ObjectSetInteger(0, objectName, OBJPROP_FILL, false);
      ObjectSetInteger(0, objectName, OBJPROP_WIDTH, 1);
      ObjectSetInteger(0, objectName, OBJPROP_SELECTABLE, false);
      ObjectSetInteger(0, objectName, OBJPROP_HIDDEN, true);
     }
   else
     {
      ObjectMove(0,
                 objectName,
                 0,
                 startTime,
                 rangeHigh);
 
      ObjectMove(0,
                 objectName,
                 1,
                 endTime,
                 rangeLow);
     }
  }

//+------------------------------------------------------------------+
//| Validates the strategy inputs                                    |
//+------------------------------------------------------------------+
bool ValidateInputs()
  {
   if(RangeStartHour < 0 || RangeStartHour > 23)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Invalid RangeStartHour");
 
      return(false);
     }
 
   if(RangeEndHour < 0 || RangeEndHour > 23)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Invalid RangeEndHour");
 
      return(false);
     }
 
   if(RangeStartMinute < 0 || RangeStartMinute > 59)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Invalid RangeStartMinute");
 
      return(false);
     }
 
   if(RangeEndMinute < 0 || RangeEndMinute > 59)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Invalid RangeEndMinute");
 
      return(false);
     }
 
   if(RiskReward <= 0.0)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] RiskReward must be greater than zero");
 
      return(false);
     }
 
   datetime startTime =
      TodayTime(RangeStartHour, RangeStartMinute);
 
   datetime endTime =
      TodayTime(RangeEndHour, RangeEndMinute);
 
   if(endTime <= startTime)
     {
      Print("[",
            MQLInfoString(MQL_PROGRAM_NAME),
            "][INDICATOR][ERROR] Range end time must be later than range start time");
 
      return(false);
     }
 
   return(true);
  }

//+------------------------------------------------------------------+
//| OnInit                                                           |
//+------------------------------------------------------------------+
int OnInit()
  {
   IndicatorLoadTime = TimeCurrent();
   LastBreakoutBarTime = 0;
   ActivityDetectedAfterSignal = false;
 
   ShowGraphics = true;
 
   if(MQLInfoInteger(MQL_TESTER) &&
      !MQLInfoInteger(MQL_VISUAL_MODE))
     {
      ShowGraphics = false;
     }
 
   if(!ValidateInputs())
      return(INIT_PARAMETERS_INCORRECT);
 
   Print("[",
         MQLInfoString(MQL_PROGRAM_NAME),
         "][INDICATOR][OnInit] ORB indicator started",
         " | Symbol=",
         _Symbol,
         " | BreakoutTimeframe=",
         EnumToString(BreakoutTimeframe),
         " | ShowGraphics=",
         ShowGraphics ? "true" : "false",
         " | LoadTime=",
         TimeToString(IndicatorLoadTime,
                      TIME_DATE | TIME_SECONDS));
 
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| OnDeinit                                                         |
//|                                                                  |
//| The duplicate-protection Global Variable is not deleted during   |
//| timeframe changes, input changes or other reinitializations.      |
//|                                                                  |
//| It is deleted only when the indicator is manually removed.       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(reason == REASON_REMOVE)
     {
      GlobalVariableDel(LastSignalGVName());
 
      if(ShowGraphics)
         DeleteBox();
     }
 
   Print("[",
         MQLInfoString(MQL_PROGRAM_NAME),
         "][INDICATOR][OnDeinit] ORB indicator stopped",
         " | Symbol=",
         _Symbol,
         " | Reason=",
         reason);
  }

//+------------------------------------------------------------------+
//| OnCalculate                                                      |
//|                                                                  |
//| Main workflow:                                                   |
//|                                                                  |
//| 1. Wait until the ORB range is completed.                        |
//| 2. Calculate the ORB high and low.                               |
//| 3. Draw the box only when graphics are enabled.                  |
//| 4. Detect a breakout using a closed candle.                      |
//| 5. Calculate Stop Loss and Take Profit.                          |
//| 6. Send the signal to RiskGuard.                                 |
//| 7. Save the daily duplicate-protection status.                   |
//+------------------------------------------------------------------+
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[])
  {
   if(ShowGraphics)
      DeleteOldBoxes();
 
   datetime now = TimeCurrent();
 
   datetime endTime =
      TodayTime(RangeEndHour, RangeEndMinute);
 
   //--- Wait until the ORB range is completed.
   if(now < endTime)
      return(rates_total);
 
   double rangeHigh = 0.0;
   double rangeLow  = 0.0;
 
   if(!GetOrbRange(rangeHigh, rangeLow))
      return(rates_total);
 
   bool signalAlreadySent = AlreadySentToday();
 
   //--- Draw the box only in live use or visual backtests.
   if(ShowGraphics && !signalAlreadySent)
      DrawBox(rangeHigh, rangeLow);
 
   //--- Manage the box after a signal has already been sent.
   if(signalAlreadySent)
     {
      bool hasStrategyActivity =
         HasRiskGuardStrategyPositionOrOrder();
 
      if(hasStrategyActivity)
         ActivityDetectedAfterSignal = true;
 
      if(ShowGraphics &&
         ActivityDetectedAfterSignal &&
         !hasStrategyActivity)
        {
         DeleteBox();
        }
 
      return(rates_total);
     }
 
   //--- Prevent retroactive signals.
   //--- If the indicator is loaded today after the range has ended,
   //--- no breakout that occurred before loading may be recovered.
   if(DayKey(IndicatorLoadTime) == DayKey(now) &&
      IndicatorLoadTime > endTime)
     {
      return(rates_total);
     }
 
   MqlRates breakoutRates[];
   ArraySetAsSeries(breakoutRates, true);
 
   int copiedBars =
      CopyRates(_Symbol,
                BreakoutTimeframe,
                0,
                3,
                breakoutRates);
 
   if(copiedBars < 3)
      return(rates_total);
 
   //--- Use only the last closed candle.
   datetime closedBarTime = breakoutRates[1].time;
 
   //--- Process each closed candle only once.
   if(closedBarTime == LastBreakoutBarTime)
      return(rates_total);
 
   LastBreakoutBarTime = closedBarTime;
 
   //--- Ignore candles closed before completion of the ORB range.
   if(closedBarTime < endTime)
      return(rates_total);
 
   double barClose = breakoutRates[1].close;
   double boxSize  = rangeHigh - rangeLow;
 
   if(boxSize <= 0.0)
      return(rates_total);
 
   double normalizedEntryPercent = EntryPercent;
 
   if(normalizedEntryPercent < 0.0)
      normalizedEntryPercent = 0.0;
 
   if(normalizedEntryPercent > 99.0)
      normalizedEntryPercent = 99.0;
 
   double ask =
      SymbolInfoDouble(_Symbol, SYMBOL_ASK);
 
   double bid =
      SymbolInfoDouble(_Symbol, SYMBOL_BID);
 
   if(ask <= 0.0 || bid <= 0.0)
      return(rates_total);

   //+---------------------------------------------------------------+
   //| BUY breakout                                                  |
   //+---------------------------------------------------------------+
   if(barClose > rangeHigh)
     {
      double stopPrice    = 0.0;
      double takePrice    = 0.0;
      double pendingPrice = 0.0;
 
      //--- Market BUY signal.
      if(normalizedEntryPercent <= 0.0)
        {
         stopPrice = rangeLow;
 
         double riskDistance = ask - stopPrice;
 
         if(riskDistance <= 0.0)
            return(rates_total);
 
         takePrice =
            ask + riskDistance * RiskReward;
 
         SendRiskGuardConfig2Signal(stopPrice,
                                    takePrice);
        }
 
      //--- Pending BUY signal inside the ORB box.
      else
        {
         pendingPrice =
            rangeHigh -
            boxSize *
            normalizedEntryPercent /
            100.0;
 
         stopPrice = rangeLow;
 
         double riskDistance =
            pendingPrice - stopPrice;
 
         if(riskDistance <= 0.0)
            return(rates_total);
 
         takePrice =
            pendingPrice +
            riskDistance *
            RiskReward;
 
         SendRiskGuardConfig2Signal(stopPrice,
                                    takePrice,
                                    pendingPrice);
        }
 
      //--- Save only after the RiskGuard signal variables exist.
      SaveSignalToday();
 
      return(rates_total);
     }

   //+---------------------------------------------------------------+
   //| SELL breakout                                                 |
   //+---------------------------------------------------------------+
   if(barClose < rangeLow)
     {
      double stopPrice    = 0.0;
      double takePrice    = 0.0;
      double pendingPrice = 0.0;
 
      //--- Market SELL signal.
      if(normalizedEntryPercent <= 0.0)
        {
         stopPrice = rangeHigh;
 
         double riskDistance =
            stopPrice - bid;
 
         if(riskDistance <= 0.0)
            return(rates_total);
 
         takePrice =
            bid -
            riskDistance *
            RiskReward;
 
         SendRiskGuardConfig2Signal(stopPrice,
                                    takePrice);
        }
 
      //--- Pending SELL signal inside the ORB box.
      else
        {
         pendingPrice =
            rangeLow +
            boxSize *
            normalizedEntryPercent /
            100.0;
 
         stopPrice = rangeHigh;
 
         double riskDistance =
            stopPrice - pendingPrice;
 
         if(riskDistance <= 0.0)
            return(rates_total);
 
         takePrice =
            pendingPrice -
            riskDistance *
            RiskReward;
 
         SendRiskGuardConfig2Signal(stopPrice,
                                    takePrice,
                                    pendingPrice);
        }
 
      //--- Save only after the RiskGuard signal variables exist.
      SaveSignalToday();
 
      return(rates_total);
     }
 
   return(rates_total);
  }
//+------------------------------------------------------------------+