Ver no GitHub

Estratégia de grade Turbo Scaler

Visão geral

A estratégia Turbo Scaler Grid é uma implementação StockSharp de alto nível do consultor especialista MQL5 "Turbo Scaler Grid Pending". A estratégia se concentra no gerenciamento de grades de stop pendentes em torno de níveis de preços predefinidos, protegendo dinamicamente as posições abertas com ponto de equilíbrio e lógica de trailing e supervisionando o patrimônio da conta para fechar posições quando os limites de lucro ou perda são atingidos.

A lógica funciona em vários períodos de tempo simultaneamente:

  • Um período de tempo de disparo configurável observa sinais de proximidade de preço que ativam a grade pendente.
  • Velas adicionais de 30 minutos, 2 horas e diárias fornecem confirmação para gatilhos condicionais opcionais.
  • Os dados de nível 1 fornecem os valores de compra/venda mais recentes usados para posicionar ordens pendentes e gerenciar trailing stops.

Regras de negociação

  1. Grade pendente
    • As ordens de compra e venda são colocadas a partir de preços âncora configuráveis (BuyStopEntry e SellStopEntry).
    • Os pedidos são espaçados por PendingStepPoints e limitados por PendingQuantity.
    • O gatilho de preço verifica as velas recentes no período de gatilho para confirmar que o preço se aproximou do nível âncora com impulso suficiente.
    • O gatilho de condição valida filtros adicionais de vários períodos de tempo (intervalos de blocos diários, direção de velas H2 e M30 e nível médio) antes de colocar ordens pendentes.
  2. Proteção de posição
    • O stop loss inicial é calculado a partir de StopLossPoints (ou substituições de preço fixo).
    • Quando o preço avança BreakevenTriggerPoints, o stop é movido para o preço de entrada mais BreakevenOffsetPoints (para posições compradas) ou menos o deslocamento (para posições vendidas).
    • Um trailing stop é ativado somente após o ponto de equilíbrio ser atingido, sendo atualizado quando o preço excede o stop anterior em TrailMultiplier * TrailPoints.
  3. Supervisão patrimonial
    • A estratégia monitora o PnL flutuante e força a liquidação da posição se o rebaixamento exceder MaxFloatLoss (escalonado para o volume do pedido selecionado).
    • Um gatilho de lucro flutuante bloqueia ganhos colocando uma linha de patrimônio interno em EquityBreakeven e seguindo-a por EquityTrail quando o lucro ultrapassar EquityTrigger.

Parâmetros

Nome Descrição
StopLossPoints Distância inicial de stop-loss em pontos.
BreakevenTriggerPoints Pontos necessários para ativar o movimento de equilíbrio.
BreakevenOffsetPoints Compensação adicionada ao preço de entrada quando o stop é movido para o ponto de equilíbrio.
TrailPoints Distância usada para trilhar após o ponto de equilíbrio.
TrailMultiplier Multiplicador aplicado antes de um novo trailing stop ser definido.
BuyStopLossPrice / SellStopLossPrice Preços de parada fixa opcionais para posições longas/curtas.
BuyStopEntry / SellStopEntry Preços base para as grades de stop pendentes.
OrderVolume Volume por ordem pendente.
PendingQuantity Número máximo de ordens pendentes ativas.
PendingStepPoints Distância entre ordens pendentes consecutivas.
TriggerCandleType Série de velas usada para a lógica de gatilho de preço.
PendingPriceTrigger Ativa o gatilho de proximidade de preço.
PendingConditionTrigger Ativa o gatilho de confirmação de vários períodos.
OrderBuyBlockStart / OrderBuyBlockEnd Bloco baixo diário usado para validar configurações longas.
OrderSellBlockStart / OrderSellBlockEnd Bloco alto diário usado para validar configurações curtas.
MaxFloatLoss Perda flutuante máxima permitida (escalonada por volume).
EquityBreakeven Nível de patrimônio mantido após a ativação do gatilho de lucro.
EquityTrigger Lucro flutuante necessário para criar o bloqueio de capital.
EquityTrail Distância final aplicada ao bloqueio de patrimônio.

Notas

  • O volume do pedido é dimensionado para corresponder ao comportamento original do EA (0.01 lotes são tratados como a etapa base).
  • Todos os comentários dentro do código são escritos em inglês, enquanto este documento fornece uma descrição detalhada para uma integração rápida.
  • A estratégia usa apenas APIs StockSharp de alto nível (SubscribeCandles, Bind, BuyStop, SellStop, SellMarket, BuyMarket) de acordo com os requisitos do projeto.
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 "Turbo Scaler Grid" MetaTrader expert.
/// Uses EMA crossover with RSI confirmation for scalping entries.
/// </summary>
public class TurboScalerGridStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _rsiUpper;
	private readonly StrategyParam<decimal> _rsiLower;

	private ExponentialMovingAverage _fastEma;
	private ExponentialMovingAverage _slowEma;
	private RelativeStrengthIndex _rsi;
	private decimal? _prevFast;
	private decimal? _prevSlow;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.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 TurboScalerGridStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for scalping", "General");

		_fastPeriod = Param(nameof(FastPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 34)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period (computed manually)", "Indicators");

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

		_rsiUpper = Param(nameof(RsiUpper), 60m)
			.SetDisplay("RSI Upper", "RSI level for buy confirmation", "Signals");

		_rsiLower = Param(nameof(RsiLower), 40m)
			.SetDisplay("RSI Lower", "RSI level for sell confirmation", "Signals");
	}

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

		_prevFast = null;
		_prevSlow = null;

		_fastEma = new ExponentialMovingAverage { Length = FastPeriod };
		_slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
		_rsi = new RelativeStrengthIndex { Length = RsiPeriod };

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

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

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

		if (!_fastEma.IsFormed || !_slowEma.IsFormed || !_rsi.IsFormed)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

		if (_prevFast is null || _prevSlow is null)
		{
			_prevFast = fastValue;
			_prevSlow = slowValue;
			return;
		}

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

		var crossUp = _prevFast.Value <= _prevSlow.Value && fastValue > slowValue;
		var crossDown = _prevFast.Value >= _prevSlow.Value && fastValue < slowValue;

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

		_prevFast = fastValue;
		_prevSlow = slowValue;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_fastEma = null;
		_slowEma = null;
		_rsi = null;
		_prevFast = null;
		_prevSlow = null;

		base.OnReseted();
	}
}