Trend Capture Legacy Strategy transporta o MetaTrader especialista TrendCapture.mq4 para o StockSharp API de alto nível. A versão C# mantém o conjunto de regras original com base na direção Parabolic SAR, um filtro baixo ADX e gerenciamento simples de equilíbrio financeiro.
Ideias centrais
Processe velas concluídas do período de tempo selecionado e alimente-as com Parabolic SAR (0.02/0.2) e Índice Direcional Médio (14).
Entre apenas quando ADX estiver abaixo de AdxThreshold, sinalizando um mercado calmo onde as reversões de SAR são mais confiáveis.
Lembre-se da direção e do resultado da última negociação fechada: repita o mesmo lado após um vencedor, vire para o lado oposto após um perdedor.
Aplique níveis de stop-loss e take-profit de distância fixa (configurados em faixas de preço) e mova o stop para o ponto de equilíbrio quando a negociação ganhar BreakEvenGuard pontos.
Dimensionar o volume do pedido a partir do valor do portfólio disponível e MaximumRisk; retorne à estratégia Volume quando as informações do portfólio não estiverem disponíveis.
Parâmetros
Nome
Padrão
Descrição
SarStep
0,02
Etapa inicial de aceleração Parabolic SAR.
SarMax
0,2
Aceleração máxima Parabolic SAR.
AdxPeriod
14
ADX período médio.
AdxThreshold
20
Valor máximo de ADX que ainda permite uma nova entrada.
TakeProfitPoints
180
Distância de lucro em faixas de preço.
StopLossPoints
50
Distância de stop-loss em faixas de preço.
BreakEvenGuard
5
Buffer de lucro (em pontos) necessário antes de mover o stop para entrada.
MaximumRisk
0,03
Fração da margem livre utilizada para dimensionamento da posição.
CandleType
Velas de 1 hora
Prazo para cálculos de indicadores e sinais de negociação.
Gerenciamento de pedidos
As entradas longas exigem o preço de fechamento acima de SAR com baixo ADX; as posições vendidas exigem o preço de fechamento abaixo de SAR com o mesmo filtro ADX.
Os níveis de stop-loss e take-profit são recalculados em cada entrada e avaliados em cada vela concluída.
A ativação do ponto de equilíbrio simplesmente muda o stop para o preço de entrada. Se nenhum stop-loss estiver configurado (distância zero ou negativa), a guarda é ignorada.
Indicadores
ParabolicSar para polarização direcional.
AverageDirectionalIndex para o filtro de força (apenas a linha principal ADX é usada).
Notas
A estratégia usa BindEx para evitar acesso direto ao buffer, seguindo as diretrizes do projeto.
O cálculo do volume baseado em portfólio respeita as restrições do conselho (LotStep, MinVolume, MaxVolume).
O histórico de negociação necessário para polarização de direção é coletado por meio de OnNewMyTrade, portanto, os preenchimentos parciais permanecem suportados.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class TrendCaptureLegacyStrategy : 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;
private int _cooldown;
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 TrendCaptureLegacyStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = default;
_prevSlow = default;
_hasPrev = default;
_cooldown = default;
}
/// <inheritdoc />
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 (!IsFormedAndOnlineAndAllowTrading()) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_cooldown > 0)
{
_cooldown--;
_prevFast = fast; _prevSlow = slow;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 2;
}
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 2;
}
_prevFast = fast; _prevSlow = slow;
}
}