Открыть на GitHub

Стратегия SpaceX Delete StopLoss TakeProfit Button

Обзор

Стратегия повторяет работу кнопки «DELETE SL_TP» из оригинального советника MetaTrader SpaceX_Delete_StopLoss_TakeProfit_button.mq5. Она служит утилитой, которая сканирует текущий портфель и снимает все защитные приказы стоп-лосс и тейк-профит, связанные с открытыми позициями. Конверсия построена на высокоуровневом API StockSharp и позволяет мгновенно очистить защитные приказы без ручного поиска заявок.

Стратегия не открывает и не закрывает позиции. Единственная задача — удалить защитные приказы по уже существующим сделкам. Инструмент полезен для трейдеров, которые управляют позициями вручную или другими роботами, но хотят иметь «паническую кнопку» для быстрого удаления стопов и тейков.

Поведение оригинального советника

В MetaTrader советник создаёт диалоговое окно с единственной кнопкой DELETE SL_TP. При нажатии кнопки он перебирает все позиции и вызывает PositionModify, устанавливая нулевые значения стоп-лосса и тейк-профита. Объём позиции при этом не изменяется.

Основные особенности оригинала:

  • Не создаются новые сделки.
  • Обрабатываются все символы терминала.
  • Удаляются только стопы и тейки, комментарии и magic number остаются без изменений.
  • Действие выполняется исключительно нажатием кнопки на графике.

Реализация в StockSharp

В версии для StockSharp функция удаления защитных приказов сохраняется, но управление реализовано через параметры стратегии. Пользователь может переключать параметры в интерфейсе StockSharp или из собственного кода. Стратегия совместима с любыми адаптерами, которые предоставляют информацию о защитных приказах.

Поддерживаются два режима запуска:

  1. Автозапуск при старте — по желанию. При включении стратегия сразу удаляет защитные приказы после старта.
  2. Ручная команда — булевый параметр, который имитирует кнопку из MetaTrader. При установке параметра в true очистка выполняется на следующем тике таймера, а затем флаг автоматически сбрасывается.

Удаление осуществляется через CancelOrder для всех активных приказов, распознанных как защитные. Объём позиций остаётся неизменным.

Параметры

Название Описание Значение по умолчанию
Run On Start (ApplyOnStart) При true удаляет защитные приказы сразу после запуска стратегии. true
All Securities (AffectAllSecurities) Обрабатывать все инструменты портфеля. При false работает только с прикреплённым инструментом. true
Delete Request (DeleteRequest) Ручной триггер, имитирующий кнопку. Установите true, чтобы выполнить удаление один раз; затем флаг сбрасывается. false
Polling Interval (s) (PollingIntervalSeconds) Интервал таймера в секундах, который проверяет ручной флаг. 1

Алгоритм работы

  1. При старте стратегия проверяет корректность интервала и запускает таймер.
  2. Если включён параметр Run On Start, сразу выполняется очистка.
  3. Каждый тик таймера проверяет параметр Delete Request. Если он true, стратегия собирает инструменты с открытыми позициями в выбранной области и отменяет все защитные приказы по ним.
  4. После выполнения флаг возвращается в false, чтобы действие не повторялось без запроса.

Определение защитных приказов

Приказ считается защитным, если выполнено одно из условий:

  • Тип приказа — Stop, TakeProfit или Conditional.
  • Указана стоп-цена, тейк-профит или непустое условие приказа.

Такое правило покрывает большинство адаптеров. Если подключение использует особые типы приказов, логику можно расширить.

Рекомендации по использованию

  • Подключайте стратегию к тому же портфелю и коннектору, где находятся управляемые позиции.
  • Переключайте параметр Delete Request в интерфейсе Hydra или Terminal, чтобы инициировать удаление.
  • Используйте стратегию совместно с другими роботами: например, сначала снимайте старые стопы, затем устанавливайте новые.
  • Для максимальной отзывчивости оставляйте интервал опроса равным одной секунде. При необходимости уменьшить нагрузку увеличьте интервал.

Отличия от MetaTrader-версии

  • В оригинале действие запускается кнопкой в окне графика; в StockSharp роль кнопки выполняет параметр и таймер.
  • В StockSharp стопы и тейки представлены отдельными приказами, поэтому они отменяются, а не модифицируются внутри позиции.
  • Добавлен параметр, ограничивающий область действия стратегией — это удобное расширение по сравнению с исходным кодом.

Ограничения

  • Требуется, чтобы адаптер предоставлял защитные приказы как активные заявки. Если брокер хранит стопы на сервере без отдельной заявки, отменить их не получится.
  • Стратегия не создаёт графический интерфейс — управление только через параметры.
  • Утилита не устанавливает новые стопы или тейки, а лишь удаляет существующие.

Тестирование

Специальные автотесты не предусмотрены: логика проста и предназначена для ручной проверки. Для теста откройте несколько позиций, подключите стратегию и убедитесь, что после срабатывания все защитные заявки отменены.

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// SpaceX Delete SL/TP strategy: Standard Deviation breakout.
/// Buys when price breaks above upper StdDev band, sells on break below lower.
/// </summary>
public class SpaceXDeleteStopLossTakeProfitButtonStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<int> _stdDevPeriod;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public int StdDevPeriod { get => _stdDevPeriod.Value; set => _stdDevPeriod.Value = value; }

	public SpaceXDeleteStopLossTakeProfitButtonStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("SMA Period", "SMA period for baseline", "Indicators");
		_stdDevPeriod = Param(nameof(StdDevPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("StdDev Period", "Standard Deviation period", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var sma = new SimpleMovingAverage { Length = SmaPeriod };
		var stdDev = new StandardDeviation { Length = StdDevPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(sma, stdDev, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal smaValue, decimal stdDevValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var upper = smaValue + 2 * stdDevValue;
		var lower = smaValue - 2 * stdDevValue;

		if (candle.ClosePrice > upper && Position <= 0)
			BuyMarket();
		else if (candle.ClosePrice < lower && Position >= 0)
			SellMarket();
	}
}