Ver no GitHub

Estratégia Digital CCI Woodies

Esta estratégia opera no cruzamento de dois indicadores CCI (Índice de Canal de Commodities). Um CCI rápido reage rapidamente às mudanças de preço, enquanto um CCI lento suaviza o ruído do mercado. Os sinais são gerados quando a linha rápida cruza a lenta.

Detalhes

  • Critérios de entrada:
    • Comprado: o CCI rápido cruza acima do CCI lento.
    • Vendido: o CCI rápido cruza abaixo do CCI lento.
  • Comprado/Vendido: Ambos.
  • Critérios de saída:
    • As posições compradas são fechadas quando o CCI rápido cruza abaixo do CCI lento.
    • As posições vendidas são fechadas quando o CCI rápido cruza acima do CCI lento.
  • Stops: Não.
  • Valores padrão:
    • CandleType = velas de 6 horas
    • FastLength = 14
    • SlowLength = 6
    • BuyOpen = true
    • SellOpen = true
    • BuyClose = true
    • SellClose = true
  • Filtros:
    • Categoria: Seguidor de tendência
    • Direção: Ambos
    • Indicadores: CCI
    • Stops: Não
    • Complexidade: Baixo
    • Período: Qualquer
    • Sazonalidade: Não
    • Redes neurais: Não
    • Divergência: Não
    • Nível de risco: Médio
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;

namespace StockSharp.Samples.Strategies;



/// <summary>
/// Strategy based on crossover of fast and slow CCI indicators.
/// </summary>
public class DigitalCciWoodiesStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<bool> _buyOpen;
	private readonly StrategyParam<bool> _sellOpen;
	private readonly StrategyParam<bool> _buyClose;
	private readonly StrategyParam<bool> _sellClose;
	
	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _isFirst = true;
	
	/// <summary>
	/// Candle type.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}
	
	/// <summary>
	/// Fast CCI length.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}
	
	/// <summary>
	/// Slow CCI length.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}
	
	/// <summary>
	/// Allow long entries.
	/// </summary>
	public bool BuyOpen
	{
		get => _buyOpen.Value;
		set => _buyOpen.Value = value;
	}
	
	/// <summary>
	/// Allow short entries.
	/// </summary>
	public bool SellOpen
	{
		get => _sellOpen.Value;
		set => _sellOpen.Value = value;
	}
	
	/// <summary>
	/// Allow closing long positions.
	/// </summary>
	public bool BuyClose
	{
		get => _buyClose.Value;
		set => _buyClose.Value = value;
	}
	
	/// <summary>
	/// Allow closing short positions.
	/// </summary>
	public bool SellClose
	{
		get => _sellClose.Value;
		set => _sellClose.Value = value;
	}
	
	/// <summary>
	/// Initializes the strategy parameters.
	/// </summary>
	public DigitalCciWoodiesStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
		.SetDisplay("Candle Type", "Timeframe for candles", "General");
		
		_fastLength = Param(nameof(FastLength), 14)
		.SetGreaterThanZero()
		.SetDisplay("Fast CCI Length", "Length of the fast CCI", "Indicators")
		
		.SetOptimize(5, 30, 1);
		
		_slowLength = Param(nameof(SlowLength), 6)
		.SetGreaterThanZero()
		.SetDisplay("Slow CCI Length", "Length of the slow CCI", "Indicators")
		
		.SetOptimize(3, 20, 1);
		
		_buyOpen = Param(nameof(BuyOpen), true)
		.SetDisplay("Buy Open", "Allow long entries", "Trading");
		
		_sellOpen = Param(nameof(SellOpen), true)
		.SetDisplay("Sell Open", "Allow short entries", "Trading");
		
		_buyClose = Param(nameof(BuyClose), true)
		.SetDisplay("Buy Close", "Allow closing longs", "Trading");
		
		_sellClose = Param(nameof(SellClose), true)
		.SetDisplay("Sell Close", "Allow closing shorts", "Trading");
	}
	
	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}
	
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = default;
		_prevSlow = default;
		_isFirst = true;
	}
	
	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		
		var fastCci = new CommodityChannelIndex { Length = FastLength };
		var slowCci = new CommodityChannelIndex { Length = SlowLength };
		
		var subscription = SubscribeCandles(CandleType);
		subscription
		.Bind(fastCci, slowCci, ProcessCandle)
		.Start();
		
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
		
		var indicatorArea = CreateChartArea();
		if (indicatorArea != null)
		{
			DrawIndicator(indicatorArea, fastCci);
			DrawIndicator(indicatorArea, slowCci);
		}
		
	}
	
	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		// Skip unfinished candles
		if (candle.State != CandleStates.Finished)
		return;
		
		// Ensure trading is allowed
		if (!IsFormedAndOnlineAndAllowTrading())
		return;
		
		if (_isFirst)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_isFirst = false;
			return;
		}
		
		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;
		
		if (crossUp)
		{
			if (Position < 0 && SellClose)
				BuyMarket();
			if (BuyOpen && Position <= 0)
				BuyMarket();
		}
		else if (crossDown)
		{
			if (Position > 0 && BuyClose)
				SellMarket();
			if (SellOpen && Position >= 0)
				SellMarket();
		}
		else
		{
			if (fast > slow && SellClose && Position < 0)
				BuyMarket();
			if (fast < slow && BuyClose && Position > 0)
				SellMarket();
		}
		
		_prevFast = fast;
		_prevSlow = slow;
	}
}