La estrategia Accelerator Trailing TP & SL porta el Asesor Experto "Accelerator Trailing TP&SL" de MetaTrader a la API de alto nivel de StockSharp. El sistema mezcla el Oscilador Acelerador de Bill Williams con la confirmación de impulso multitemporal y un filtro de tendencia MACD mensual. Las entradas se diseñan con dimensionamiento de posición geométrico mientras que las salidas combinan distancias clásicas de stop/objetivo, seguimiento adaptativo y lógica de break-even.
Lógica de trading
Filtro de impulso – un indicador de Momentum de 14 períodos calculado en un marco temporal superior debe desviarse del nivel neutro de 100 al menos por el umbral configurado en cualquiera de las últimas tres barras completadas.
Oscilador Acelerador – las operaciones largas requieren una lectura positiva del acelerador, las operaciones cortas requieren una lectura negativa en el marco temporal de señal.
Medias móviles – una media móvil ponderada lineal rápida (LWMA) debe estar por encima de la LWMA lenta para largos y por debajo de ella para cortos, aproximando el filtro de tendencia rápido/lento original.
Tendencia MACD mensual – de forma predeterminada el filtro observa velas mensuales. Las operaciones largas demandan que la línea MACD esté por encima de la línea de señal (incluso cuando ambos valores son negativos), mientras que las operaciones cortas requieren la condición opuesta.
Entradas escalonadas – la estrategia puede piramidizar hasta el número máximo configurado de posiciones por dirección. Cada entrada adicional se multiplica por el exponente de lote, recreando el dimensionamiento de estilo martingala utilizado en el programa MQL.
Gestión del riesgo
Stop-loss / take-profit estático – las distancias en pips reflejan los ajustes originales de Stop Loss y Take Profit.
Trailing stop – cuando está habilitado, la estrategia sigue el precio más favorable por el número de pips configurado.
Movimiento de break-even – después de que una operación alcanza la distancia de disparo, el stop avanza por el desplazamiento especificado, protegiendo las ganancias acumuladas.
Salida MACD – cuando el filtro MACD se vuelve en contra de la posición activa, la estrategia puede cerrar todas las posiciones de inmediato, coincidiendo con el ayudante de salida manual en el código MQL.
Parámetros
Parámetro
Descripción
FastMaLength / SlowMaLength
Períodos de las LWMAs rápida y lenta en el marco temporal de trading.
MomentumThreshold
Desviación absoluta mínima del momentum del valor neutro de 100 en el marco temporal superior.
StopLossPips / TakeProfitPips
Distancias de stop de protección y objetivo en pips.
TrailingStopPips
Distancia utilizada por el gestor de trailing stop opcional.
BreakEvenTriggerPips / BreakEvenOffsetPips
Define cuándo y cómo se mueve el stop al break-even.
MaxTrades
Número máximo de entradas escalonadas por dirección.
BaseVolume
Volumen de la primera orden en una secuencia.
LotExponent
Multiplicador aplicado a cada entrada escalonada adicional.
EnableTrailing
Habilita o deshabilita la gestión del trailing stop.
UseBreakEven
Habilita o deshabilita el movimiento del stop de break-even.
CloseOnMacdFlip
Cierra todas las operaciones si el MACD del marco temporal superior se invierte.
CandleType
Serie de velas principal para señales (predeterminado: 15 minutos).
MomentumCandleType
Velas de marco temporal superior utilizadas por el filtro de impulso (predeterminado: 1 hora).
MacdCandleType
Serie de velas utilizada para el filtro de tendencia MACD (predeterminado: velas mensuales).
Notas
La estrategia depende del PriceStep del instrumento para convertir los ajustes de riesgo basados en pips a distancias de precio. Asegúrese de que los metadatos del valor estén poblados al ejecutar la estrategia.
Dado que StockSharp usa posiciones netas, las entradas escalonadas adicionales se abren enviando órdenes de mercado repetidamente hasta que se alcanza el máximo configurado. Las salidas cierran toda la posición neta, coincidiendo con las rutinas "cerrar todo" en el experto original.
El marco temporal MACD mensual puede ajustarse a través del parámetro MacdCandleType para adaptarse a diferentes instrumentos o backtests.
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;
public class AcceleratorTrailingTPSLStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public AcceleratorTrailingTPSLStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 accelerator_trailing_tpsl_strategy(Strategy):
def __init__(self):
super(accelerator_trailing_tpsl_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(accelerator_trailing_tpsl_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(accelerator_trailing_tpsl_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return accelerator_trailing_tpsl_strategy()