Ver no GitHub

Estratégia JK BullP AutoTrader

Visão geral

JK BullP AutoTrader é um consultor especialista em acompanhamento de impulso originalmente escrito para MetaTrader 4. Ele monitora o Elder Bulls Power indicador e reage quando a pressão de alta enfraquece ou fica negativa. A porta StockSharp mantém a lógica direta do original, ao mesmo tempo que fornece parâmetros explícitos, gerenciamento detalhado de rastreamento e controles de risco amigáveis à plataforma.

Lógica de negociação

  1. A estratégia assina uma série de velas configuráveis (velas de 1 hora por padrão) e calcula um valor exponencial de 13 períodos. média móvel (EMA) para replicar a linha de base do Bulls Power.
  2. Para cada vela concluída, o Bulls Power é medido como a diferença entre a máxima da vela e o valor EMA.
  3. Duas leituras consecutivas do Bulls Power são comparadas:
    • Se o valor anterior estiver acima do valor mais recente e o valor mais recente permanecer positivo, a estratégia abre uma posição curta.
    • Se o último valor do Bulls Power cair abaixo de zero, a estratégia abre uma posição longa.
  4. Apenas uma posição pode estar ativa por vez, espelhando o especialista MQL original que bloqueou novas ordens enquanto as negociações estavam abertas.

Gestão de riscos e saídas

  • Stop-loss/take-profit inicial: As distâncias são configuradas em pips e convertidas em unidades de preço usando a etapa de preço do título. Ambas as proteções são habilitadas por meio do auxiliar StartProtection do StockSharp, mantendo o comportamento próximo às entradas do MetaTrader.
  • Trailing stop: Quando o lucro flutuante excede a distância final especificada, o nível de stop é movido vela por vela. Em vez de modificar as ordens stop existentes (como em MetaTrader), a porta emite uma ordem de mercado para sair da posição quando o preço fecha além do limite final. Isto garante saídas oportunas mesmo quando as ordens de proteção não são apoiadas pelo local.

Parâmetros

Nome Descrição Padrão
OrderVolume Tamanho da ordem de mercado usado para entradas. 8,5
TakeProfitPips Distância de take-profit em pips (convertida em unidades de preço). 500
StopLossPips Distância de stop-loss em pips. 20
TrailingStopPips Distância de lucro em pips que ativa e mantém o trailing stop. 10
EmaPeriod Comprimento do EMA usado pelo cálculo do Bulls Power. 13
CandleType Tipo de dados das velas que orientam a estratégia (período padrão de 1 hora). Velas de 1 hora

Notas de implementação

  • As entradas não utilizadas (Patr, Prange, Kstop, kts, Vts) do script original foram omitidas intencionalmente porque tinham nenhum efeito na lógica MetaTrader.
  • As distâncias pip dependem do instrumento PriceStep. Se os dados da etapa não estiverem disponíveis, um valor de 1 será usado como padrão conservador.
  • A estratégia usa StockSharp Bind API de alto nível, processa apenas velas concluídas e mantém o estado interno (_previousBullsPower) para corresponder aos cálculos baseados em turnos MT4.
  • A lógica móvel é redefinida automaticamente após cada saída para evitar níveis de parada obsoletos quando uma nova posição é aberta.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// JK BullP AutoTrader: RSI momentum with EMA filter and ATR stops.
/// </summary>
public class JkBullPAutoTraderStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevRsi;
	private decimal _entryPrice;

	public JkBullPAutoTraderStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");
		_rsiLength = Param(nameof(RsiLength), 13)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");
		_emaLength = Param(nameof(EmaLength), 20)
			.SetDisplay("EMA Length", "Trend filter.", "Indicators");
		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiLength { get => _rsiLength.Value; set => _rsiLength.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }

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

		_prevRsi = 0; _entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 0; _entryPrice = 0;
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var atr = new AverageTrueRange { Length = AtrLength };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ema, atr, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, ema); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevRsi == 0 || atrVal <= 0) { _prevRsi = rsiVal; return; }
		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 75) { SellMarket(); _entryPrice = 0; }
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 25) { BuyMarket(); _entryPrice = 0; }
		}

		if (Position == 0)
		{
			if (rsiVal > 55 && _prevRsi <= 55 && close > emaVal) { _entryPrice = close; BuyMarket(); }
			else if (rsiVal < 45 && _prevRsi >= 45 && close < emaVal) { _entryPrice = close; SellMarket(); }
		}
		_prevRsi = rsiVal;
	}
}