Ver no GitHub

Estratégia Straddle News

Estratégia projetada para divulgações de notícias de alta volatilidade. Coloca ordens stop simétricas em ambos os lados do preço atual para capturar rompimentos. Quando uma ordem é acionada, a ordem pendente oposta é cancelada e um trailing stop protege a posição aberta.

Detalhes

  • Critérios de entrada: aguardar spread abaixo de SpreadOperation, então colocar compra stop em Ask + PipsAway pontos e venda stop em Bid - PipsAway pontos
  • Comprado/Vendido: Ambos
  • Critérios de saída: stop loss ou take profit de proteção, ou trailing stop quando o preço recua TrailingStop pontos
  • Stops: Stop loss e take profit iniciais via StartProtection; trailing stop personalizado no código
  • Valores padrão:
    • StopLoss = 100
    • TakeProfit = 300
    • TrailingStop = 50
    • PipsAway = 50
    • BalanceUsed = 0.01
    • SpreadOperation = 25
    • Leverage = 400
  • Filtros:
    • Categoria: Rompimento
    • Direção: Ambos
    • Indicadores: Nenhum
    • Stops: Sim
    • Complexidade: Básico
    • Período: Level1 / Tick
    • Sazonalidade: Não
    • Redes neurais: Não
    • Divergência: Não
    • Nível de risco: Alto

Como funciona

  1. Assinar cotações Level1 para acessar os preços de compra e venda atuais.
  2. Quando o spread for pequeno o suficiente, calcular o volume usando o valor do portfólio, alavancagem e BalanceUsed.
  3. Colocar ordens pendentes de compra e venda stop com offsets definidos por PipsAway.
  4. Quando uma posição for aberta, cancelar a ordem pendente oposta.
  5. Anexar ordens de stop loss e take profit baseadas em StopLoss e TakeProfit.
  6. Rastrear o preço mais alto/mais baixo desde a entrada e sair se o preço recuar mais de TrailingStop pontos.
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// EMA crossover strategy.
/// </summary>
public class StraddleNewsStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public StraddleNewsStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}