Esta estrategia opera rompimientos cuando el precio de cierre cruza una Media Móvil Suavizada (SMMA) de largo plazo.
Se abre una posición larga cuando el precio sube por encima de la SMMA y una posición corta cuando cae por debajo.
Las posiciones se cierran cuando el precio se mueve en contra de la operación y cruza una Media Móvil Exponencial (EMA).
Detalles
Criterios de entrada:
Largo: El precio de cierre cruza por encima de SMMA(200).
Corto: El precio de cierre cruza por debajo de SMMA(200).
Criterios de salida:
Largo: El precio de cierre cae por debajo de EMA(5).
Corto: El precio de cierre sube por encima de EMA(5).
Largo/Corto: Ambos.
Stops: Sin stop-loss fijo, la salida está determinada por la señal EMA.
Valores predeterminados:
SMMA period = 200
EMA period = 5
Candle type = velas de 5 minutos
Filtros:
Categoría: Seguimiento de tendencia
Dirección: Ambos
Indicadores: Medias Móviles
Stops: No
Complejidad: Simple
Marco temporal: Corto plazo
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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>
/// Strategy based on smoothed moving average breakout with EMA exit.
/// </summary>
public class MmaBreakoutVolumeIStrategy : Strategy
{
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _exitPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevPrice;
private decimal _prevSlow;
private bool _hasPrev;
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int ExitPeriod { get => _exitPeriod.Value; set => _exitPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MmaBreakoutVolumeIStrategy()
{
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetDisplay("Slow EMA Period", "Period for long moving average", "Indicators");
_exitPeriod = Param(nameof(ExitPeriod), 10)
.SetDisplay("Exit EMA Period", "Period for exit EMA", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevPrice = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
var exitEma = new ExponentialMovingAverage { Length = ExitPeriod };
SubscribeCandles(CandleType)
.Bind(slowEma, exitEma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal slowValue, decimal exitValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevPrice = candle.ClosePrice;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
var isCrossAbove = _prevPrice <= _prevSlow && candle.ClosePrice > slowValue;
var isCrossBelow = _prevPrice >= _prevSlow && candle.ClosePrice < slowValue;
if (isCrossAbove && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (isCrossBelow && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
else if (Position > 0 && candle.ClosePrice < exitValue)
SellMarket();
else if (Position < 0 && candle.ClosePrice > exitValue)
BuyMarket();
_prevPrice = candle.ClosePrice;
_prevSlow = slowValue;
}
}
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 mma_breakout_volume_i_strategy(Strategy):
def __init__(self):
super(mma_breakout_volume_i_strategy, self).__init__()
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow EMA Period", "Period for long moving average", "Indicators")
self._exit_period = self.Param("ExitPeriod", 10) \
.SetDisplay("Exit EMA Period", "Period for exit EMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_price = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def slow_period(self):
return self._slow_period.Value
@property
def exit_period(self):
return self._exit_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(mma_breakout_volume_i_strategy, self).OnReseted()
self._prev_price = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(mma_breakout_volume_i_strategy, self).OnStarted2(time)
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.slow_period
exit_ema = ExponentialMovingAverage()
exit_ema.Length = self.exit_period
self.SubscribeCandles(self.candle_type).Bind(slow_ema, exit_ema, self.process_candle).Start()
def process_candle(self, candle, slow_value, exit_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
sv = float(slow_value)
exv = float(exit_value)
if not self._has_prev:
self._prev_price = close
self._prev_slow = sv
self._has_prev = True
return
is_cross_above = self._prev_price <= self._prev_slow and close > sv
is_cross_below = self._prev_price >= self._prev_slow and close < sv
if is_cross_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif is_cross_below and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
elif self.Position > 0 and close < exv:
self.SellMarket()
elif self.Position < 0 and close > exv:
self.BuyMarket()
self._prev_price = close
self._prev_slow = sv
def CreateClone(self):
return mma_breakout_volume_i_strategy()