Открыть на GitHub

Стратегия News Release

Стратегия повторяет ключевые механики экспертного советника NewsReleaseEA: заранее выставляет симметричные стоп‑ордера перед выходом новости и активно сопровождает открытую позицию.

Основные идеи

  • Пять входных параметров (время новости, временные окна до/после, базовое расстояние и шаг между ордерами) определяют момент размещения и уровни заявок.
  • Непосредственно перед событием публикуется пара Buy Stop и Sell Stop. Первая пара ставится на расстоянии DistancePips от текущего ask/bid, следующие пары смещаются на StepPips.
  • Все отложенные ордера остаются активными до истечения PostNewsMinutes минут после новости. По окончании окна стратегия отменяет их и, при необходимости, закрывает открытую позицию.
  • После срабатывания любой заявки противоположные ордера снимаются автоматически, а позиция управляется правилами стоп‑лосса, тейк‑профита, перевода в безубыток и трейлинга (все значения указываются в пунктах).
  • Модуль безубытка активируется, когда цена проходит BreakEvenTriggerPips в прибыльную сторону, и закрывает сделку, если цена возвращается к уровню входа плюс BreakEvenOffsetPips (для лонга) или минус этот сдвиг (для шорта).
  • Трейлинг отслеживает максимальное/минимальное значение после входа. Как только расстояние до текущей цены превысит TrailingPips, позиция закрывается для фиксации прибыли.
  • Флаг TradeOnce соответствует параметру «TradeOneTimePerNews» из оригинального советника и запрещает повторный запуск после завершения первой сделки.

Параметры

  • NewsTime – момент выхода новости.
  • PreNewsMinutes – за сколько минут до события выставлять ордера.
  • PostNewsMinutes – сколько минут держать ордера после новости.
  • OrderPairs – количество пар Buy Stop/Sell Stop.
  • DistancePips – расстояние (в пунктах) до первой пары от текущих цен.
  • StepPips – дополнительный шаг между соседними парами.
  • OrderVolume – объем каждого отложенного ордера.
  • TradeOnce – разрешить только одну сделку на событие.
  • UseStopLoss / StopLossPips – включить стоп‑лосс и задать расстояние.
  • UseTakeProfit / TakeProfitPips – включить тейк‑профит и задать расстояние.
  • UseBreakEven, BreakEvenTriggerPips, BreakEvenOffsetPips – параметры перевода в безубыток.
  • UseTrailing / TrailingPips – включить трейлинг и определить его шаг.
  • CloseAfterEvent – закрывать позицию после завершения пост‑новостного окна.

Заметки

  • Стратегия использует только поток Level1 (SubscribeLevel1), поэтому реагирует на изменения bid/ask без ожидания закрытия свечи.
  • Пункты переводятся в абсолютные цены через PriceStep инструмента; если шаг цены неизвестен, используется значение 1 для безопасного расчёта.
  • Все защитные правила закрывают позицию рыночной заявкой (ClosePosition()), что сохраняет реактивный стиль управления, присущий оригинальному EA.
  • Python‑версия преднамеренно отсутствует.
using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// News Release strategy: Volatility breakout using Highest/Lowest channel.
/// Buys when close >= highest. Sells when close <= lowest.
/// </summary>
public class NewsReleaseStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelPeriod;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int ChannelPeriod
	{
		get => _channelPeriod.Value;
		set => _channelPeriod.Value = value;
	}

	public NewsReleaseStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_channelPeriod = Param(nameof(ChannelPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Channel Period", "Highest/Lowest lookback", "Indicators");
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var high = new Highest { Length = ChannelPeriod };
		var low = new Lowest { Length = ChannelPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(high, low, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (candle.ClosePrice >= high && Position <= 0)
		{
			BuyMarket();
		}
		else if (candle.ClosePrice <= low && Position >= 0)
		{
			SellMarket();
		}
	}
}