The Connect Disconnect Sound Alert Strategy continuously monitors the connection status of the strategy connector and logs every transition between online and offline states. The original MQL5 expert played audio files when the MetaTrader terminal was connected or disconnected. This C# conversion keeps the core logic – detecting connection changes – and exposes hooks that allow the StockSharp runtime to record events and durations. The strategy can be used as a lightweight watchdog that informs the operator about connectivity problems without placing any orders.
Key Features
Periodically polls the connector state using a configurable interval.
Detects both connection and disconnection events and writes detailed log entries.
Records how long the terminal stayed online or offline (optional).
Skips notification sounds on the very first check to mirror the MQL behavior.
Parameters
Name
Default
Description
CheckIntervalSeconds
1
Number of seconds between connector status checks. Must be greater than zero.
LogDurations
true
When enabled, the strategy logs the time span that the connection stayed online or offline after each transition.
All parameters are exposed through StrategyParam<T> so they can be modified from the UI or during optimization.
How It Works
When the strategy starts it stores the current connector state and, optionally, logs the initial status.
A System.Threading.Timer periodically calls an internal handler that compares the current connection flag with the previous value.
If the state changed, the strategy logs the transition. The very first notification is marked as "initial" and does not represent an actual sound alert (matching the original expert advisor logic).
Optional duration logs show how long the previous state lasted, helping the operator evaluate connection stability.
The timer is automatically disposed when the strategy stops or resets.
Usage Notes
Attach the strategy to any connector-enabled StockSharp terminal. It does not interact with market data or place orders.
Keep the default polling interval for near real-time monitoring. Increase the value if you only need coarse updates.
The strategy uses the StockSharp logging subsystem (LogInfo). Configure log listeners or dashboards to see the notifications.
To add actual sound alerts, connect a notification service in your host application and play audio when log messages arrive.
Safety Considerations
The strategy validates the polling interval and throws an exception if it is not positive.
Timer callbacks use the strategy CurrentTime to ensure consistent timestamps even when historical data replay is used.
All resources are released on stop/reset to avoid background timers after the strategy is disabled.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Connection alert strategy with SMA crossover trading.
/// Buys when fast SMA crosses above slow SMA, sells on cross below.
/// </summary>
public class ConnectDisconnectSoundAlertStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public ConnectDisconnectSoundAlertStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { Length = SlowPeriod };
decimal? prevFast = null;
decimal? prevSlow = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, (candle, fastVal, slowVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (prevFast.HasValue && prevSlow.HasValue)
{
var crossUp = prevFast.Value <= prevSlow.Value && fastVal > slowVal;
var crossDown = prevFast.Value >= prevSlow.Value && fastVal < slowVal;
if (crossUp && Position <= 0)
BuyMarket();
else if (crossDown && Position >= 0)
SellMarket();
}
prevFast = fastVal;
prevSlow = slowVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class connect_disconnect_sound_alert_strategy(Strategy):
"""
SMA crossover strategy. Buys when fast SMA crosses above slow SMA.
"""
def __init__(self):
super(connect_disconnect_sound_alert_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._fast_period = self.Param("FastPeriod", 10) \
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30) \
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(connect_disconnect_sound_alert_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
def OnStarted2(self, time):
super(connect_disconnect_sound_alert_strategy, self).OnStarted2(time)
fast = SimpleMovingAverage()
fast.Length = self._fast_period.Value
slow = SimpleMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def on_process(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if self._prev_fast != 0.0 and self._prev_slow != 0.0:
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and self.Position <= 0:
self.BuyMarket()
elif cross_down and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return connect_disconnect_sound_alert_strategy()