The Alerting System strategy is a faithful StockSharp conversion of the MetaTrader 4 expert advisor AlertingSystem.mq4. The original script draws two horizontal lines and plays a sound whenever the market touches them. The StockSharp version accomplishes the same goal by subscribing to Level1 (best bid/ask) quotes and printing journal messages when either configurable alert level is crossed.
Core Idea
Register a Level1 data stream so the strategy receives tick-by-tick bid and ask updates, mirroring the MQL OnTick handler.
Read the user-defined UpperPrice and LowerPrice levels. A value of 0 disables the corresponding alert, just like removing the horizontal line in MetaTrader.
Compare every incoming bid with the upper level and every ask with the lower level.
Emit a single log notification when the price crosses an active level and wait until the market returns to the safe zone before arming the alert again. This prevents noisy duplicate alerts while preserving the intent of the original sound trigger.
Parameters
Name
Default
Description
UpperPrice
0
Upper horizontal alert level. Set to 0 to disable the check.
LowerPrice
0
Lower horizontal alert level. Set to 0 to disable the check.
Both parameters are exposed through the Designer UI. They can be changed before the launch or while the strategy is running; the next quote update will use the new levels.
Runtime Behavior
Data subscription: GetWorkingSecurities requests Level1 data, ensuring the strategy receives bid/ask updates even without candles or trades.
Initialization: When OnStarted fires the strategy logs the currently configured levels so the operator can verify the setup.
Alert detection: Helper methods (CheckUpperAlert and CheckLowerAlert) store internal flags to guarantee that each breach produces exactly one notification until the market moves back beyond the threshold.
No trading: The conversion does not send orders. It is purely an alerting utility, matching the behavior of the MetaTrader script that only played a sound.
Reset handling: OnReseted clears the internal flags so the next run starts with fresh alert states.
Typical Usage Steps
Select the desired instrument in StockSharp Designer and attach AlertingSystemStrategy.
Specify the upper and/or lower alert levels. Leave a value at 0 to ignore that side.
Start the strategy. The log will display entries confirming which alerts are active.
Monitor the journal window. When the bid rises above the upper level or the ask falls below the lower level, the strategy records a descriptive message.
Conversion Notes
The original MetaTrader advisor created two draggable horizontal lines. StockSharp uses numeric parameters instead, which keeps the workflow deterministic and more suitable for algorithmic execution.
MetaTrader triggered the PlaySound function on every qualifying tick. To avoid overwhelming the log, the conversion debounces alerts until the price re-enters the acceptable range.
The logic intentionally stays indicator-free: only raw quotes are required, so the strategy works on any timeframe or instrument that provides Level1 data.
Classification
Category: Utilities / Alerts
Trading Direction: None
Execution Style: Event-driven monitoring
Data Requirements: Level1 bid/ask
Complexity: Basic
Recommended Timeframe: Any (quote-driven)
Risk Management: Not applicable (no positions opened)
This documentation summarizes the StockSharp implementation and highlights the practical steps needed to reproduce the MetaTrader alerting workflow inside the platform.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Alerting System strategy: Bollinger Band breakout.
/// Buys when price crosses above upper band, sells when below lower band.
/// </summary>
public class AlertingSystemStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bbWidth;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public decimal BbWidth { get => _bbWidth.Value; set => _bbWidth.Value = value; }
public AlertingSystemStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bbWidth = Param(nameof(BbWidth), 2m)
.SetDisplay("BB Width", "Bollinger Bands width multiplier", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands
{
Length = BbPeriod,
Width = BbWidth
};
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(bb, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bbValue)
{
if (candle.State != CandleStates.Finished) return;
if (!bbValue.IsFinal) return;
var typed = (BollingerBandsValue)bbValue;
if (typed.UpBand is not decimal upper || typed.LowBand is not decimal lower) return;
var close = candle.ClosePrice;
// Mean reversion: buy at lower band, sell at upper band
if (close < lower && Position <= 0)
BuyMarket();
else if (close > upper && Position >= 0)
SellMarket();
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import BollingerBands
from StockSharp.Algo.Strategies import Strategy
class alerting_system_strategy(Strategy):
def __init__(self):
super(alerting_system_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._bb_period = self.Param("BbPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._bb_width = self.Param("BbWidth", 2.0) \
.SetDisplay("BB Width", "Bollinger Bands width multiplier", "Indicators")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(alerting_system_strategy, self).OnStarted2(time)
self._bb = BollingerBands()
self._bb.Length = self._bb_period.Value
self._bb.Width = self._bb_width.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(self._bb, self._process_candle).Start()
def _process_candle(self, candle, bb_value):
if candle.State != CandleStates.Finished:
return
if not bb_value.IsFinal:
return
upper = bb_value.UpBand
lower = bb_value.LowBand
if upper is None or lower is None:
return
close = float(candle.ClosePrice)
upper_val = float(upper)
lower_val = float(lower)
if close < lower_val and self.Position <= 0:
self.BuyMarket()
elif close > upper_val and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return alerting_system_strategy()