Esta estrategia es un porte de StockSharp del asesor experto de MetaTrader Exp_AltrTrend_Signal_v2_2. Recrea la lógica
del canal adaptativo del indicador AltrTrend Signal original y ejecuta operaciones en barras retrasadas tal como la versión MQL5.
El valor ADX contrae o amplía el canal de modo que las rupturas solo se activan cuando la fuerza de la tendencia las respalda.
Cómo funciona
Se calcula un canal dinámico en cada vela completada del marco temporal configurado. El ancho del canal se define por el
máximo y mínimo del precio dentro de un lookback que se expande o contrae según el valor ADX anterior (KPeriod / ADX).
Los límites internos (smin, smax) se acercan al centro en KPercent. El precio debe cerrar fuera de estos límites
internos para establecer un estado de tendencia direccional.
Cuando la tendencia pasa de bajista a alcista y el cierre está por encima del límite superior, se genera una señal de compra.
Un giro bajista por debajo del límite inferior emite una señal de venta. Las señales se ejecutan en la barra definida por el
retraso SignalBar, coincidiendo con el comportamiento del asesor experto original.
Los niveles opcionales de stop-loss y take-profit se asignan de puntos a pasos de precio para que las salidas de protección
imiten la colocación de órdenes original con valores fijos de SL/TP.
Detalles
Criterios de entrada:
Largo: La tendencia anterior era bajista o neutral, el precio cierra por encima del límite superior contraído y las
entradas largas están habilitadas. Las posiciones cortas pueden cerrarse automáticamente si está permitido.
Corto: La tendencia anterior era alcista o neutral, el precio cierra por debajo del límite inferior contraído y las
entradas cortas están habilitadas. Las posiciones largas pueden cerrarse automáticamente si está permitido.
Criterios de salida:
Señal de ruptura opuesta cuando las salidas están permitidas para la dirección actual.
Distancias de stop-loss o take-profit expresadas en pasos de precio.
Largo/Corto: Dirección dual con interruptores independientes de habilitación/deshabilitación para entradas y salidas.
Gestión de riesgos:
StopLossPoints y TakeProfitPoints replican el módulo MM original aplicando salidas basadas en distancia después de que
se ejecutan las órdenes de mercado.
Configuración del indicador:
KPercent controla cuánto se contraen los bordes del canal hacia el rango medio.
KStop mantiene el valor de proyección de flecha original para gráficos y logging.
KPeriod es el lookback base antes de la modulación ADX.
AdxPeriod establece la longitud del Índice Direccional Promedio que adapta el ancho del canal.
SignalBar retrasa la ejecución de órdenes por el número especificado de velas completadas.
Mercados recomendados:
Funciona mejor en instrumentos con fases de swing claras donde la fuerza de la tendencia varía con el tiempo (pares de forex
principales, oro y futuros de índices). El marco temporal predeterminado es H1 como en la plantilla MQL5.
Parámetros
Parámetro
Descripción
CandleType
Marco temporal usado para construir el canal adaptativo.
KPercent
Porcentaje que acerca los límites internos del canal hacia adentro.
KStop
Multiplicador para los precios de flecha proyectados (mantenido por compatibilidad).
KPeriod
Número base de velas examinadas antes del ajuste ADX.
AdxPeriod
Período del Índice Direccional Promedio que impulsa el ancho del canal.
SignalBar
Número de velas completadas que se esperan antes de ejecutar una señal.
AllowBuyEntries / AllowSellEntries
Habilitar o deshabilitar la apertura de posiciones en cada dirección.
AllowBuyExits / AllowSellExits
Permitir el cierre automático de posiciones en señales opuestas.
StopLossPoints
Distancia del stop-loss medida en pasos de precio (0 deshabilita).
TakeProfitPoints
Distancia del take-profit medida en pasos de precio (0 deshabilita).
Este porte mantiene los interruptores discrecionales y los parámetros de riesgo del asesor experto original, facilitando la
reproducción del mismo comportamiento dentro de StockSharp Designer, Shell o Runner.
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>
/// AltrTrend signal strategy using EMA crossover for alternating trend detection.
/// </summary>
public class AltrTrendSignalStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public AltrTrendSignalStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 7)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
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 fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
if (!prevAbove && currAbove)
{
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (prevAbove && !currAbove)
{
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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 altr_trend_signal_strategy(Strategy):
def __init__(self):
super(altr_trend_signal_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 7) \
.SetDisplay("Fast Period", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 14) \
.SetDisplay("Slow Period", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(altr_trend_signal_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(altr_trend_signal_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).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 _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif prev_above and not curr_above:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return altr_trend_signal_strategy()