Estrategia de Reversión a la Media Consecutive Close High1
Estrategia solo en corto que cuenta los cierres consecutivos por encima del máximo anterior y vende una vez que el conteo alcanza un umbral. La posición se cierra cuando el precio cae por debajo del mínimo anterior. El filtro EMA 200 opcional confirma la tendencia bajista.
Detalles
- Criterios de entrada: los cierres consecutivos por encima del máximo anterior alcanzan el umbral
- Largo/Corto: Corto
- Criterios de salida: cierre por debajo del mínimo anterior
- Stops: No
- Valores predeterminados:
Threshold= 3EmaPeriod= 200
- Filtros:
- Categoría: Reversión a la media
- Dirección: Corto
- Indicadores: EMA
- Stops: No
- Complejidad: Básico
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
using System;
using System.Linq;
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>
/// Short strategy based on consecutive closes above previous highs.
/// </summary>
public class ConsecutiveCloseHigh1MeanReversionStrategy : Strategy
{
private readonly StrategyParam<int> _threshold;
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private int _bullCount;
private decimal _prevHigh;
private decimal _prevLow;
private bool _isReady;
public int Threshold { get => _threshold.Value; set => _threshold.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ConsecutiveCloseHigh1MeanReversionStrategy()
{
_threshold = Param(nameof(Threshold), 3)
.SetGreaterThanZero()
.SetDisplay("Threshold", "Consecutive closes above prior high", "Parameters");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA length for trend filter", "Filters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullCount = 0;
_prevHigh = 0;
_prevLow = 0;
_isReady = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_isReady)
{
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_isReady = true;
return;
}
if (candle.ClosePrice > _prevHigh)
_bullCount++;
if (candle.ClosePrice < _prevLow)
_bullCount = 0;
// Short: consecutive closes above prior high, below EMA
if (_bullCount >= Threshold && candle.ClosePrice < emaValue && Position >= 0)
SellMarket();
else if (Position < 0 && candle.ClosePrice < _prevLow)
BuyMarket();
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class consecutive_close_high1_mean_reversion_strategy(Strategy):
def __init__(self):
super(consecutive_close_high1_mean_reversion_strategy, self).__init__()
self._threshold = self.Param("Threshold", 3) \
.SetDisplay("Threshold", "Consecutive closes above prior high", "Parameters")
self._ema_period = self.Param("EmaPeriod", 50) \
.SetDisplay("EMA Period", "EMA length for trend filter", "Filters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._bull_count = 0
self._prev_high = 0.0
self._prev_low = 0.0
self._is_ready = False
@property
def threshold(self):
return self._threshold.Value
@property
def ema_period(self):
return self._ema_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(consecutive_close_high1_mean_reversion_strategy, self).OnReseted()
self._bull_count = 0
self._prev_high = 0.0
self._prev_low = 0.0
self._is_ready = False
def OnStarted2(self, time):
super(consecutive_close_high1_mean_reversion_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def on_process(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
if not self._is_ready:
self._prev_high = candle.HighPrice
self._prev_low = candle.LowPrice
self._is_ready = True
return
if candle.ClosePrice > self._prev_high:
self._bull_count += 1
if candle.ClosePrice < self._prev_low:
self._bull_count = 0
# Short: consecutive closes above prior high, below EMA
if self._bull_count >= self.threshold and candle.ClosePrice < ema_value and self.Position >= 0:
self.SellMarket()
elif self.Position < 0 and candle.ClosePrice < self._prev_low:
self.BuyMarket()
self._prev_high = candle.HighPrice
self._prev_low = candle.LowPrice
def CreateClone(self):
return consecutive_close_high1_mean_reversion_strategy()