Estrategia de Cruce Triple EMA
Estrategia basada en tres medias móviles simples. Se abre una operación larga cuando la SMA corta cruza por encima de la SMA media mientras las tres están alineadas al alza. Se abre una operación corta en el cruce opuesto y alineación. El precio al cruzar de nuevo la SMA corta cierra la posición.
Detalles
- Criterios de entrada: Cruces de SMA1 y SMA2 con filtro de tendencia.
- Largo/Corto: Ambos direcciones.
- Criterios de salida: Precio cruzando SMA1 o stops protectores.
- Stops: Sí.
- Valores predeterminados:
Sma1Period= 9Sma2Period= 21Sma3Period= 55StopLossTicks= 200TakeProfitTicks= 200CandleType= TimeSpan.FromMinutes(5)
- Filtros:
- Categoría: Tendencia
- Dirección: Ambos
- Indicadores: SMA
- Stops: Fijo
- Complejidad: Básico
- Marco temporal: Intradía (5m)
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Triple SMA crossover with stop loss and take profit.
/// </summary>
public class TripleEmaCrossoverStrategy : Strategy
{
private readonly StrategyParam<int> _sma1Period;
private readonly StrategyParam<int> _sma2Period;
private readonly StrategyParam<int> _sma3Period;
private readonly StrategyParam<int> _stopLossTicks;
private readonly StrategyParam<int> _takeProfitTicks;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevSma1;
private decimal _prevSma2;
private decimal _prevSma3;
private int _cooldown;
public TripleEmaCrossoverStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_sma1Period = Param(nameof(Sma1Period), 5)
.SetDisplay("SMA1 Period", "Period for short SMA", "Indicators");
_sma2Period = Param(nameof(Sma2Period), 13)
.SetDisplay("SMA2 Period", "Period for middle SMA", "Indicators");
_sma3Period = Param(nameof(Sma3Period), 21)
.SetDisplay("SMA3 Period", "Period for long SMA", "Indicators");
_stopLossTicks = Param(nameof(StopLossTicks), 200)
.SetDisplay("Stop Loss (ticks)", "Stop loss in ticks", "Risk");
_takeProfitTicks = Param(nameof(TakeProfitTicks), 200)
.SetDisplay("Take Profit (ticks)", "Take profit in ticks", "Risk");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int Sma1Period
{
get => _sma1Period.Value;
set => _sma1Period.Value = value;
}
public int Sma2Period
{
get => _sma2Period.Value;
set => _sma2Period.Value = value;
}
public int Sma3Period
{
get => _sma3Period.Value;
set => _sma3Period.Value = value;
}
public int StopLossTicks
{
get => _stopLossTicks.Value;
set => _stopLossTicks.Value = value;
}
public int TakeProfitTicks
{
get => _takeProfitTicks.Value;
set => _takeProfitTicks.Value = value;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSma1 = 0;
_prevSma2 = 0;
_prevSma3 = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma1 = new SimpleMovingAverage { Length = Sma1Period };
var sma2 = new SimpleMovingAverage { Length = Sma2Period };
var sma3 = new SimpleMovingAverage { Length = Sma3Period };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma1, sma2, sma3, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma1);
DrawIndicator(area, sma2);
DrawIndicator(area, sma3);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sma1, decimal sma2, decimal sma3)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevSma1 == 0 || _prevSma2 == 0 || _prevSma3 == 0)
{
_prevSma1 = sma1;
_prevSma2 = sma2;
_prevSma3 = sma3;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevSma1 = sma1;
_prevSma2 = sma2;
_prevSma3 = sma3;
return;
}
// SMA1 cross SMA2 — entry signal
var crossUp = _prevSma1 <= _prevSma2 && sma1 > sma2;
var crossDown = _prevSma1 >= _prevSma2 && sma1 < sma2;
// Exit on opposite cross
if (Position > 0 && crossDown)
{
SellMarket();
_cooldown = 20;
}
else if (Position < 0 && crossUp)
{
BuyMarket();
_cooldown = 20;
}
// Entry on SMA1/SMA2 cross
if (Position == 0)
{
if (crossUp)
{
BuyMarket();
_cooldown = 20;
}
else if (crossDown)
{
SellMarket();
_cooldown = 20;
}
}
_prevSma1 = sma1;
_prevSma2 = sma2;
_prevSma3 = sma3;
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class triple_ema_crossover_strategy(Strategy):
"""Triple SMA crossover: trade on SMA1/SMA2 cross with cooldown."""
def __init__(self):
super(triple_ema_crossover_strategy, self).__init__()
self._sma1_period = self.Param("Sma1Period", 5).SetDisplay("SMA1 Period", "Short SMA", "Indicators")
self._sma2_period = self.Param("Sma2Period", 13).SetDisplay("SMA2 Period", "Middle SMA", "Indicators")
self._sma3_period = self.Param("Sma3Period", 21).SetDisplay("SMA3 Period", "Long SMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(triple_ema_crossover_strategy, self).OnReseted()
self._prev_sma1 = 0
self._prev_sma2 = 0
self._prev_sma3 = 0
self._cooldown = 0
def OnStarted2(self, time):
super(triple_ema_crossover_strategy, self).OnStarted2(time)
self._prev_sma1 = 0
self._prev_sma2 = 0
self._prev_sma3 = 0
self._cooldown = 0
sma1 = SimpleMovingAverage()
sma1.Length = self._sma1_period.Value
sma2 = SimpleMovingAverage()
sma2.Length = self._sma2_period.Value
sma3 = SimpleMovingAverage()
sma3.Length = self._sma3_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(sma1, sma2, sma3, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, sma1)
self.DrawIndicator(area, sma2)
self.DrawIndicator(area, sma3)
self.DrawOwnTrades(area)
def OnProcess(self, candle, s1, s2, s3):
if candle.State != CandleStates.Finished:
return
s1 = float(s1)
s2 = float(s2)
s3 = float(s3)
if self._prev_sma1 == 0 or self._prev_sma2 == 0 or self._prev_sma3 == 0:
self._prev_sma1 = s1
self._prev_sma2 = s2
self._prev_sma3 = s3
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_sma1 = s1
self._prev_sma2 = s2
self._prev_sma3 = s3
return
cross_up = self._prev_sma1 <= self._prev_sma2 and s1 > s2
cross_down = self._prev_sma1 >= self._prev_sma2 and s1 < s2
# Exit on opposite cross
if self.Position > 0 and cross_down:
self.SellMarket()
self._cooldown = 20
elif self.Position < 0 and cross_up:
self.BuyMarket()
self._cooldown = 20
# Entry
if self.Position == 0:
if cross_up:
self.BuyMarket()
self._cooldown = 20
elif cross_down:
self.SellMarket()
self._cooldown = 20
self._prev_sma1 = s1
self._prev_sma2 = s2
self._prev_sma3 = s3
def CreateClone(self):
return triple_ema_crossover_strategy()