Ver no GitHub

Estratégia DeMarker ganhando posição Volume 2

Esta estratégia reproduz o consultor especialista MetaTrader 5 "DeMarker ganhando volume de posição 2" usando o StockSharp de alto nível de API. Ele analisa uma série de velas configuráveis ​​com o oscilador DeMarker e reage quando o valor entra em zonas extremas. A implementação mantém o sabor original de gerenciamento de dinheiro com tamanho de lote fixo, reversão opcional de sinais, tratamento integrado de stop-loss/take-profit e um filtro de sessão de negociação opcional.

Comportamento original de especialista

  • Plataforma: MetaTrader 5.
  • Indicador: oscilador DeMarker clássico (DEM), período padrão 14.
  • Entradas: abra posições compradas quando o DeMarker cair abaixo de um limite inferior, abra posições vendidas quando ele subir acima de um limite superior.
  • Controles de risco: stop-loss/take-profit fixo expresso em pontos, trailing stop opcional com step, janela de tempo opcional.
  • Gerenciamento de posição: garanta apenas uma negociação por barra e feche o lado oposto antes de mudar de direção.

A conversão StockSharp segue os mesmos princípios. As ordens de proteção são implementadas com StartProtection, portanto, stop-loss, take-profit e trailing são gerenciados automaticamente assim que uma posição é aberta.

Lógica de negociação

  1. Assine o tipo de vela configurado (CandleType, velas de 5 minutos por padrão) e calcule o valor DeMarker com o período escolhido (DeMarkerPeriod).
  2. Quando uma vela fecha, avalie o oscilador:
    • Se ReverseSignals for falso (padrão):
      • Configuração longaDeMarker <= LowerLevel.
      • Configuração curtaDeMarker >= UpperLevel.
    • Se ReverseSignals for true, as regras longas/curtas são trocadas.
  3. Negocie apenas dentro da janela de sessão opcional definida por SessionStart/SessionEnd quando UseTimeFilter estiver ativado. Sessões noturnas são suportadas.
  4. Execute no máximo uma nova entrada por vela. Antes de abrir uma nova posição, a estratégia fecha quaisquer participações opostas para espelhar a lógica MT5.
  5. Os volumes são fixados pelo parâmetro TradeVolume. Se a estratégia já estiver parcialmente na direção desejada, ela completa o volume solicitado.

Gestão de risco

  • StopLossPoints e TakeProfitPoints (em etapas de preço) mapeiam as distâncias de stop e take-profit baseadas em pontos do especialista.
  • Ativar EnableTrailing muda a distância de parada para TrailingStopPoints e ativa o mecanismo de rastreamento integrado usando TrailingStepPoints como etapa de ajuste.
  • StartProtection está configurado com useMarketOrders = true para que as ordens de proteção sejam executadas imediatamente, semelhante ao comportamento de fechamento de negociação MT5.

Parâmetros

Parâmetro Descrição
DeMarkerPeriod Período médio do indicador DeMarker.
UpperLevel / LowerLevel Limites de sobrecompra/sobrevenda acionando posições curtas/longas.
ReverseSignals Troque condições longas e curtas.
StopLossPoints Distância inicial de parada de proteção medida em etapas de preço.
TakeProfitPoints Distância de lucro medida em etapas de preço.
EnableTrailing Ativa o bloco de trailing stop.
TrailingStopPoints Distância do trailing stop quando o trailing estiver ativo.
TrailingStepPoints Movimento favorável mínimo antes do avanço do trailing stop.
UseTimeFilter Restringe a negociação à janela SessionStartSessionEnd.
SessionStart / SessionEnd Limites de sessão inclusivos/exclusivos (suporta wrap-around).
TradeVolume Quantidade a enviar com cada ordem de mercado.
CandleType Série de velas a serem analisadas (padrão 5 minutos).

Notas de implementação

  • O especialista MT5 incluiu um limite de “ativação final”. A proteção final padrão de StockSharp não expõe o mesmo parâmetro, portanto, o rastreamento é ativado imediatamente quando EnableTrailing é verdadeiro.
  • O tratamento de erros para tamanhos de lote inválidos, níveis de congelamento e lógica de atualização de lance/pedido são tratados pela infraestrutura de StockSharp, portanto, são omitidos da conversão.
  • O registro em log é executado por meio da classe base Strategy (chame LogInfo/LogError se for necessário rastreamento adicional).
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Strategy converted from "DeMarker gaining position volume 2" expert advisor.
/// Uses DeMarker oscillator thresholds for entry signals.
/// </summary>
public class DeMarkerGainingPositionVolume2Strategy : Strategy
{
	private readonly StrategyParam<int> _deMarkerPeriod;
	private readonly StrategyParam<decimal> _upperLevel;
	private readonly StrategyParam<decimal> _lowerLevel;
	private readonly StrategyParam<DataType> _candleType;

	private RelativeStrengthIndex _rsi;
	private decimal? _prevOscillator;

	/// <summary>
	/// DeMarker averaging period.
	/// </summary>
	public int DeMarkerPeriod
	{
		get => _deMarkerPeriod.Value;
		set => _deMarkerPeriod.Value = value;
	}

	/// <summary>
	/// Upper DeMarker threshold.
	/// </summary>
	public decimal UpperLevel
	{
		get => _upperLevel.Value;
		set => _upperLevel.Value = value;
	}

	/// <summary>
	/// Lower DeMarker threshold.
	/// </summary>
	public decimal LowerLevel
	{
		get => _lowerLevel.Value;
		set => _lowerLevel.Value = value;
	}

	/// <summary>
	/// Candle type for DeMarker calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public DeMarkerGainingPositionVolume2Strategy()
	{
		_deMarkerPeriod = Param(nameof(DeMarkerPeriod), 14)
			.SetDisplay("DeMarker Period", "Number of bars used by the oscillator.", "Indicator");

		_upperLevel = Param(nameof(UpperLevel), 0.7m)
			.SetDisplay("Upper Level", "Overbought threshold.", "Indicator");

		_lowerLevel = Param(nameof(LowerLevel), 0.3m)
			.SetDisplay("Lower Level", "Oversold threshold.", "Indicator");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for calculations.", "Data");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevOscillator = null;
		_rsi = new RelativeStrengthIndex { Length = DeMarkerPeriod };

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

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

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

		if (!_rsi.IsFormed)
		{
			_prevOscillator = rsiValue / 100m;
			return;
		}

		var oscillatorValue = rsiValue / 100m;

		var volume = Volume;
		if (volume <= 0)
			volume = 1;

		// Cross below lower level => oversold => buy
		if (_prevOscillator is decimal prev)
		{
			var crossBelow = prev >= LowerLevel && oscillatorValue < LowerLevel;
			var crossAbove = prev <= UpperLevel && oscillatorValue > UpperLevel;

			if (crossBelow)
			{
				if (Position <= 0)
					BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
			}
			else if (crossAbove)
			{
				if (Position >= 0)
					SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
			}
		}

		_prevOscillator = oscillatorValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_rsi = null;
		_prevOscillator = null;

		base.OnReseted();
	}
}