Ver no GitHub

Estratégia de Cesta de Trader de Divergência

Visão geral

Esta estratégia é uma versão StockSharp do consultor especialista "Divergence Trader" MetaTrader. Ele compara duas médias móveis simples calculado em fontes de preços configuráveis e mede sua diferença (divergência). Quando a distância entre o rápido e o lento médias caem dentro de um corredor neutro, o algoritmo assume que o momentum está prestes a ser retomado e abre uma posição no direção do viés predominante. A implementação usa apenas velas concluídas de um período selecionado e depende do API de alto nível com ligações de indicadores.

Parâmetros

  • Tamanho do Lote – volume de negociação enviado com cada nova posição. O valor está alinhado com o passo de volume do instrumento.
  • Período/preço SMA rápido – duração e fonte de preço para a média móvel rápida.
  • Período/preço lento SMA – duração e fonte de preço para a média móvel lenta.
  • Limiar de Compra – divergência positiva mínima necessária antes de abrir uma posição longa.
  • Stay-Out Threshold – divergência máxima permitida para novas entradas; valores fora desta faixa desabilitam a negociação.
  • Take Profit (pips) – meta de lucro expressa em pips. Desativado quando definido como zero.
  • Stop Loss (pips) – tolerância a perdas em pips. Desativado quando definido como zero.
  • Trailing Stop (pips) – distância móvel ativada após a negociação se tornar lucrativa. Desativado quando zero.
  • Break-Even Trigger / Buffer (pips) – ganho de pip necessário antes de proteger a posição no ponto de equilíbrio e buffer opcional para compensar o ponto de equilíbrio do preço de entrada.
  • Basket Lucro/Basket Loss – limites baseados no patrimônio da conta que nivelam todas as posições quando alcançados. O controle de perdas é desativado por padrão.
  • Start Hour / Stop Hour – janela de negociação no horário local. Quando ambos os valores são iguais, a estratégia funciona o dia todo.
  • Tipo de vela – período de tempo usado tanto para geração de sinal quanto para gerenciamento de risco.

Lógica de negociação

  1. Assine a série de velas configurada e calcule as médias móveis simples rápidas e lentas.
  2. Trabalhe apenas com velas prontas para evitar ruído intrabarra e ficar próximo do comportamento original EA.
  3. Acompanhe a divergência (rápida menos lenta) calculada na vela finalizada anteriormente:
    • Se a divergência for positiva e permanecer entre o Limiar de Compra e o Limiar de Permanência, envie uma ordem de compra a mercado.
    • Se a divergência for negativa e seu valor absoluto permanecer dentro do corredor, envie uma ordem de venda a mercado.
  4. As negociações são ignoradas fora do horário permitido ou quando a estratégia já possui uma posição aberta.

Gerenciamento de posição

  • Controle de ponto de equilíbrio – quando o lucro flutuante atinge o gatilho, a estratégia armazena um nível de stop de ponto de equilíbrio (opcionalmente deslocado pelo buffer). Uma vela que atinge este nível fecha a posição.
  • Trailing stop – quando o lucro excede a distância final, o nível de stop segue o preço mais favorável, embora sempre ficando atrás dele pelo número configurado de pips.
  • Take Profit/Stop Loss – saídas fixas calculadas a partir do preço de entrada em unidades pip.
  • Proteção de cesta – o patrimônio do portfólio é comparado com os limites de lucros e perdas configurados. Atingindo qualquer limite fecha a posição atual e cancela as ordens ativas, emulando a rotina "CloseEverything" da versão MQL.

Notas de uso

  • O corredor de divergência é simétrico: ampliar o Limite de permanência permite que as negociações permaneçam abertas por mais tempo, ao mesmo tempo que o estreita aumenta a frequência dos sinais.
  • As opções de origem de preço correspondem a valores StockSharp CandlePrice, possibilitando o uso de abertura, fechamento, mediana ou típica preços como em MetaTrader.
  • A estratégia traça velas, tanto médias móveis quanto ordens preenchidas, em uma área do gráfico para monitoramento e depuração.
  • Os recursos de gerenciamento de dinheiro dependem dos dados do portfólio. Ao executar em um sandbox sem estatísticas de portfólio, os controles de cesta são ignorado automaticamente.
using System;
using System.Linq;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Divergence-based strategy converted from the Divergence Trader MQL expert advisor.
/// Trades based on the divergence between fast and slow moving averages.
/// </summary>
public class DivergenceTraderBasketStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<decimal> _buyThreshold;
	private readonly StrategyParam<decimal> _stayOutThreshold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _previousDifference;
	private decimal _entryPrice;

	public DivergenceTraderBasketStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 7)
			.SetDisplay("Fast SMA Period", "Length of the fast simple moving average.", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 88)
			.SetDisplay("Slow SMA Period", "Length of the slow simple moving average.", "Indicators");

		_buyThreshold = Param(nameof(BuyThreshold), 0.0001m)
			.SetDisplay("Buy Threshold", "Minimum divergence value required before buying.", "Signals");

		_stayOutThreshold = Param(nameof(StayOutThreshold), 1000m)
			.SetDisplay("Stay-Out Threshold", "Upper divergence limit that disables new entries.", "Signals");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe used for calculations.", "General");
	}

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public decimal BuyThreshold
	{
		get => _buyThreshold.Value;
		set => _buyThreshold.Value = value;
	}

	public decimal StayOutThreshold
	{
		get => _stayOutThreshold.Value;
		set => _stayOutThreshold.Value = value;
	}

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_previousDifference = null;
		_entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_previousDifference = null;
		_entryPrice = 0;

		var fastMa = new SimpleMovingAverage { Length = FastPeriod };
		var slowMa = new SimpleMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastMa, slowMa, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastMa);
			DrawIndicator(area, slowMa);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var currentDiff = fastValue - slowValue;

		if (_previousDifference == null)
		{
			_previousDifference = currentDiff;
			return;
		}

		var prevDiff = _previousDifference.Value;
		_previousDifference = currentDiff;

		// Manage open position
		if (Position != 0)
		{
			// Exit on divergence sign change
			if (Position > 0 && currentDiff < 0)
			{
				SellMarket();
				_entryPrice = 0;
			}
			else if (Position < 0 && currentDiff > 0)
			{
				BuyMarket();
				_entryPrice = 0;
			}
			return;
		}

		// Entry logic: divergence crosses zero line
		if (currentDiff > 0 && prevDiff <= 0)
		{
			// Bullish divergence crossover
			BuyMarket();
			_entryPrice = candle.ClosePrice;
		}
		else if (currentDiff < 0 && prevDiff >= 0)
		{
			// Bearish divergence crossover
			SellMarket();
			_entryPrice = candle.ClosePrice;
		}
	}
}