La estrategia Lucky Jump es un sistema de reversión a la media a corto plazo que reacciona a saltos repentinos de precio en el mejor bid y ask. Cuando el precio ask salta hacia arriba un número específico de puntos en comparación con la cotización anterior, la estrategia abre una posición corta esperando un retroceso. Por el contrario, cuando el precio bid cae la misma cantidad, entra en largo. Las posiciones se cierran en el primer tick favorable o cuando la pérdida supera un límite predefinido.
Este enfoque intenta capturar correcciones rápidas después de movimientos agresivos del mercado. Opera puramente sobre datos de cotización Level1 y no depende de velas ni indicadores.
Detalles
Criterios de entrada:
Corto: Ask(t) - Ask(t-1) >= Shift * PriceStep.
Largo: Bid(t-1) - Bid(t) >= Shift * PriceStep.
Criterios de salida:
Cerrar la posición tan pronto como sea rentable.
Cerrar si la pérdida supera Limit * PriceStep.
Stops: stop implícito basado en el parámetro Limit.
Valores predeterminados:
Shift = 30 puntos.
Limit = 180 puntos.
Volume = 1.
Filtros:
Categoría: Reversión a la media
Dirección: Ambos
Indicadores: Ninguno
Stops: Sí
Complejidad: Simple
Marco temporal: Ultra corto plazo
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Alto
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>
/// Price jump reversal strategy using EMA crossover.
/// </summary>
public class LuckyJumpStrategy : 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 LuckyJumpStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Trading");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Trading");
_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;
}
}