Ver no GitHub

Estratégia do Profeta

Visão geral

Esta estratégia é uma versão StockSharp do MetaTrader 4 consultor especialista "PROphet". O EA original avalia a negociação recente percorre quatro velas históricas e usa essas faixas ponderadas para acionar novas negociações. Mantém posições abertas apenas entre os nas sessões europeia e norte-americana e segue o stop loss sempre que o preço se move uma distância fixa a favor da negociação. O StockSharp a implementação mantém toda essa mecânica enquanto os adapta ao modelo de compensação usado pelos portfólios StockSharp.

Lógica de negociação

  • Assine o prazo configurado (CandleType, padrão M5) e processe apenas velas concluídas.
  • Mantenha as três velas concluídas mais recentemente para reproduzir a indexação High[i] e Low[i] usada pela versão MQL.
  • Calcule o gatilho longo Qu(X1, X2, X3, X4) e o gatilho curto Qu(Y1, Y2, Y3, Y4) em cada barra. Cada termo multiplica um intervalo ponderado (por exemplo |High[1] - Low[2]|) pelo peso correspondente menos cem, exatamente como no código original.
  • Permitir novas entradas somente quando a hora atual estiver entre TradeStartHour e TradeEndHour (inclusive). Isso imita o homem janela de negociação normal do especialista MQL (das 10h00 às 18h00 por padrão).
  • Utilize uma única ordem de mercado cujo volume neutralize qualquer exposição oposta antes de abrir a nova posição. Isso reflete o Mag ic Filtros de número da implementação MetaTrader.

Gerenciamento de risco e rastreamento

  • A estratégia converte as distâncias de parada baseadas em pontos MetaTrader em unidades de preço por meio do instrumento PriceStep. Os padrões (B uyStopLossPoints = 68, SellStopLossPoints = 72) corresponde às variáveis externas MQL.
  • Assim que o lance (para negociações longas) ou o pedido (para negociações curtas) ultrapassar o stop existente em spread + 2 * stopDistance, o O trailing stop é avançado para currentPrice ± stopDistance, usando dados de nível 1 ao vivo, quando disponíveis.
  • As negociações abertas são fechadas à força após ExitHour. O valor padrão (18) reproduz o comportamento original de fechamento da posição s depois das 18:00, horário do servidor.
  • As saídas protetoras usam ordens de mercado porque o API de alto nível de StockSharp não gera ordens de stop automaticamente. Isso mantém comportamento determinístico entre corretores.

Parâmetros

Parâmetro Descrição
AllowBuy Permite negociações longas.
AllowSell Permite negociações curtas.
X1, X2, X3, X4 Pesos aplicados aos componentes do intervalo do lado longo dentro da fórmula Qu.
BuyStopLossPoints Distância de stop-loss para negociações longas expressa em MetaTrader pontos.
Y1, Y2, Y3, Y4 Pesos aplicados aos componentes do intervalo menor dentro da fórmula Qu.
SellStopLossPoints Distância de stop-loss para negociações curtas expressa em MetaTrader pontos.
TradeVolume Volume base (lotes) utilizado para novas entradas. O volume extra é adicionado automaticamente para fechar a exposição oposta.
TradeStartHour Primeira hora da janela de negociação (inclusive).
TradeEndHour Última hora da janela de negociação (inclusive).
ExitHour Hora após a qual todas as negociações abertas são fechadas.
CandleType Prazo das velas utilizadas para análise.

Notas

  • StockSharp carteiras são compensadas por padrão. Quando um novo sinal aparece, a estratégia adiciona o volume necessário para nivelar o ex posição atual antes de abrir a nova negociação, que reproduz o design de posição única por direção da experiência MetaTrader Rt.
  • O script MQL usou a propagação de símbolos relatada por MarketInfo. A porta recupera o spread dos dados de nível 1 quando disponível e, caso contrário, volta a uma única etapa de preço.
  • Como o trailing stop é avaliado no fechamento de cada vela finalizada, pode ocorrer derrapagem em comparação com o stop no nível do tick atualizações realizadas pelo EA original.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Translation of the MetaTrader "PROphet" expert advisor.
/// Uses a range-weighted signal from previous candles to enter trades.
/// </summary>
public class ProphetStrategy : Strategy
{
	private readonly StrategyParam<int> _x1;
	private readonly StrategyParam<int> _x2;
	private readonly StrategyParam<int> _x3;
	private readonly StrategyParam<int> _x4;
	private readonly StrategyParam<DataType> _candleType;

	private ICandleMessage _candle1;
	private ICandleMessage _candle2;
	private ICandleMessage _candle3;
	private decimal _entryPrice;

	public ProphetStrategy()
	{
		_x1 = Param(nameof(X1), 9)
			.SetDisplay("X1", "Weight applied to |High[1] - Low[2]|.", "Signal");

		_x2 = Param(nameof(X2), 29)
			.SetDisplay("X2", "Weight applied to |High[3] - Low[2]|.", "Signal");

		_x3 = Param(nameof(X3), 94)
			.SetDisplay("X3", "Weight applied to |High[2] - Low[1]|.", "Signal");

		_x4 = Param(nameof(X4), 125)
			.SetDisplay("X4", "Weight applied to |High[2] - Low[3]|.", "Signal");

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

	public int X1 { get => _x1.Value; set => _x1.Value = value; }
	public int X2 { get => _x2.Value; set => _x2.Value = value; }
	public int X3 { get => _x3.Value; set => _x3.Value = value; }
	public int X4 { get => _x4.Value; set => _x4.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

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

		_candle1 = null;
		_candle2 = null;
		_candle3 = null;
		_entryPrice = 0;
	}

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

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

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

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

		// Shift history
		_candle3 = _candle2;
		_candle2 = _candle1;
		_candle1 = candle;

		if (_candle1 == null || _candle2 == null || _candle3 == null)
			return;

		// Manage position - simple exit on reversal signal
		if (Position > 0)
		{
			var sellSignal = CalculateSignal(true);
			if (sellSignal > 0)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			var buySignal = CalculateSignal(false);
			if (buySignal > 0)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		// Entry
		if (Position == 0)
		{
			var buySignal = CalculateSignal(false);
			var sellSignal = CalculateSignal(true);

			if (buySignal > 0 && buySignal > sellSignal)
			{
				BuyMarket();
				_entryPrice = candle.ClosePrice;
			}
			else if (sellSignal > 0 && sellSignal > buySignal)
			{
				SellMarket();
				_entryPrice = candle.ClosePrice;
			}
		}
	}

	private decimal CalculateSignal(bool isSell)
	{
		var term1 = Math.Abs(_candle1.HighPrice - _candle2.LowPrice);
		var term2 = Math.Abs(_candle3.HighPrice - _candle2.LowPrice);
		var term3 = Math.Abs(_candle2.HighPrice - _candle1.LowPrice);
		var term4 = Math.Abs(_candle2.HighPrice - _candle3.LowPrice);

		if (isSell)
		{
			// For sell, use inverted weights
			return (100 - X1) * term1 + (100 - X2) * term2 + (X3 - 100) * term3 + (X4 - 100) * term4;
		}

		// For buy, use standard weights
		return (X1 - 100) * term1 + (X2 - 100) * term2 + (100 - X3) * term3 + (100 - X4) * term4;
	}
}