Ver no GitHub

Estratégia AOCCI

Visão geral

A estratégia AOCCI é uma conversão direta do consultor especialista MetaTrader 4 "AOCCI". Ele combina filtros de impulso e reversão à média usando o Awesome Oscillator (AO) e o Commodity Channel Index (CCI) junto com um pivô diário. A versão convertida funciona no alto nível de StockSharp API e mantém a mesma lógica de proteção do script original.

Lógica

  1. Preparação de dados
    • Usa velas intradiárias (padrão 1 hora) para geração de sinal.
    • Usa velas diárias para calcular o pivô do dia anterior concluído (máxima + mínima + fechamento dividido por 3).
    • Rastreia os últimos seis preços de abertura intradiários para detectar grandes lacunas.
  2. Filtro de lacunas
    • Qualquer diferença de passo único que exceda o limite do Big Jump Filter cancela o sinal atual.
    • Qualquer diferença combinada de duas etapas que exceda o limite do Filtro de Salto Duplo também cancela o sinal.
  3. Verificações de indicadores
    • AO deve ser maior que zero e CCI deve ser não negativo na barra atual.
    • Pelo menos um dos seguintes itens deve ser verdadeiro na barra anterior: AO abaixo de zero, CCI igual ou inferior a zero ou preço abaixo do pivô.
  4. Filtro direcional
    • O preço de fechamento deve permanecer acima do nível pivô.
  5. Pedidos
    • O consultor especialista original só abre negociações longas porque a condição curta duplica a lógica longa. A conversão mantém esse comportamento.
    • As ordens de mercado usam o Volume de Ordens configurado.
  6. Proteção
    • O stop loss e o take-profit iniciais são expressos em etapas de preço.
    • O trailing stop opcional estreita o stop quando o preço se move a favor da posição em pelo menos a distância final.

Parâmetros

Nome Descrição
CciPeriod Período para o Commodity Channel Index (padrão 55).
SignalCandleOffset Compensação adicional aplicada ao fazer referência a velas diárias históricas (padrão 0).
StopLossPoints Distância de stop-loss em etapas de preço.
TakeProfitPoints Distância de lucro em etapas de preço.
TrailingStopPoints Distância do trailing stop em etapas de preço (0 desativa o trailing).
BigJumpPoints Gap máximo permitido de abertura de barra única expresso em etapas de preço.
DoubleJumpPoints Gap máximo permitido combinado de duas barras expresso em etapas de preço.
OrderVolume Volume utilizado no envio de ordens de mercado.
CandleType Tipo de vela intradiária (barras padrão de uma hora).
DailyCandleType Tipo de vela diária usado para cálculo de pivô.

Notas de uso

  • A estratégia requer assinaturas de dados intradiárias e diárias.
  • A etapa de preço (tamanho do tick) do título selecionado é usada para traduzir parâmetros de risco baseados em pontos em preços reais.
  • O gerenciamento de trailing stop é aplicado em velas concluídas, refletindo o comportamento do EA original.
  • Como a versão original MQL4 nunca aciona negociações curtas, a conversão mantém intencionalmente o mesmo conjunto de regras.
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>
/// AOCCI Pivot strategy - CCI crossover with momentum filter.
/// Buys when CCI crosses above 0 with positive momentum.
/// Sells when CCI crosses below 0 with negative momentum.
/// </summary>
public class AocciPivotFilterStrategy : Strategy
{
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<int> _momentumPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevCci;
	private bool _hasPrev;

	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public AocciPivotFilterStrategy()
	{
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetDisplay("CCI Period", "CCI period", "Indicators");

		_momentumPeriod = Param(nameof(MomentumPeriod), 10)
			.SetDisplay("Momentum Period", "Momentum period", "Indicators");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCci = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var mom = new Momentum { Length = MomentumPeriod };

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

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

		if (!_hasPrev)
		{
			_prevCci = cciValue;
			_hasPrev = true;
			return;
		}

		// CCI crosses above 0 with positive momentum
		if (_prevCci <= 0 && cciValue > 0 && momValue > 0 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// CCI crosses below 0 with negative momentum
		else if (_prevCci >= 0 && cciValue < 0 && momValue < 0 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevCci = cciValue;
	}
}