A estratégia KWAN CCC reproduz o especialista MetaTrader Exp_KWAN_CCC.mq5 usando a API de alto nível do StockSharp. O sistema deriva sinais de trading de um oscilador personalizado construído da seguinte forma:
Calcular o oscilador Chaikin (diferença entre as médias móveis rápida e lenta da linha de acumulação/distribuição).
Multiplicar o valor Chaikin pelo Commodity Channel Index (CCI).
Dividir o resultado pelo valor do indicador Momentum. Quando o Momentum é zero, o script substitui um valor constante de 100 para evitar divisão por zero, exatamente como o código original.
Suavizar a série resultante com o método XMA selecionado pelo usuário.
Detectar a inclinação da série suavizada. Barras em alta são coloridas com 0, barras em queda com 2, caso contrário 1.
Quando a cor muda de 0 para qualquer outra coisa, a estratégia fecha posições vendidas e abre uma posição comprada. Quando a cor muda de 2 para qualquer outra coisa, fecha posições compradas e abre uma vendida. Isso reflete a lógica implementada no especialista MQL, incluindo o deslocamento de sinal opcional (SignalBar).
Regras de trading
Entrada comprada: a cor na barra em SignalBar + 1 é igual a 0 e a barra em SignalBar é diferente de 0.
Entrada vendida: a cor na barra em SignalBar + 1 é igual a 2 e a barra em SignalBar é diferente de 2.
Saída comprada: habilitada quando EnableLongExits = true e a condição de entrada vendida é acionada.
Saída vendida: habilitada quando EnableShortExits = true e a condição de entrada comprada é acionada.
As ordens de stop protetor e alvo são criadas através de StartProtection usando deslocamentos de preço absolutos derivados de StopLossPoints e TakeProfitPoints multiplicados pelo PriceStep do instrumento.
Parâmetros
Parâmetro
Descrição
OrderVolume
Tamanho de ordem base usado ao abrir uma nova posição.
CandleType
Período para todos os cálculos de indicadores. O padrão é 1 hora.
FastPeriod / SlowPeriod
Comprimentos das médias móveis dentro do oscilador Chaikin.
ChaikinMethod
Tipo de média móvel (simples, exponencial, suavizada, ponderada) aplicada à linha de acumulação/distribuição.
CciPeriod
Período do Commodity Channel Index.
MomentumPeriod
Período do indicador Momentum.
SmoothingMethod
Método de suavização XMA mapeado das opções originais. JurX, Parabolic e T3 recorrem ao Jurik MA; Vidya usa suavização adaptativa baseada no Oscilador de Momentum de Chande; Adaptive usa Kaufman AMA.
SmoothingLength
Número de barras usadas pelo filtro de suavização selecionado.
SmoothingPhase
Parâmetro adicional usado por métodos específicos (p. ex., comprimento CMO de VIDYA, período lento de AMA).
SignalBar
Deslocamento (em barras completadas) usado para avaliar as transições de cor. 1 reproduz o padrão do MetaTrader.
EnableLongEntries / EnableShortEntries
Permitir ou bloquear a abertura de novas posições na direção correspondente.
EnableLongExits / EnableShortExits
Permitir ou bloquear o fechamento de posições impulsionado pelo indicador.
StopLossPoints / TakeProfitPoints
Stop protetor/alvo medido em passos de preço (definir como zero para desabilitar).
Notas de implementação
A estratégia age apenas em velas terminadas e usa o helper Bind do StockSharp para transmitir dados de velas para os indicadores.
A lista de métodos de suavização reflete a implementação XMA da biblioteca original. Métodos não disponíveis no StockSharp são mapeados para a alternativa mais próxima, conforme indicado na tabela de parâmetros.
A entrada VolumeType do MetaTrader é omitida porque as velas do StockSharp já encapsulam as informações de volume total usadas pela linha de acumulação/distribuição.
O gerenciamento de dinheiro no especialista original dependia de helpers personalizados de dimensionamento de lotes. A conversão assume um volume fixo especificado por OrderVolume.
Dicas de uso
Certifique-se de que o instrumento forneça dados de volume significativos se o comportamento do oscilador Chaikin for importante. Para instrumentos ilíquidos, considere aumentar MomentumPeriod para reduzir o ruído.
Ao otimizar os parâmetros de suavização, combine SmoothingLength e SmoothingPhase com cuidado: combinações extremas podem atrasar os sinais consideravelmente.
Os valores protetores padrão (StopLossPoints = 1000, TakeProfitPoints = 2000) correspondem a grandes deslocamentos. Ajuste-os para corresponder ao tamanho do tick do instrumento.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Strategy converted from the KWAN_CCC expert advisor.
/// Uses CCI and Momentum to detect trend transitions.
/// Enters long when CCI turns up while momentum is positive,
/// enters short when CCI turns down while momentum is negative.
/// </summary>
public class KwanCccStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private decimal _prevCci;
private decimal _prevClose;
private bool _initialized;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
public KwanCccStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for calculations", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI length", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = 0m;
_prevClose = 0m;
_initialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCci = 0m;
_prevClose = 0m;
_initialized = false;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(cci, (ICandleMessage candle, decimal cciValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (!_initialized)
{
_prevCci = cciValue;
_prevClose = candle.ClosePrice;
_initialized = true;
return;
}
var closeUp = candle.ClosePrice > _prevClose;
var closeDown = candle.ClosePrice < _prevClose;
// Buy when CCI crosses into positive territory and price confirms the move.
if (_prevCci <= 0m && cciValue > 0m && closeUp && Position <= 0)
{
BuyMarket();
}
// Sell when CCI crosses into negative territory and price confirms the move.
else if (_prevCci >= 0m && cciValue < 0m && closeDown && Position >= 0)
{
SellMarket();
}
_prevCci = cciValue;
_prevClose = candle.ClosePrice;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, cci);
DrawOwnTrades(area);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class kwan_ccc_strategy(Strategy):
def __init__(self):
super(kwan_ccc_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for calculations", "General")
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI length", "Indicators")
self._prev_cci = 0.0
self._prev_close = 0.0
self._initialized = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def CciPeriod(self):
return self._cci_period.Value
def OnReseted(self):
super(kwan_ccc_strategy, self).OnReseted()
self._prev_cci = 0.0
self._prev_close = 0.0
self._initialized = False
def OnStarted2(self, time):
super(kwan_ccc_strategy, self).OnStarted2(time)
self._prev_cci = 0.0
self._prev_close = 0.0
self._initialized = False
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(cci, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, cci)
self.DrawOwnTrades(area)
def _on_process(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
cv = float(cci_value)
close = float(candle.ClosePrice)
if not self._initialized:
self._prev_cci = cv
self._prev_close = close
self._initialized = True
return
close_up = close > self._prev_close
close_down = close < self._prev_close
if self._prev_cci <= 0 and cv > 0 and close_up and self.Position <= 0:
self.BuyMarket()
elif self._prev_cci >= 0 and cv < 0 and close_down and self.Position >= 0:
self.SellMarket()
self._prev_cci = cv
self._prev_close = close
def CreateClone(self):
return kwan_ccc_strategy()