Ver no GitHub

Estratégia Extrema Sweet Spot

Sweet Spot Extreme é uma porta direta do MetaTrader 4 consultor especialista "Sweet_Spot_Extreme.mq4" construído no StockSharp de alto nível API. A estratégia busca fortes retrocessos dentro de uma tendência existente, combinando duas médias móveis exponenciais em velas de 15 minutos com um filtro de índice de canal de commodities de 30 minutos (CCI). O dimensionamento da posição reflete os controles de risco originais, incluindo a redução de lote no estilo MetaTrader após sequências de derrotas.

Lógica central

  1. Confirmação da inclinação da tendência. O EMA principal (MaPeriod, padrão 85) e o próximo EMA (CloseMaPeriod, padrão 70) são alimentados com preços medianos de 15 minutos. Uma configuração longa exige que ambos os EMAs se inclinem para cima; uma configuração curta precisa que ambos se inclinem para baixo.
  2. CCI filtro de exaustão. Uma segunda assinatura de vela (30 minutos por padrão) alimenta o CciPeriod CCI. As negociações longas só disparam quando CCI cai abaixo de BuyCciLevel (-200), enquanto as posições curtas exigem CCI acima de SellCciLevel (+200).
  3. Limite da pirâmide. A posição líquida agregada não pode exceder MaxTradesPerSymbol × volume. Quando um novo sinal aparece, a estratégia fecha qualquer exposição oposta e então soma a capacidade permitida na direção do sinal.
  4. Saídas. As posições são fechadas quando a tendência EMA perde sua vantagem de inclinação (espelhando a condição MQL MA <= MAprevious) ou depois que o preço percorre StopPoints o instrumento aponta a favor da posição.

Gestão de risco

  • Volume baseado em risco. O tamanho padrão do pedido é Portfolio.CurrentValue × MaximumRisk ÷ price. Quando faltam informações de patrimônio, o mecanismo recorre ao parâmetro Lots (ou à estratégia Volume).
  • Ajuste de sequência de perdas. Após duas ou mais negociações consecutivas perdidas, o tamanho do novo pedido é reduzido em volume × losses ÷ DecreaseFactor, correspondendo ao auxiliar MQL LotsOptimized().
  • Normalização. O volume final é alinhado com o VolumeStep do instrumento, delimitado por MinVolume e cortado por Security.MaxVolume quando fornecido.

Parâmetros

Nome Padrão Descrição
MaxTradesPerSymbol 3 Número máximo de entradas agregadas permitidas por direção.
Lots 1 Tamanho de lote fixo substituto quando o patrimônio do portfólio não estiver disponível.
MaximumRisk 0.05 Fração do patrimônio usado para dimensionar cada nova negociação.
DecreaseFactor 6 Divisor que reduz o próximo pedido após perdas consecutivas.
StopPoints 10 Distância alvo de lucro em pontos de instrumento. Defina como 0 para desativar.
MaPeriod 85 Período EMA aplicado a velas de 15 minutos para a verificação da inclinação da tendência.
CloseMaPeriod 70 Período EMA aplicado a velas de 15 minutos para o filtro de suavização próximo.
CciPeriod 12 Lookback usado para o filtro CCI de 30 minutos.
BuyCciLevel -200 Limite de sobrevenda CCI necessário para entradas longas.
SellCciLevel 200 Limite de sobrecompra de CCI necessário para entradas curtas.
MinVolume 0.1 Volume mínimo permitido após a normalização.
TrendCandleType 15m Tipo de vela usado para cálculos de EMA (preço médio).
CciCandleType 30m Tipo de vela usado para o filtro CCI.

Notas e limitações

  • StockSharp opera no modo de compensação, portanto, vários tickets MT4 são representados como uma única posição agregada. A proteção MaxTradesPerSymbol, portanto, limita a exposição líquida em vez de contar pedidos individuais.
  • O EA original dependia de AccountFreeMargin para dimensionamento. Esta porta se aproxima de Portfolio.CurrentValue; ajuste MaximumRisk ou Lots para atender às especificações do contrato do seu corretor.
  • Certifique-se de que ambas as assinaturas de vela estejam habilitadas na fonte de dados, caso contrário, os filtros EMA ou CCI nunca serão formados e a estratégia permanecerá inativa.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// EMA slope + CCI filter strategy.
/// Buys when EMA slope is up and CCI is oversold.
/// Sells when EMA slope is down and CCI is overbought.
/// Exits on EMA slope reversal.
/// </summary>
public class SweetSpotExtremeStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _buyCciLevel;
	private readonly StrategyParam<decimal> _sellCciLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevEma;
	private decimal _prevPrevEma;
	private bool _hasPrevEma;

	public int EmaPeriod
	{
		get => _emaPeriod.Value;
		set => _emaPeriod.Value = value;
	}

	public int CciPeriod
	{
		get => _cciPeriod.Value;
		set => _cciPeriod.Value = value;
	}

	public decimal BuyCciLevel
	{
		get => _buyCciLevel.Value;
		set => _buyCciLevel.Value = value;
	}

	public decimal SellCciLevel
	{
		get => _sellCciLevel.Value;
		set => _sellCciLevel.Value = value;
	}

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

	public SweetSpotExtremeStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetDisplay("EMA Period", "Trend EMA period", "Indicators");

		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetDisplay("CCI Period", "CCI lookback", "Indicators");

		_buyCciLevel = Param(nameof(BuyCciLevel), -50m)
			.SetDisplay("Buy CCI", "Oversold CCI level for buy", "Indicators");

		_sellCciLevel = Param(nameof(SellCciLevel), 50m)
			.SetDisplay("Sell CCI", "Overbought CCI level for sell", "Indicators");

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

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

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

		_prevEma = 0m;
		_prevPrevEma = 0m;
		_hasPrevEma = false;
	}

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

		_prevEma = 0;
		_prevPrevEma = 0;
		_hasPrevEma = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var cci = new CommodityChannelIndex { Length = CciPeriod };

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

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

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

		if (!_hasPrevEma)
		{
			_prevPrevEma = emaValue;
			_prevEma = emaValue;
			_hasPrevEma = true;
			return;
		}

		var slopeUp = emaValue > _prevEma && _prevEma > _prevPrevEma;
		var slopeDown = emaValue < _prevEma && _prevEma < _prevPrevEma;

		// Entry
		if (slopeUp && cciValue <= BuyCciLevel && Position <= 0)
		{
			BuyMarket();
		}
		else if (slopeDown && cciValue >= SellCciLevel && Position >= 0)
		{
			SellMarket();
		}
		// Exit on slope reversal
		else if (Position > 0 && emaValue < _prevEma)
		{
			SellMarket();
		}
		else if (Position < 0 && emaValue > _prevEma)
		{
			BuyMarket();
		}

		_prevPrevEma = _prevEma;
		_prevEma = emaValue;
	}
}