Ver no GitHub

Grade do Gerenciador de Comércio XP (C#)

Visão geral

A estratégia XP Trade Manager Grid é uma porta direta do MetaTrader 4 consultor especialista XP Trade Manager Grid.mq4. Ele automatiza uma grade simétrica que adiciona continuamente novas posições sempre que o mercado se afasta de um número configurável de pontos da última etapa preenchida. O especialista original administrou os lucros com níveis de take-profit parciais para as três primeiras ordens, um cluster de ponto de equilíbrio quando a escada cresce e uma proteção de risco global baseada na porcentagem da conta. A implementação StockSharp mantém as mesmas ideias enquanto aproveita primitivas API de alto nível (ordens de mercado, assinaturas de velas e parâmetros de estratégia).

Lógica de negociação

  1. Entrada inicial – a estratégia abre imediatamente a primeira ordem de mercado na direção selecionada pelo usuário (venda por padrão). Todas as negociações subsequentes são agrupadas na escada da grade.
  2. Expansão da grade – sempre que o preço de fechamento oscila em StepPoints * passo de preço além da perna mais recente de um lado, uma nova ordem de mercado é colocada nessa direção, desde que o número total de pernas simultâneas seja inferior a MaxOrders.
  3. TP dedicado para as três primeiras etapas – as três primeiras ordens de cada lado herdam suas compensações de take-profit exclusivas (TakeProfit1Partitive, TakeProfit2, TakeProfit3). Uma vez que os máximos/mínimos da vela tocam esses níveis, a perna fica achatada.
  4. Cluster de equilíbrio – quando a quantidade total de pernas abertas atinge quatro ou mais, a estratégia calcula o preço de equilíbrio ponderado de toda a escada. Dependendo de qual lado tem mais pernas, ele compensa esse ponto de equilíbrio pela meta total correspondente (TakeProfit4TotalTakeProfit15Total) dividida entre os pedidos ativos. Se o preço atingir o objetivo calculado, toda a exposição será fechada.
  5. Renovação do ciclo – se a primeira ordem de um ciclo for fechada, mas o lucro coletado em pontos ainda estiver abaixo de TakeProfit1Total, a lógica espera que o mercado se mova TakeProfit1Offset pontos além da última saída e então reabre a ordem inicial.
  6. Controle de risco – o lucro flutuante na moeda da conta (realizado + não realizado) é constantemente comparado com RiskPercent por cento do saldo inicial do portfólio. Se o limite de perda for violado, toda a escada será achatada imediatamente.

A porta C# rastreia cada trecho preenchido internamente. Os preenchimentos parciais são suportados e as estruturas cobertas (compra e venda simultâneas) são resolvidas exatamente como no especialista MQL: os preenchimentos opostos primeiro cancelam as pernas pendentes antes que uma nova exposição seja registrada.

Parâmetros

Nome Descrição
CandleType Tipo de dados usado para conduzir a estratégia (padrão: velas de 1 minuto).
OrderVolume Volume de cada ordem/perna de mercado.
MaxOrders Máximo de pernas simultâneas em ambas as direções.
StepPoints Distância em pontos entre ordens de grade consecutivas.
RiskPercent Perda flutuante máxima tolerável como % do saldo inicial da carteira.
TakeProfit1Total Meta total de pontos acumulados pelos ciclos do pedido nº 1 antes que nenhuma renovação automática ocorra.
TakeProfit1Partitive Distância de lucro (pontos) para a primeira etapa.
TakeProfit1Offset Distância mínima de retração necessária antes de recriar a primeira ordem.
TakeProfit2 / TakeProfit3 Deslocamentos de TP individuais (pontos) para as pernas 2 e 3.
TakeProfit4TotalTakeProfit15Total Totais de TP de ponto de equilíbrio usados quando o tamanho da escada atinge o número correspondente de pedidos.
InitialSide Direção do primeiro pedido (Compra ou Venda).

Observação: Todas as entradas baseadas em pontos são automaticamente dimensionadas pela segurança PriceStep, correspondendo à lógica Point() original de MetaTrader.

Comportamento comparado à versão MetaTrader

  • A variante StockSharp fecha as três primeiras etapas por meio de ordens de mercado em vez de modificar os valores de take-profit individuais, porque o API de alto nível não expõe a modificação direta da ordem.
  • Os cálculos de lucro flutuante baseiam-se na etapa do instrumento e no preço da etapa. Corretores com especificações de contrato exóticas podem exigir ajustes se não exporem esses campos.
  • Os rótulos de nível de plataforma mostrados no MT4 ("Profit pips" / "Profit coins") não são reproduzidos. Em vez disso, as estatísticas do ciclo interno são usadas para decidir quando reabrir o primeiro pedido.

Requisitos

  • Anexe a estratégia a uma segurança que exponha PriceStep e StepPrice.
  • Certifique-se de que o conector de negociação suporta ordens de mercado imediatas ou canceladas. Todas as pernas da grade são executadas por meio de métodos auxiliares BuyMarket/SellMarket.

Dicas de uso

  1. Comece com valores OrderVolume pequenos ao testar para avaliar como a grade se comporta em seu feed.
  2. Ajuste cuidadosamente StepPoints para a volatilidade do símbolo. Degraus maiores reduzem o número de pernas abertas e, portanto, o rebaixamento.
  3. Aumente TakeProfit1Offset ao negociar instrumentos com spreads mais amplos para evitar reentradas prematuras.
  4. Combine a estratégia com a chamada StartProtection() integrada, que monitora desconexões inesperadas e reconecta normalmente.
using System;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Simplified from "XP Trade Manager Grid" MetaTrader expert.
/// Uses RSI for entry direction with grid-style position management.
/// </summary>
public class XpTradeManagerGridStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpper;
	private readonly StrategyParam<decimal> _rsiLower;

	private RelativeStrengthIndex _rsi;
	private decimal? _prevRsi;

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

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

	public decimal RsiUpper
	{
		get => _rsiUpper.Value;
		set => _rsiUpper.Value = value;
	}

	public decimal RsiLower
	{
		get => _rsiLower.Value;
		set => _rsiLower.Value = value;
	}

	public XpTradeManagerGridStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for signal generation", "General");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");

		_rsiUpper = Param(nameof(RsiUpper), 70m)
			.SetDisplay("RSI Upper", "RSI threshold for sell", "Signals");

		_rsiLower = Param(nameof(RsiLower), 30m)
			.SetDisplay("RSI Lower", "RSI threshold for buy", "Signals");
	}

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

		_prevRsi = null;
		_rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

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

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

		if (!_rsi.IsFormed)
		{
			_prevRsi = rsiValue;
			return;
		}

		if (_prevRsi is null)
		{
			_prevRsi = rsiValue;
			return;
		}

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

		// RSI crosses below oversold -> buy
		var crossDown = _prevRsi.Value > RsiLower && rsiValue <= RsiLower;
		// RSI crosses above overbought -> sell
		var crossUp = _prevRsi.Value < RsiUpper && rsiValue >= RsiUpper;

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

		_prevRsi = rsiValue;
	}

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

		base.OnReseted();
	}
}