Ver no GitHub

Estratégia News Release

Esta estratégia reproduz o comportamento central do expert advisor original NewsReleaseEA preparando um bracket de ordens pendentes ao redor de uma notícia agendada e gerenciando ativamente a posição resultante.

Ideias-chave

  • Cinco entradas (hora da notícia, janelas antes/depois, distâncias das ordens e espaçamento) definem quando e onde as ordens stop são colocadas.
  • Um conjunto simétrico de ordens buy stop e sell stop é enviado pouco antes da hora configurada da notícia. O primeiro par é colocado a DistancePips do ask/bid atual e pares adicionais são deslocados por StepPips.
  • Ordens pendentes permanecem ativas até PostNewsMinutes minutos após o evento. Ao fim da janela, a estratégia cancela toda ordem ativa e, se solicitado, fecha qualquer posição aberta.
  • Quando uma ordem é executada, as ordens pendentes opostas são canceladas automaticamente e a posição aberta é gerenciada por regras de stop-loss, take-profit, break-even e trailing expressas em pips.
  • A proteção break-even arma depois que o preço se move BreakEvenTriggerPips a favor da posição e força uma saída se o preço retornar ao preço de entrada mais BreakEvenOffsetPips (compras) ou menos esse offset (vendas).
  • A gestão de trailing acompanha o melhor preço alcançado após a entrada. Quando a distância entre o preço atual e o extremo excede TrailingPips, a posição é fechada para proteger o lucro acumulado.
  • A flag TradeOnce espelha o comportamento "trade one time per news" do programa MQL impedindo uma segunda ativação após a primeira operação ter sido concluída.

Parâmetros

  • NewsTime: hora agendada da notícia.
  • PreNewsMinutes: quantos minutos antes da notícia as ordens pendentes são colocadas.
  • PostNewsMinutes: quantos minutos depois da notícia as ordens pendentes permanecem vivas antes do cancelamento.
  • OrderPairs: número de pares buy stop/sell stop que formam o bracket.
  • DistancePips: distância em pips do primeiro par em relação ao melhor ask/bid no momento da colocação.
  • StepPips: espaçamento adicional em pips entre pares consecutivos.
  • OrderVolume: volume enviado com cada ordem pendente.
  • TradeOnce: se habilitado, a estratégia pode operar apenas uma vez por janela de evento.
  • UseStopLoss / StopLossPips: habilita e configura a distância do stop-loss em pips.
  • UseTakeProfit / TakeProfitPips: habilita e configura a distância do take-profit em pips.
  • UseBreakEven, BreakEvenTriggerPips, BreakEvenOffsetPips: configura o módulo break-even.
  • UseTrailing / TrailingPips: habilita a lógica de saída trailing e define a distância em pips.
  • CloseAfterEvent: fecha qualquer posição aberta quando a janela pós-notícia termina.

Notas

  • A estratégia trabalha exclusivamente com dados level1 (SubscribeLevel1) para reagir aos preços bid/ask mais recentes sem aguardar candles.
  • Distâncias de preço expressas em pips são convertidas para preços absolutos usando o PriceStep do instrumento. Se PriceStep estiver indisponível, o valor 1 é usado como fallback seguro.
  • Condições de stop-loss, take-profit, break-even e trailing fecham a posição a mercado chamando ClosePosition(). Isso espelha a gestão reativa do expert original mantendo a implementação compacta.
  • Nenhuma versão Python é fornecida, conforme solicitado.
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();
		}
	}
}