Time Bomb воспроизводит одноимённого советника MetaTrader, который открывает единственную сделку, когда цена резко проходит
заданное количество пунктов за короткий промежуток времени. Стратегия отслеживает лучшие цены спроса и предложения в реальном
времени и измеряет число пунктов между последней сохранённой ценой и текущей котировкой. Если нужная дистанция преодолена
достаточно быстро, стратегия отправляет рыночный ордер в сторону импульса и сразу рассчитывает скрытые уровни стоп-лосса и тейк-
профита в пунктах.
Реализация работает только при отсутствии открытых позиций, повторяя логику исходного конструктора блоков, который запрещал
перекрывающиеся сделки. Опорные цены перезаписываются сразу после появления сигнала либо когда истекает окно наблюдения, поэтому
каждый всплеск волатильности может породить не более одной сделки на сторону. Стопы и тейк-профиты ведутся внутренне и
контролируются кодом стратегии, поскольку StockSharp не создаёт защитные заявки автоматически при рыночном входе.
Детали
Условия входа:
Покупка: Лучшая цена ask выросла как минимум на BuyPipsInTime пунктов относительно сохранённой цены, и это произошло за
время не больше BuyTimeToWait секунд. После выполнения условий отправляется ордер объёмом BuyVolume.
Продажа: Лучшая цена bid снизилась как минимум на SellPipsInTime пунктов относительно сохранённой цены, и это произошло
за время не больше SellTimeToWait секунд. После выполнения условий отправляется ордер объёмом SellVolume.
Направление торговли: Возможны длинные и короткие позиции, но одновременно разрешена только одна позиция.
Условия выхода:
Покупка: Позиция закрывается, когда лучшая цена bid достигает рассчитанного стоп-лосса или тейк-профита.
Продажа: Позиция закрывается, когда лучшая цена ask достигает стоп-лосса или лучшая цена bid достигает тейк-профита.
Стопы: Защитные уровни скрытые и поддерживаются внутри стратегии. Расстояния задаются в пунктах и переводятся в цены через
текущий шаг цены инструмента.
Индикаторы: Только чистое ценовое движение без осцилляторов.
Стопы: Да (фиксированные дистанции в пунктах для каждой стороны).
Сложность: Низкая — один детектор импульса и простое хранение состояний.
Таймфрейм: Внутридневный, реагирует на тики не реже одного раза в секунду.
Сезонность: Нет.
Нейросети: Нет.
Дивергенции: Нет.
Уровень риска: Зависит от выбранных расстояний в пунктах; значения по умолчанию соответствуют среднему риску на мажорных FX
парах.
Параметры
Название
Описание
SellPipsInTime
Минимальное падение цены в пунктах перед открытием короткой позиции.
SellTimeToWait
Сколько секунд отводится на движение вниз.
SellVolume
Объём сделки при продаже.
SellStopLossPips
Стоп-лосс для коротких позиций в пунктах.
SellTakeProfitPips
Тейк-профит для коротких позиций в пунктах.
BuyPipsInTime
Минимальный подъём цены в пунктах перед открытием длинной позиции.
BuyTimeToWait
Сколько секунд отводится на движение вверх.
BuyVolume
Объём сделки при покупке.
BuyStopLossPips
Стоп-лосс для длинных позиций в пунктах.
BuyTakeProfitPips
Тейк-профит для длинных позиций в пунктах.
Примечания
Стратегия зависит от обновлений лучшего bid/ask, поэтому необходим поток котировок уровня Level I с актуальными значениями.
Если задать нулевые дистанции или временные окна, соответствующий сигнал будет отключён, потому что опорная цена будет
перезаписываться без открытия сделки.
Поскольку защитные уровни обслуживаются внутри стратегии, неожиданные разрывы связи могут оставить позицию без жёстких стопов.
Для живой торговли рекомендуется дополнительно включать внешние механизмы управления риском.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Time Bomb strategy: Momentum zero-line crossover.
/// Buys when momentum crosses above zero, sells when momentum crosses below zero.
/// </summary>
public class TimeBombStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _period;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal _prevMom;
private int _candlesSinceTrade;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int Period { get => _period.Value; set => _period.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public TimeBombStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_period = Param(nameof(Period), 10)
.SetGreaterThanZero()
.SetDisplay("Period", "Momentum period", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMom = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMom = 0;
_candlesSinceTrade = SignalCooldownCandles;
_hasPrev = false;
var mom = new Momentum { Length = Period };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(mom, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal momValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_hasPrev)
{
if (_prevMom <= 0 && momValue > 0 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevMom >= 0 && momValue < 0 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevMom = momValue;
_hasPrev = true;
}
}