Ver no GitHub

Estratégia do Mod Pedro

Visão geral

Esta estratégia é uma versão StockSharp do consultor especialista Pedroxxmod MetaTrader 4. O EA original espera que o mercado mova um alguns pips de distância de um preço de referência e então abre uma posição contrária. Os pedidos subsequentes são calculados na mesma direção sempre que o preço retrocede por uma distância configurável. A implementação StockSharp mantém o comportamento intacto ao expor parâmetros fortemente digitados por meio do Strategy API de alto nível.

Lógica de negociação

  1. Assine as melhores cotações de compra/venda da Level1 e armazene em cache os valores mais recentes.
  2. Quando nenhuma negociação estiver aberta, armazene o preço de venda atual como nível de entrada de referência. A negociação só é permitida entre StartHour e EndHour, e de StartYear em diante.
  3. Se a melhor venda subir Gap MetaTrader pips acima da referência, envie uma ordem de venda a mercado. Se cair Gap pips, enviar uma ordem de compra de mercado. Os níveis protetores de stop-loss e take-profit são anexados automaticamente chamando SetStopLoss / SetTakeProfit com as mesmas distâncias de pip que o consultor especialista.
  4. Uma vez estabelecida uma direção de cesta, a estratégia mantém uma lista FIFO das posições sintéticas para emular o hedge. estilo de MetaTrader. Contanto que o tamanho atual da cesta seja inferior a MaxTrades, a média dos pedidos será adicionada quando a melhor oferta retorna dentro de ReEntryGap pips do último preço de entrada.
  5. O gerenciamento de dinheiro pode usar o parâmetro fixo Lots ou alocar volume dinamicamente de acordo com a regra EA floor(Equity / 20000), limitado por MaxLots. Todos os volumes são normalizados em relação à etapa/mín/máx do volume da segurança.
  6. As atualizações fora do horário comercial redefinem as âncoras de entrada internas para evitar negociações falsas quando a próxima sessão começar.

Parâmetros

Nome Descrição
Lots Volume de pedidos fixo quando o gerenciamento de dinheiro está desativado.
StopLoss Distância de parada protetora em MetaTrader pips. Defina como 0 para desativar a parada.
TakeProfit Distância alvo de lucro em MetaTrader pips. Defina como 0 para desativar o alvo.
Gap Distância em MetaTrader pips que o pedido deve se afastar da referência antes de abrir a primeira negociação.
MaxTrades Número máximo de negociações abertas simultaneamente (tamanho da cesta).
ReEntryGap Distância em MetaTrader pips que aciona a média dos pedidos na direção da cesta.
MoneyManagement Ativa a regra de volume dinâmico floor(Equity / 20000) quando definida como true.
MaxLots Limite superior para o volume calculado dinamicamente.
StartHour / EndHour Janela de negociação no horário do servidor Exchange (inclusive).
StartYear Ano civil a partir do qual a negociação é permitida. Os dados anteriores são ignorados.

Notas

  • A estratégia consome apenas dados do Nível 1 e não solicita velas. É, portanto, leve e reage imediatamente a alterações de cotação, assim como o manipulador de ticks MT4 start().
  • Paradas e alvos dependem dos métodos auxiliares de Strategy para traduzir distâncias de MetaTrader pip em específicas do corretor níveis de preços. Certifique-se de que o local conectado exponha os valores PriceStep, StepPrice e VolumeStep corretos.
  • O contador de cesta sintético permite que a estratégia imite contas de hedge, mesmo que StockSharp agregue a posição. Preenchimentos parciais e ocorrências de parada são tratados por meio do retorno de chamada OnPositionChanged que mantém as filas FIFO.
  • A implementação do Python é omitida intencionalmente de acordo com as diretrizes do repositório.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;

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

/// <summary>
/// Pedro Mod mean reversion strategy using Bollinger Bands.
/// Buy when price touches the lower band, sell when price touches the upper band.
/// </summary>
public class PedroModStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerWidth { get => _bollingerWidth.Value; set => _bollingerWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public PedroModStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("Bollinger Period", "Bollinger Bands period", "Indicators");

		_bollingerWidth = Param(nameof(BollingerWidth), 1.5m)
			.SetDisplay("Bollinger Width", "Standard deviation multiplier", "Indicators");

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

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

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

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

		var bb = new BollingerBands { Length = BollingerPeriod, Width = BollingerWidth };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bb, ProcessCandle)
			.Start();
	}

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

		if (!bbValue.IsFinal)
			return;

		var bb = (BollingerBandsValue)bbValue;
		if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower || bb.MovingAverage is not decimal middle)
			return;

		// Buy when price touches lower band (mean reversion)
		if (Position <= 0 && candle.ClosePrice <= lower)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell when price touches upper band
		else if (Position >= 0 && candle.ClosePrice >= upper)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit at middle band
		else if (Position > 0 && candle.ClosePrice >= middle)
		{
			SellMarket();
		}
		else if (Position < 0 && candle.ClosePrice <= middle)
		{
			BuyMarket();
		}
	}
}