Esta estrategia identifica la continuación de la tendencia prevaleciente usando un par de medias móviles exponenciales sobre los datos de precio. Se abre una posición larga cuando la EMA rápida cruza por encima de la EMA lenta, señalando una continuación alcista. Se abre una posición corta cuando la EMA rápida cruza por debajo de la EMA lenta.
Parámetros
Fast EMA Length – período para la EMA rápida (por defecto: 20).
Candle Type – marco temporal de las velas (por defecto: 4 horas).
Stop Loss – stop loss protector aplicado mediante StartProtection (por defecto: 1000).
Take Profit – objetivo de beneficio aplicado mediante StartProtection (por defecto: 2000).
Cómo funciona
Al inicio, la estrategia se suscribe a la serie de velas seleccionada y crea dos indicadores EMA.
Cada vela completada se procesa para detectar cruces entre la EMA rápida y la lenta.
Un cruce de abajo hacia arriba abre una posición larga y cierra cualquier posición corta. El cruce opuesto abre una posición corta y cierra cualquier posición larga.
La gestión del riesgo se maneja mediante los parámetros integrados de stop loss y take profit.
Este ejemplo es una conversión simplificada del experto MQL original Exp_TrendContinuation.
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>
/// Trend continuation strategy based on fast and slow EMA cross.
/// Opens long when fast EMA crosses above slow EMA, short on opposite.
/// </summary>
public class TrendContinuationStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevFast;
private decimal? _prevSlow;
public int Length
{
get => _length.Value;
set => _length.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public TrendContinuationStrategy()
{
_length = Param(nameof(Length), 20)
.SetGreaterThanZero()
.SetDisplay("Fast EMA Length", "Period for the fast EMA", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).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();
_prevFast = null;
_prevSlow = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = Length };
var slow = new ExponentialMovingAverage { Length = Length * 2 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fast);
DrawIndicator(area, slow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevFast.HasValue && _prevSlow.HasValue)
{
if (_prevFast < _prevSlow && fast >= slow && Position <= 0)
BuyMarket();
if (_prevFast > _prevSlow && fast <= slow && Position >= 0)
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 trend_continuation_strategy(Strategy):
def __init__(self):
super(trend_continuation_strategy, self).__init__()
self._length = self.Param("Length", 20) \
.SetDisplay("Fast EMA Length", "Period for the fast EMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_fast = None
self._prev_slow = None
@property
def length(self):
return self._length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(trend_continuation_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(trend_continuation_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.length
slow = ExponentialMovingAverage()
slow.Length = self.length * 2
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
fast = float(fast)
slow = float(slow)
if self._prev_fast is not None and self._prev_slow is not None:
if self._prev_fast < self._prev_slow and fast >= slow and self.Position <= 0:
self.BuyMarket()
if self._prev_fast > self._prev_slow and fast <= slow and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return trend_continuation_strategy()