Esta estrategia replica el asesor experto MetaTrader que intercambia el cruce entre un EMA(6) rápido y un }(12) lento. Se suscribe a velas horarias de forma predeterminada, calcula ambas medias móviles y espera un cruce confirmado al cierre de una vela antes de actuar.
Lógica de trading
Entrada:
Aparece una señal alcista cuando EMA(6) cruza por encima de EMA(12). La estrategia abre una posición larga si no hay ninguna posición activa.
Aparece una señal bajista cuando EMA(6) cruza por debajo de EMA(12). La estrategia abre una posición corta si no hay una posición activa.
Salir:
Cuando UseCloseSignals está habilitado (comportamiento predeterminado), la estrategia cierra la posición actual una vez que se detecta un cruce opuesto. Espera el próximo cruce antes de abrir una nueva operación, reflejando al asesor experto original.
Las protecciones opcionales de toma de ganancias y trailing stop se administran a través del asistente integrado StartProtection de StockSharp.
Tamaño de posición:
Los pedidos utilizan el parámetro OrderVolume (1 lote predeterminado). Los volúmenes se alinean con la configuración de seguridad antes de enviar pedidos.
Gestión del riesgo
Parada dinámica: Convierte la configuración original de "puntos" en incrementos de precios. Cuando es mayor que cero, el stop se desplaza automáticamente en la dirección de la operación una vez que la posición se vuelve rentable.
Take de ganancias: Expresado en incrementos de precio. Establezca en cero para desactivar.
La estrategia nunca promedia hacia abajo o pirámides. Sólo se permite una posición por símbolo.
Parámetros
Parámetro
Descripción
CandleType
Marco de tiempo utilizado para construir velas y EMA. El valor predeterminado es 1 hora.
OrderVolume
Tamaño comercial en lotes.
ShortEmaLength
Periodo para la EMA rápida (por defecto 6).
LongEmaLength
Período para el EMA lento (predeterminado 12).
UseCloseSignals
Cierre la posición actual en un cruce opuesto (predeterminado: habilitado).
TrailingStopSteps
Distancia de seguimiento en pasos de precio. Zero desactiva el seguimiento.
TakeProfitSteps
Tome la distancia de beneficio en pasos de precio. Zero lo desactiva.
Notas
Las señales se procesan únicamente en velas terminadas para evitar el ruido dentro de la barra.
Los valores EMA anteriores se restablecen cada vez que la posición vuelve a cero, lo que garantiza una detección limpia para el siguiente cruce.
Todos los comentarios del código están escritos en inglés y la sangría utiliza tabulaciones de acuerdo con las pautas del proyecto.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// EMA 6/12 crossover strategy.
/// Buys when EMA(6) crosses above EMA(12).
/// Sells when EMA(6) crosses below EMA(12).
/// </summary>
public class Ema612Strategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Ema612Strategy()
{
_fastPeriod = Param(nameof(FastPeriod), 6)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 12)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 ema612_strategy(Strategy):
def __init__(self):
super(ema612_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 6).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 12).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(ema612_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ema612_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished: return
f = float(fast); s = float(slow)
if not self._has_prev:
self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return ema612_strategy()