Long EMA con Salida Avanzada
Long EMA con Salida Avanzada es una estrategia solo de largos que entra cuando una media móvil corta cruza hacia arriba de una media, y el precio está por encima de una media móvil larga. Las salidas pueden activarse por cruce bajista del MACD, cierre del precio por debajo de la media móvil seleccionada, cruce bajista de la MA, stop trailing o un filtro de volatilidad basado en ATR.
Detalles
- Datos: Velas de precio.
- Criterios de entrada:
- Largo: La MA corta cruza hacia arriba la MA media y el precio está por encima de la MA larga.
- Criterios de salida: Cruce bajista del MACD, precio por debajo de la MA seleccionada, cruce bajista de la MA corta por debajo de la MA media, stop trailing opcional.
- Stops: Stop trailing opcional.
- Valores predeterminados:
MaType = EMA
EntryConditionType = Crossover
LongTermPeriod = 200
ShortTermPeriod = 5
MidTermPeriod = 10
EnableMacdExit = true
MacdCandleType = TimeSpan.FromDays(7).TimeFrame()
MacdFastLength = 12
MacdSlowLength = 26
MacdSignalLength = 9
UseTrailingStop = false
TrailingStopPercent = 15
UseMaCloseExit = false
MaCloseExitPeriod = 50
UseMaCrossExit = true
UseVolatilityFilter = false
AtrPeriod = 14
AtrMultiplier = 1.5
CandleType = TimeSpan.FromMinutes(5).TimeFrame()
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Solo largos
- Indicadores: MA, MACD, ATR
- Complejidad: Medio
- Nivel de riesgo: Medio
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EMA crossover strategy with trailing exit.
/// </summary>
public class LongEmaAdvancedExitStrategy : Strategy
{
private readonly StrategyParam<int> _shortPeriod;
private readonly StrategyParam<int> _midPeriod;
private readonly StrategyParam<int> _longPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevShort;
private decimal _prevMid;
private int _barsSinceSignal;
public int ShortPeriod { get => _shortPeriod.Value; set => _shortPeriod.Value = value; }
public int MidPeriod { get => _midPeriod.Value; set => _midPeriod.Value = value; }
public int LongPeriod { get => _longPeriod.Value; set => _longPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public LongEmaAdvancedExitStrategy()
{
_shortPeriod = Param(nameof(ShortPeriod), 10)
.SetDisplay("Short EMA", "Short EMA period", "Indicators");
_midPeriod = Param(nameof(MidPeriod), 20)
.SetDisplay("Mid EMA", "Mid EMA period", "Indicators");
_longPeriod = Param(nameof(LongPeriod), 40)
.SetDisplay("Long EMA", "Long EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_cooldownBars = Param(nameof(CooldownBars), 38)
.SetDisplay("Cooldown Bars", "Min bars between signals", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevShort = 0;
_prevMid = 0;
_barsSinceSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevShort = 0;
_prevMid = 0;
_barsSinceSignal = 0;
var emaShort = new ExponentialMovingAverage { Length = ShortPeriod };
var emaMid = new ExponentialMovingAverage { Length = MidPeriod };
var emaLong = new ExponentialMovingAverage { Length = LongPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(emaShort, emaMid, emaLong, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaShort);
DrawIndicator(area, emaMid);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal shortVal, decimal midVal, decimal longVal)
{
if (candle.State != CandleStates.Finished)
return;
_barsSinceSignal++;
if (_prevShort == 0 || _prevMid == 0)
{
_prevShort = shortVal;
_prevMid = midVal;
return;
}
if (_barsSinceSignal < CooldownBars)
{
_prevShort = shortVal;
_prevMid = midVal;
return;
}
// Entry: short crosses above mid + price above long EMA -> buy
var crossUp = _prevShort <= _prevMid && shortVal > midVal;
if (crossUp && candle.ClosePrice > longVal && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_barsSinceSignal = 0;
}
// Entry: short crosses below mid + price below long EMA -> sell
var crossDown = _prevShort >= _prevMid && shortVal < midVal;
if (crossDown && candle.ClosePrice < longVal && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_barsSinceSignal = 0;
}
_prevShort = shortVal;
_prevMid = midVal;
}
}
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 long_ema_advanced_exit_strategy(Strategy):
"""Triple EMA crossover with long EMA trend filter."""
def __init__(self):
super(long_ema_advanced_exit_strategy, self).__init__()
self._short_period = self.Param("ShortPeriod", 10).SetDisplay("Short EMA", "Short EMA period", "Indicators")
self._mid_period = self.Param("MidPeriod", 20).SetDisplay("Mid EMA", "Mid EMA period", "Indicators")
self._long_period = self.Param("LongPeriod", 40).SetDisplay("Long EMA", "Long EMA period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 38).SetDisplay("Cooldown Bars", "Min bars between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candles", "General")
self._prev_short = 0.0
self._prev_mid = 0.0
self._bars_since_signal = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(long_ema_advanced_exit_strategy, self).OnReseted()
self._prev_short = 0.0
self._prev_mid = 0.0
self._bars_since_signal = 0
def OnStarted2(self, time):
super(long_ema_advanced_exit_strategy, self).OnStarted2(time)
ema_short = ExponentialMovingAverage()
ema_short.Length = self._short_period.Value
ema_mid = ExponentialMovingAverage()
ema_mid.Length = self._mid_period.Value
ema_long = ExponentialMovingAverage()
ema_long.Length = self._long_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema_short, ema_mid, ema_long, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_short)
self.DrawIndicator(area, ema_mid)
self.DrawOwnTrades(area)
def _process_candle(self, candle, short_val, mid_val, long_val):
if candle.State != CandleStates.Finished:
return
self._bars_since_signal += 1
sv = float(short_val)
mv = float(mid_val)
lv = float(long_val)
if self._prev_short == 0 or self._prev_mid == 0:
self._prev_short = sv
self._prev_mid = mv
return
if self._bars_since_signal < self._cooldown_bars.Value:
self._prev_short = sv
self._prev_mid = mv
return
close = float(candle.ClosePrice)
cross_up = self._prev_short <= self._prev_mid and sv > mv
if cross_up and close > lv and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._bars_since_signal = 0
cross_down = self._prev_short >= self._prev_mid and sv < mv
if cross_down and close < lv and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._bars_since_signal = 0
self._prev_short = sv
self._prev_mid = mv
def CreateClone(self):
return long_ema_advanced_exit_strategy()