Estrategia diseñada para publicaciones de noticias de alta volatilidad. Coloca órdenes stop simétricas en ambos lados del precio actual para capturar rupturas. Una vez que se activa una orden, la orden pendiente opuesta se cancela y un trailing stop protege la posición abierta.
Detalles
Criterios de entrada: esperar spread por debajo de SpreadOperation, luego colocar compra stop en Ask + PipsAway puntos y venta stop en Bid - PipsAway puntos
Largo/Corto: Ambos
Criterios de salida: stop loss o take profit de protección, o trailing stop cuando el precio retrocede TrailingStop puntos
Stops: Stop loss y take profit iniciales mediante StartProtection; trailing stop personalizado en código
Valores predeterminados:
StopLoss = 100
TakeProfit = 300
TrailingStop = 50
PipsAway = 50
BalanceUsed = 0.01
SpreadOperation = 25
Leverage = 400
Filtros:
Categoría: Ruptura
Dirección: Ambos
Indicadores: Ninguno
Stops: Sí
Complejidad: Básico
Marco temporal: Level1 / Tick
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Alto
Cómo funciona
Suscribirse a cotizaciones Level1 para acceder a los precios de compra y venta actuales.
Cuando el spread es suficientemente pequeño, calcular el volumen usando el valor de la cartera, el apalancamiento y BalanceUsed.
Colocar órdenes pendientes de compra y venta stop con los desplazamientos definidos por PipsAway.
Cuando se abre una posición, cancelar la orden pendiente opuesta.
Adjuntar órdenes de stop loss y take profit basadas en StopLoss y TakeProfit.
Rastrear el precio más alto/más bajo desde la entrada y salir si el precio retrocede más de TrailingStop puntos.
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;
}
}