Connect Disconnect Sound Alert Strategy постоянно отслеживает состояние подключения коннектора стратегии и фиксирует каждое переключение между онлайн и офлайн режимами. В оригинальном советнике MQL5 воспроизводились звуковые файлы при подключении или отключении терминала MetaTrader. В C# версии сохранена основная логика — обнаружение изменения соединения — и добавлены расширенные журналы StockSharp, которые позволяют контролировать длительность каждого состояния. Стратегия подходит в качестве легкого «сторожа», информирующего оператора о проблемах связи без выставления заявок.
Основные возможности
Периодический опрос состояния коннектора с настраиваемым интервалом.
Фиксация событий подключения и отключения с подробными сообщениями в логах.
Опциональное отображение длительности пребывания в каждом состоянии.
Пропуск звукового уведомления при первом запуске для соответствия поведению MQL-советника.
Параметры
Название
Значение по умолчанию
Описание
CheckIntervalSeconds
1
Интервал между проверками состояния соединения в секундах. Значение должно быть больше нуля.
LogDurations
true
При включении в лог записывается, сколько времени соединение оставалось в предыдущем состоянии.
Параметры созданы через StrategyParam<T> и могут настраиваться из пользовательского интерфейса или в оптимизаторе.
Принцип работы
При старте стратегия сохраняет текущее состояние коннектора и при необходимости выводит начальное сообщение.
System.Threading.Timer с заданной периодичностью вызывает обработчик, сравнивающий новое состояние с предыдущим.
При изменении состояния стратегия пишет событие в журнал. Первое уведомление помечается как «initial» и не инициирует звуковой сигнал, повторяя поведение MQL-версии.
По желанию пользователя выводится длительность предыдущего состояния, что помогает оценить стабильность соединения.
Таймер автоматически останавливается при остановке или сбросе стратегии, ресурсы освобождаются корректно.
Рекомендации по использованию
Запускайте стратегию вместе с любым терминалом StockSharp, в котором доступен коннектор. Торговых операций она не выполняет.
Используйте значение интервала по умолчанию для оперативного мониторинга. Увеличивайте его только при необходимости уменьшить нагрузку.
Уведомления выводятся через LogInfo, поэтому настройте подходящий слушатель логов или панель мониторинга.
Для реального звукового оповещения подключите сервис уведомлений на стороне хоста и воспроизводите звуки при получении сообщений.
Меры предосторожности
Проверяется корректность интервала опроса, при неверном значении выбрасывается исключение.
Метки времени берутся из CurrentTime, что обеспечивает корректные значения как в онлайне, так и при прогоне истории.
Таймер уничтожается при остановке и сбросе стратегии, исключая «висящие» фоновые задачи.
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()