Ver no GitHub

Estratégia do comerciante Doji

Esta estratégia converte o consultor especialista MQL4 "DojiTrader" em uma amostra StockSharp C#. Ele procura velas doji recentes e negocia um rompimento da faixa doji durante as principais sessões da Europa e dos EUA.

Lógica de negociação

  • A estratégia processa apenas velas finalizadas do período selecionado (velas de 30 minutos por padrão).
  • A negociação é permitida apenas entre 8h00 e 17h00 horário da plataforma.
  • Embora estável, ele analisa até três velas concluídas e lembra o doji mais recente (o preço de abertura é igual ao preço de fechamento).
  • Quando a vela imediatamente após o doji fecha acima da máxima do doji, um longo rompimento é armado. Se fechar abaixo da mínima doji, um pequeno rompimento será armado.
  • Assim que uma vela subsequente fecha além do preço de ativação, a estratégia envia uma ordem de mercado na direção do rompimento.
  • Após a entrada, o intervalo doji é mantido para controle de saída. A posição é fechada quando:
    • A vela anterior fecha dentro do intervalo (longa: fecha abaixo da mínima do doji, curta: fecha acima da máxima do doji).
    • Os extremos da vela atingem os níveis de stop loss sintético ou takeprofit que imitam as saídas de ponto fixo MQL4 originais.

Parâmetros

  • Volume de ordens – volume utilizado para ordens de mercado.
  • Take Profit (steps) – distância até a meta de lucro medida em etapas de preço.
  • Stop loss (etapas) – distância até o stop de proteção em etapas de preço.
  • Tipo de vela – período de tempo das velas usadas para detecção de sinal.

Os cálculos de stop-loss e take-profit baseiam-se na etapa do preço do título, emulando o EA original que usava distâncias fixas de pip. Quando nenhum doji válido estiver presente nas últimas três velas, o estado de rompimento é apagado e a busca é reiniciada.

using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Doji Trader breakout strategy.
/// Detects doji candles and enters on breakout of doji range.
/// Uses SMA as trend filter for direction.
/// </summary>
public class DojiTraderBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _smaPeriod;
	private readonly StrategyParam<decimal> _dojiRatio;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _prevWasDoji;
	private bool _hasPrev;

	public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
	public decimal DojiRatio { get => _dojiRatio.Value; set => _dojiRatio.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public DojiTraderBreakoutStrategy()
	{
		_smaPeriod = Param(nameof(SmaPeriod), 20)
			.SetDisplay("SMA Period", "SMA period for trend filter", "Indicators");

		_dojiRatio = Param(nameof(DojiRatio), 0.25m)
			.SetDisplay("Doji Ratio", "Max body/range ratio for doji detection", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevHigh = 0m; _prevLow = 0m; _prevWasDoji = false; _hasPrev = false; }

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

		_hasPrev = false;
		_prevWasDoji = false;

		var sma = new SimpleMovingAverage { Length = SmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(sma, ProcessCandle)
			.Start();
	}

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

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
		var isDoji = range > 0 && body / range < DojiRatio;

		if (_hasPrev && _prevWasDoji)
		{
			// Bullish breakout above doji high with SMA confirmation
			if (candle.ClosePrice > _prevHigh && candle.ClosePrice > sma && Position <= 0)
			{
				if (Position < 0)
					BuyMarket();
				BuyMarket();
			}
			// Bearish breakout below doji low with SMA confirmation
			else if (candle.ClosePrice < _prevLow && candle.ClosePrice < sma && Position >= 0)
			{
				if (Position > 0)
					SellMarket();
				SellMarket();
			}
		}

		_prevHigh = candle.HighPrice;
		_prevLow = candle.LowPrice;
		_prevWasDoji = isDoji;
		_hasPrev = true;
	}
}