Converte o MetaTrader 4 consultor especialista "Anubis" para o StockSharp API de alto nível.
Usa um filtro de índice de canais de commodities (CCI) de 4 horas junto com um cruzamento MACD de 15 minutos.
Aplica dimensionamento de posição adaptável, stop-loss, proteção de equilíbrio, saídas orientadas por ATR e um take-profit baseado no desvio padrão.
Lógica estratégica
Dados
Período principal: velas de 15 minutos (SignalCandleType), usadas para cálculos de MACD e ATR.
Prazo maior: velas de 4 horas (TrendCandleType), usadas para filtragem CCI e medição de desvio padrão.
Indicadores
CommodityChannelIndex com período configurável na série 4H.
StandardDeviation (comprimento 30) em 4H fecha para estimar a distância de realização do lucro.
MovingAverageConvergenceDivergenceSignal (rápido/lento/sinal configurável) em velas de 15 milhões.
AverageTrueRange (comprimento 12) em velas de 15 milhões para saídas baseadas em volatilidade.
Inscrições
Venda: quando 4H CCI está acima de CciThreshold, os dois valores anteriores de MACD mostram um cruzamento de baixa (MACD cruzando abaixo de seu sinal), MACD foi positivo, não há posições compradas abertas e o preço se moveu pelo menos PriceFilterPoints desde a última entrada vendida.
Longo: condição simétrica com CCI abaixo de -CciThreshold, MACD cruzando para cima enquanto negativo, sem posições curtas abertas e o filtro de distância mínima satisfeito.
Gerenciamento de riscos
O volume base é definido por VolumeValue e é dimensionado pelo patrimônio da conta (2× acima de 14k, 3,2× acima de 22k) e por LossFactor após uma negociação perdedora.
O máximo de negociações simultâneas por direção é limitado por MaxLongTrades e MaxShortTrades.
Stop-loss rígido colocado virtualmente em StopLossPoints * PriceStep do preço médio de entrada.
O ponto de equilíbrio é ativado quando o preço avança BreakevenPoints e fecha imediatamente a posição se o preço retornar à entrada.
Saídas
O take-profit de desvio padrão fecha a posição quando o preço se move StdDevMultiplier * StdDev a favor.
As saídas agressivas são acionadas quando o intervalo da vela anterior excede CloseAtrMultiplier * ATR.
As saídas de desaceleração MACD exigem lucro suficiente (ProfitThresholdPoints) e uma reversão na inclinação MACD (MACD anterior menor ou maior que duas barras atrás, dependendo da direção).
O stop protetor fecha a negociação se o preço ultrapassar a distância do stop loss ou voltar à entrada após a ativação do ponto de equilíbrio.
Parâmetros
Nome
Descrição
VolumeValue
Volume básico do pedido.
CciThreshold
Limite absoluto para o filtro 4H CCI.
CciPeriod
Período do indicador 4H CCI.
StopLossPoints
Distância de stop-loss em pontos.
BreakevenPoints
Lucre em pontos necessários para armar o ponto de equilíbrio.
MacdFastPeriod
Período rápido de EMA para MACD.
MacdSlowPeriod
Período EMA lenta para MACD.
MacdSignalPeriod
Período de sinal EMA para MACD.
LossFactor
Multiplicador de volume aplicado após uma negociação perdida.
MaxShortTrades
Número máximo de entradas curtas simultâneas.
MaxLongTrades
Número máximo de entradas longas simultâneas.
CloseAtrMultiplier
Multiplicador de ATR para saídas antecipadas.
ProfitThresholdPoints
Buffer de lucro adicional (pontos) antes da saída de MACD.
StdDevMultiplier
Multiplicador de desvio padrão para o take-profit.
PriceFilterPoints
Movimento do preço mínimo entre entradas consecutivas.
SignalCandleType
Período principal para MACD e ATR.
TrendCandleType
Prazo maior para CCI e desvio padrão.
Notas
A estratégia depende de metadados Security.PriceStep válidos para traduzir parâmetros baseados em pontos em distâncias de preços.
A lógica de proteção é implementada por meio de verificações explícitas em vez de ordens pendentes de stop/limit, espelhando o comportamento original EA com paradas virtuais.
A versão Python é omitida intencionalmente de acordo com as instruções da tarefa.
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>
/// Anubis CCI + MACD strategy.
/// Buys when CCI crosses above 0 and MACD histogram is positive.
/// Sells when CCI crosses below 0 and MACD histogram is negative.
/// </summary>
public class AnubisCciMacdStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevCci;
private bool _hasPrev;
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AnubisCciMacdStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetDisplay("CCI Period", "CCI lookback 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 macd = new MovingAverageConvergenceDivergenceSignal();
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(cci, macd, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue cciValue, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!cciValue.IsFinal || !macdValue.IsFinal)
return;
var cci = cciValue.ToDecimal();
var macdVal = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
if (macdVal.Macd is not decimal macd || macdVal.Signal is not decimal signal)
return;
var histogram = macd - signal;
if (!_hasPrev)
{
_prevCci = cci;
_hasPrev = true;
return;
}
// CCI crosses above 0 with bullish MACD
if (_prevCci <= 0 && cci > 0 && histogram > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// CCI crosses below 0 with bearish MACD
else if (_prevCci >= 0 && cci < 0 && histogram < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevCci = cci;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import CommodityChannelIndex, MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class anubis_cci_macd_strategy(Strategy):
"""Anubis CCI + MACD strategy.
Buys when CCI crosses above 0 and MACD histogram is positive.
Sells when CCI crosses below 0 and MACD histogram is negative."""
def __init__(self):
super(anubis_cci_macd_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI lookback period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_cci = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
def OnReseted(self):
super(anubis_cci_macd_strategy, self).OnReseted()
self._prev_cci = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(anubis_cci_macd_strategy, self).OnStarted2(time)
self._has_prev = False
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
macd = MovingAverageConvergenceDivergenceSignal()
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(cci, macd, self._process_candle).Start()
def _process_candle(self, candle, cci_value, macd_value):
if candle.State != CandleStates.Finished:
return
if not cci_value.IsFinal or not macd_value.IsFinal:
return
cci = float(cci_value)
macd_raw = macd_value.Macd if hasattr(macd_value, 'Macd') else None
signal_raw = macd_value.Signal if hasattr(macd_value, 'Signal') else None
if macd_raw is None or signal_raw is None:
return
histogram = float(macd_raw) - float(signal_raw)
if not self._has_prev:
self._prev_cci = cci
self._has_prev = True
return
# CCI crosses above 0 with bullish MACD
if self._prev_cci <= 0 and cci > 0 and histogram > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# CCI crosses below 0 with bearish MACD
elif self._prev_cci >= 0 and cci < 0 and histogram < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_cci = cci
def CreateClone(self):
return anubis_cci_macd_strategy()