Estrategia de Cruce de MA CANX
Esta estrategia opera cruces de EMA del precio mediano (HL2). Se abre una posición larga cuando la EMA rápida cruza por encima de la EMA lenta. Si el modo solo largo está desactivado, se abre una posición corta cuando la EMA rápida cruza por debajo de la EMA lenta. Un filtro de año de inicio impide operar antes del año especificado.
Parámetros
- Tipo de vela
- Longitud de EMA rápida
- Multiplicador (EMA lenta = longitud rápida * multiplicador)
- Solo largo
- Año de inicio
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>
/// CanxMaCrossoverStrategy using EMA crossover for trend timing.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class CanxMaCrossoverStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFastEma;
private decimal _prevSlowEma;
public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public CanxMaCrossoverStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFastEma = 0m;
_prevSlowEma = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevFastEma == 0m || _prevSlowEma == 0m)
{
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
return;
}
if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
{
BuyMarket();
}
else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
{
SellMarket();
}
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
}
}
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 canx_ma_crossover_strategy(Strategy):
"""
CANX MA Crossover strategy using EMA crossover for trend timing.
Enters long on golden cross, short on death cross.
"""
def __init__(self):
super(canx_ma_crossover_strategy, self).__init__()
self._fast_ema_period = self.Param("FastEmaPeriod", 120) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_ema_period = self.Param("SlowEmaPeriod", 450) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_fast_ema = 0.0
self._prev_slow_ema = 0.0
@property
def fast_ema_period(self):
return self._fast_ema_period.Value
@fast_ema_period.setter
def fast_ema_period(self, value):
self._fast_ema_period.Value = value
@property
def slow_ema_period(self):
return self._slow_ema_period.Value
@slow_ema_period.setter
def slow_ema_period(self, value):
self._slow_ema_period.Value = value
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(canx_ma_crossover_strategy, self).OnReseted()
self._prev_fast_ema = 0.0
self._prev_slow_ema = 0.0
def OnStarted2(self, time):
super(canx_ma_crossover_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.fast_ema_period
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.slow_ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ema, slow_ema, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def on_process(self, candle, fast_ema_value, slow_ema_value):
if candle.State != CandleStates.Finished:
return
if self._prev_fast_ema == 0.0 or self._prev_slow_ema == 0.0:
self._prev_fast_ema = fast_ema_value
self._prev_slow_ema = slow_ema_value
return
if self._prev_fast_ema <= self._prev_slow_ema and fast_ema_value > slow_ema_value and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast_ema >= self._prev_slow_ema and fast_ema_value < slow_ema_value and self.Position >= 0:
self.SellMarket()
self._prev_fast_ema = fast_ema_value
self._prev_slow_ema = slow_ema_value
def CreateClone(self):
return canx_ma_crossover_strategy()