A estratégia Accelerator Trailing TP & SL porta o Consultor Especialista "Accelerator Trailing TP&SL" do MetaTrader para a API de alto nível do StockSharp. O sistema combina o Oscilador Acelerador de Bill Williams com confirmação de momentum multi-período e um filtro de tendência MACD mensal. As entradas são construídas com dimensionamento de posição geométrico enquanto as saídas combinam distâncias clássicas de stop/alvo, trailing adaptativo e lógica de break-even.
Lógica de trading
Filtro de momentum – um indicador de Momentum de 14 períodos calculado em um período superior deve desviar do nível neutro de 100 pelo menos pelo limiar configurado em qualquer uma das últimas três barras concluídas.
Oscilador Acelerador – negociações longas requerem uma leitura positiva do acelerador, negociações curtas requerem uma leitura negativa no período de sinal.
Médias móvies – uma média móvel ponderada linear rápida (LWMA) deve estar acima da LWMA lenta para comprados e abaixo para vendidos, aproximando o filtro de tendência rápido/lento original.
Tendência MACD mensal – por padrão, o filtro observa velas mensais. Negociações longas exigem que a linha MACD esteja acima da linha de sinal (mesmo quando ambos os valores são negativos), enquanto negociações curtas requerem a condição oposta.
Entradas escalonadas – a estratégia pode piramidizar até o número máximo configurado de posições por direção. Cada entrada adicional é multiplicada pelo expoente de lote, recriando o dimensionamento estilo martingale usado no programa MQL.
Gestão de risco
Stop-loss / take-profit estático – distâncias em pips refletem as configurações originais de Stop Loss e Take Profit.
Trailing stop – quando habilitado, a estratégia segue o preço mais favorável pelo número de pips configurado.
Movimentação de break-even – após uma negociação atingir a distância de gatilho, o stop é avançado pelo offset especificado, protegendo os lucros acumulados.
Saída MACD – quando o filtro MACD se inverte contra a posição ativa, a estratégia pode fechar todas as posições imediatamente, correspondendo ao auxiliar de saída manual no código MQL.
Parâmetros
Parâmetro
Descrição
FastMaLength / SlowMaLength
Períodos das LWMAs rápida e lenta no período de negociação.
MomentumThreshold
Desvio absoluto mínimo do momentum do valor neutro de 100 no período superior.
StopLossPips / TakeProfitPips
Distâncias de stop de proteção e alvo em pips.
TrailingStopPips
Distância usada pelo gerenciador de trailing stop opcional.
BreakEvenTriggerPips / BreakEvenOffsetPips
Define quando e como o stop é movido para break-even.
MaxTrades
Número máximo de entradas escalonadas por direção.
BaseVolume
Volume da primeira ordem em uma sequência.
LotExponent
Multiplicador aplicado a cada entrada escalonada adicional.
EnableTrailing
Habilita ou desabilita o gerenciamento do trailing stop.
UseBreakEven
Habilita ou desabilita a movimentação do stop de break-even.
CloseOnMacdFlip
Fecha todas as negociações se o MACD do período superior se inverter.
CandleType
Série de velas principal para sinais (padrão: 15 minutos).
MomentumCandleType
Velas de período superior usadas pelo filtro de momentum (padrão: 1 hora).
MacdCandleType
Série de velas para o filtro de tendência MACD (padrão: velas mensais).
Notas
A estratégia depende do PriceStep do instrumento para converter configurações de risco baseadas em pips para distâncias de preço. Certifique-se de que os metadados do ativo estejam preenchidos ao executar a estratégia.
Como o StockSharp usa posições líquidas, entradas escalonadas adicionais são abertas enviando ordens de mercado repetidamente até que o máximo configurado seja atingido. As saídas fecham toda a posição líquida, correspondendo às rotinas "fechar tudo" no especialista original.
O período MACD mensal pode ser ajustado através do parâmetro MacdCandleType para diferentes instrumentos ou 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()