Ver no GitHub

Estratégia GG-RSI-CCI

Esta estratégia replica o expert advisor GG-RSI-CCI do MetaTrader usando a API de alto nível do StockSharp. Combina os indicadores Índice de Força Relativa (RSI) e Índice de Canal de Commodities (CCI), cada um suavizado por duas médias móveis. Uma posição é aberta quando ambos os indicadores apontam na mesma direção.

Lógica

  1. Indicadores
    • Calcular RSI e CCI com o mesmo período.
    • Suavizar cada indicador com uma média móvel rápida e uma lenta.
  2. Sinais
    • Comprar quando o RSI rápido está acima do RSI lento e o CCI rápido está acima do CCI lento.
    • Vender quando o RSI rápido está abaixo do RSI lento e o CCI rápido está abaixo do CCI lento.
    • Se o modo estiver definido como Flat, qualquer estado neutro fechará a posição atual.
  3. Gestão de risco
    • A estratégia chama StartProtection uma vez na inicialização. Os níveis de stop loss e take profit podem ser configurados através do gerenciador de risco da plataforma.

Parâmetros

Nome Descrição
CandleType Período de tempo usado para os cálculos.
Length Período do RSI e CCI.
FastPeriod Período de suavização rápido.
SlowPeriod Período de suavização lento.
Volume Volume da ordem.
AllowBuyOpen Habilitar abertura de posições compradas.
AllowSellOpen Habilitar abertura de posições vendidas.
AllowBuyClose Habilitar fechamento de posições vendidas.
AllowSellClose Habilitar fechamento de posições compradas.
Mode Trend fecha apenas em sinais opostos; Flat fecha também em sinais neutros.

Observações

A estratégia processa apenas candles completados e usa auxiliares de ordens de alto nível (BuyMarket / SellMarket). Evita acesso direto aos buffers de indicadores e armazena o estado internamente.

using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
using StockSharp.Algo;

namespace StockSharp.Samples.Strategies;



/// <summary>
/// Strategy based on the GG-RSI-CCI indicator.
/// </summary>
public class GgRsiCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _length;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<bool> _allowBuyOpen;
	private readonly StrategyParam<bool> _allowSellOpen;
	private readonly StrategyParam<bool> _allowBuyClose;
	private readonly StrategyParam<bool> _allowSellClose;
	private readonly StrategyParam<SignalModes> _mode;

	private SimpleMovingAverage _rsiFast = null!;
	private SimpleMovingAverage _rsiSlow = null!;
	private SimpleMovingAverage _cciFast = null!;
	private SimpleMovingAverage _cciSlow = null!;
	private int _prevSignal;

	/// <summary>
	/// Defines how positions are closed.
	/// </summary>
	public enum SignalModes
	{
		/// <summary>Position is closed only on opposite signal.</summary>
		Trend,
		/// <summary>Position is closed on any neutral signal.</summary>
		Flat,
	}

	public GgRsiCciStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Time frame for indicator calculation.", "General");

		_length = Param(nameof(Length), 8)
			.SetGreaterThanZero()
			.SetDisplay("Length", "RSI and CCI period.", "Indicators");

		_fastPeriod = Param(nameof(FastPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast smoothing period.", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow smoothing period.", "Indicators");


		_allowBuyOpen = Param(nameof(AllowBuyOpen), true)
			.SetDisplay("Allow Buy", "Permit opening long positions.", "Permissions");

		_allowSellOpen = Param(nameof(AllowSellOpen), true)
			.SetDisplay("Allow Sell", "Permit opening short positions.", "Permissions");

		_allowBuyClose = Param(nameof(AllowBuyClose), true)
			.SetDisplay("Close Short", "Permit closing short positions.", "Permissions");

		_allowSellClose = Param(nameof(AllowSellClose), true)
			.SetDisplay("Close Long", "Permit closing long positions.", "Permissions");

		_mode = Param(nameof(Mode), SignalModes.Trend)
			.SetDisplay("Mode", "Closing style.", "Trading");
	}

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

	public int Length
	{
		get => _length.Value;
		set => _length.Value = value;
	}

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

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}


	public bool AllowBuyOpen
	{
		get => _allowBuyOpen.Value;
		set => _allowBuyOpen.Value = value;
	}

	public bool AllowSellOpen
	{
		get => _allowSellOpen.Value;
		set => _allowSellOpen.Value = value;
	}

	public bool AllowBuyClose
	{
		get => _allowBuyClose.Value;
		set => _allowBuyClose.Value = value;
	}

	public bool AllowSellClose
	{
		get => _allowSellClose.Value;
		set => _allowSellClose.Value = value;
	}

	public SignalModes Mode
	{
		get => _mode.Value;
		set => _mode.Value = value;
	}

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

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

		_rsiFast?.Reset();
		_rsiSlow?.Reset();
		_cciFast?.Reset();
		_cciSlow?.Reset();
		_prevSignal = -1;
	}

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

		var rsi = new RelativeStrengthIndex { Length = Length };
		var cci = new CommodityChannelIndex { Length = Length };

		_rsiFast = new SimpleMovingAverage { Length = FastPeriod };
		_rsiSlow = new SimpleMovingAverage { Length = SlowPeriod };
		_cciFast = new SimpleMovingAverage { Length = FastPeriod };
		_cciSlow = new SimpleMovingAverage { Length = SlowPeriod };

		_prevSignal = -1;

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var rsiFast = _rsiFast.Process(new DecimalIndicatorValue(_rsiFast, rsiValue, candle.OpenTime)).ToDecimal();
		var rsiSlow = _rsiSlow.Process(new DecimalIndicatorValue(_rsiSlow, rsiValue, candle.OpenTime)).ToDecimal();
		var cciFast = _cciFast.Process(new DecimalIndicatorValue(_cciFast, cciValue, candle.OpenTime)).ToDecimal();
		var cciSlow = _cciSlow.Process(new DecimalIndicatorValue(_cciSlow, cciValue, candle.OpenTime)).ToDecimal();

		int signal;
		if (rsiFast > rsiSlow && cciFast > cciSlow && cciValue > 0m)
			signal = 2;
		else if (rsiFast < rsiSlow && cciFast < cciSlow && cciValue < 0m)
			signal = 0;
		else
			signal = 1;

		if (signal == 2)
		{
			if (AllowSellClose && Position < 0)
				BuyMarket(Math.Abs(Position));

			if (AllowBuyOpen && Position <= 0 && _prevSignal != 2)
				BuyMarket(Volume + Math.Abs(Position));
		}
		else if (signal == 0)
		{
			if (AllowBuyClose && Position > 0)
				SellMarket(Position);

			if (AllowSellOpen && Position >= 0 && _prevSignal != 0)
				SellMarket(Volume + Math.Abs(Position));
		}
		else if (Mode == SignalModes.Flat)
		{
			if (AllowBuyClose && Position > 0)
				SellMarket(Position);
			if (AllowSellClose && Position < 0)
				BuyMarket(Math.Abs(Position));
		}

		_prevSignal = signal;
	}
}