Estrategia ColorXvaMA Digit
Esta estrategia opera basándose en el cambio de pendiente de una media móvil con doble suavizado. Una Media Móvil Exponencial se suaviza nuevamente con una Media Móvil Jurik. Se abre una posición larga cuando la JMA rápida cruza por encima de la EMA lenta, y una posición corta cuando cruza por debajo.
Detalles
- Criterios de entrada:
- Largo: La JMA rápida cruza por encima de la EMA lenta.
- Corto: La JMA rápida cruza por debajo de la EMA lenta.
- Largo/Corto: Ambos lados.
- Criterios de salida: Señal opuesta.
- Stops: Ninguno.
- Valores predeterminados:
SlowLength= 15FastLength= 5
- Filtros:
- Categoría: Seguimiento de tendencia
- Dirección: Ambos
- Indicadores: EMA, JMA
- Stops: Ninguno
- Complejidad: Bajo
- Marco temporal: 8h
- 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 the slope change of a double-smoothed moving average.
/// Uses an EMA and JMA combination to detect trend reversals.
/// </summary>
public class ColorXvaMADigitStrategy : Strategy
{
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _slowMa;
private JurikMovingAverage _fastMa;
private int _previousDirection;
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public ColorXvaMADigitStrategy()
{
_slowLength = Param(nameof(SlowLength), 15)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "EMA period", "Indicators");
_fastLength = Param(nameof(FastLength), 5)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "JMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousDirection = 0;
_slowMa = null;
_fastMa = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previousDirection = 0;
_slowMa = new ExponentialMovingAverage { Length = SlowLength };
_fastMa = new JurikMovingAverage { Length = FastLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_slowMa, _fastMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _slowMa);
DrawIndicator(area, _fastMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal slowValue, decimal fastValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_previousDirection = fastValue > slowValue ? 1 : -1;
return;
}
var direction = fastValue > slowValue ? 1 : -1;
if (direction != _previousDirection && _previousDirection != 0)
{
if (direction > 0 && Position <= 0)
BuyMarket();
else if (direction < 0 && Position >= 0)
SellMarket();
}
_previousDirection = direction;
}
}
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, JurikMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_xva_ma_digit_strategy(Strategy):
def __init__(self):
super(color_xva_ma_digit_strategy, self).__init__()
self._slow_length = self.Param("SlowLength", 15) \
.SetDisplay("Slow Length", "EMA period", "Indicators")
self._fast_length = self.Param("FastLength", 5) \
.SetDisplay("Fast Length", "JMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._previous_direction = 0
@property
def slow_length(self):
return self._slow_length.Value
@property
def fast_length(self):
return self._fast_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_xva_ma_digit_strategy, self).OnReseted()
self._previous_direction = 0
def OnStarted2(self, time):
super(color_xva_ma_digit_strategy, self).OnStarted2(time)
self._previous_direction = 0
slow_ma = ExponentialMovingAverage()
slow_ma.Length = int(self.slow_length)
fast_ma = JurikMovingAverage()
fast_ma.Length = int(self.fast_length)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(slow_ma, fast_ma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, slow_ma)
self.DrawIndicator(area, fast_ma)
self.DrawOwnTrades(area)
def process_candle(self, candle, slow_value, fast_value):
if candle.State != CandleStates.Finished:
return
slow_value = float(slow_value)
fast_value = float(fast_value)
direction = 1 if fast_value > slow_value else -1
if direction != self._previous_direction and self._previous_direction != 0:
if direction > 0 and self.Position <= 0:
self.BuyMarket()
elif direction < 0 and self.Position >= 0:
self.SellMarket()
self._previous_direction = direction
def CreateClone(self):
return color_xva_ma_digit_strategy()