Ver no GitHub

Estratégia Doji Rápida

Visão geral

A estratégia Rapid Doji replica a lógica do consultor especialista "Rapid Doji EA" original. Ele verifica velas concluídas de um período configurável (diariamente por padrão) e coloca ordens de entrada de parada acima e abaixo de cada vela doji. Os stops de proteção são posicionados usando um multiplicador Average True Range (ATR), enquanto um trailing stop auxiliar mantém a distância de risco fixa em pontos brutos depois que uma posição se torna lucrativa.

Lógica de negociação

  1. Assinatura de dados – a estratégia escuta velas finalizadas do período selecionado e mantém um indicador ATR com período configurável.
  2. Detecção de Doji – uma vela é tratada como doji quando o tamanho absoluto do corpo é no máximo 3% da faixa completa da vela. Apenas velas concluídas são avaliadas.
  3. Colocação de pedido – quando um doji válido é encontrado:
    • Uma ordem de compra stop é colocada na máxima doji.
    • Uma ordem de stop de venda é colocada na mínima doji.
    • Cada entrada lembra um preço de parada de proteção igual ao extremo oposto menos/mais ATR × multiplicador.
  4. Gerenciamento de risco – assim que uma posição é aberta, a ordem pendente restante é cancelada, o stop memorizado é registrado como um stop de proteção e a lógica móvel assume o controle.
  5. Trailing stop – em cada nova vela o nível de stop é movido para manter uma distância fixa (em pontos convertidos através da etapa de preço do instrumento) do último preço de fechamento, mas somente quando a posição já for lucrativa.

A estratégia nunca utiliza metas de lucro; as saídas acontecem através da parada de proteção ou intervenção manual.

Parâmetros

Parâmetro Descrição
CandleType Tipo de dados Candle usado para detecção de padrões (período diário por padrão).
AtrPeriod Comprimento de lookback do indicador ATR.
AtrMultiplier Multiplicador aplicado ao valor ATR para cálculo de stop loss.
TrailingDistancePoints Distância fixa em pontos brutos usados ao rastrear a parada.

Todos os parâmetros suportam otimização dentro do ambiente StockSharp.

Notas de implementação

  • O código depende da assinatura de vela de alto nível API (SubscribeCandles) combinada com a vinculação do indicador (Bind) para evitar o tratamento manual do histórico.
  • Os pedidos são normalizados por meio de Security.ShrinkPrice para respeitar o tamanho do tick da exchange.
  • As paradas de proteção são gerenciadas explicitamente para imitar o comportamento do consultor especialista MetaTrader original.
  • O projeto omite intencionalmente uma implementação Python de acordo com os requisitos da tarefa.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Rapid Doji strategy: detects doji candles and trades the breakout direction.
/// Buys on next candle if it closes above doji high, sells if below doji low.
/// Uses ATR for volatility confirmation.
/// </summary>
public class RapidDojiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _dojiThreshold;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _prevWasDoji;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public decimal DojiThreshold { get => _dojiThreshold.Value; set => _dojiThreshold.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public RapidDojiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Period", "ATR period for volatility filter", "Indicators");
		_dojiThreshold = Param(nameof(DojiThreshold), 0.15m)
			.SetDisplay("Doji Threshold", "Max body/range ratio for doji detection", "Pattern");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between breakouts", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = 0m;
		_prevLow = 0m;
		_prevWasDoji = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevWasDoji = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var atr = new AverageTrueRange { Length = AtrPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(atr, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (_prevWasDoji && atr > 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			var close = candle.ClosePrice;
			if (close > _prevHigh + atr * 0.2m && Position <= 0)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (close < _prevLow - atr * 0.2m && Position >= 0)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		_prevWasDoji = range > 0 && body <= DojiThreshold * range;
		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
	}
}