Estrategia de Histograma CCI
Esta estrategia utiliza el Índice de Canal de Materias Primas (CCI) para detectar reversiones cuando el indicador abandona zonas extremas. Se abre una posición larga cuando el CCI cae por debajo del nivel superior después de haber estado por encima. Se abre una posición corta cuando el CCI sube por encima del nivel inferior después de haber estado por debajo. Niveles opcionales de stop loss y take profit en puntos pueden proteger las posiciones abiertas.
Detalles
- Criterios de entrada:
- Largo: CCI anterior >
UpperLevely CCI actual ≤UpperLevel. - Corto: CCI anterior <
LowerLevely CCI actual ≥LowerLevel.
- Largo: CCI anterior >
- Largo/Corto: Ambos.
- Criterios de salida: La señal opuesta cierra la posición existente y abre una nueva.
- Stops: Stop loss y take profit fijos opcionales en puntos.
- Valores predeterminados:
CCI Period= 14Upper Level= 100Lower Level= -100Stop Loss= 100 puntosTake Profit= 200 puntos
- Filtros:
- Categoría: Reversión
- Dirección: Ambos
- Indicadores: CCI
- Stops: Opcional
- Complejidad: Simple
- Marco temporal: Cualquiera (por defecto 4H)
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// CCI Histogram reversal strategy.
/// Buys when CCI leaves the upper extreme and sells when it leaves the lower extreme.
/// Optional stop loss and take profit protection in points.
/// </summary>
public class CciHistogramStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _upperLevel;
private readonly StrategyParam<decimal> _lowerLevel;
private readonly StrategyParam<decimal> _stopLossPoints;
private readonly StrategyParam<decimal> _takeProfitPoints;
private readonly StrategyParam<bool> _useStopLoss;
private readonly StrategyParam<bool> _useTakeProfit;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevCci;
/// <summary>
/// CCI period length.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// Upper CCI level that defines overbought zone.
/// </summary>
public decimal UpperLevel
{
get => _upperLevel.Value;
set => _upperLevel.Value = value;
}
/// <summary>
/// Lower CCI level that defines oversold zone.
/// </summary>
public decimal LowerLevel
{
get => _lowerLevel.Value;
set => _lowerLevel.Value = value;
}
/// <summary>
/// Stop loss in absolute points.
/// </summary>
public decimal StopLossPoints
{
get => _stopLossPoints.Value;
set => _stopLossPoints.Value = value;
}
/// <summary>
/// Take profit in absolute points.
/// </summary>
public decimal TakeProfitPoints
{
get => _takeProfitPoints.Value;
set => _takeProfitPoints.Value = value;
}
/// <summary>
/// Use stop loss protection.
/// </summary>
public bool UseStopLoss
{
get => _useStopLoss.Value;
set => _useStopLoss.Value = value;
}
/// <summary>
/// Use take profit protection.
/// </summary>
public bool UseTakeProfit
{
get => _useTakeProfit.Value;
set => _useTakeProfit.Value = value;
}
/// <summary>
/// Candle type to process.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="CciHistogramStrategy"/> class.
/// </summary>
public CciHistogramStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "Period length for the CCI indicator", "General")
.SetOptimize(7, 28, 7);
_upperLevel = Param(nameof(UpperLevel), 100m)
.SetDisplay("Upper Level", "Upper CCI level", "General")
.SetOptimize(80m, 120m, 10m);
_lowerLevel = Param(nameof(LowerLevel), -100m)
.SetDisplay("Lower Level", "Lower CCI level", "General")
.SetOptimize(-120m, -80m, 10m);
_stopLossPoints = Param(nameof(StopLossPoints), 100m)
.SetDisplay("Stop Loss", "Stop loss in points", "Risk Management")
.SetOptimize(50m, 200m, 25m);
_takeProfitPoints = Param(nameof(TakeProfitPoints), 200m)
.SetDisplay("Take Profit", "Take profit in points", "Risk Management")
.SetOptimize(50m, 300m, 25m);
_useStopLoss = Param(nameof(UseStopLoss), false)
.SetDisplay("Enable Stop Loss", "Use stop loss protection", "Risk Management");
_useTakeProfit = Param(nameof(UseTakeProfit), false)
.SetDisplay("Enable Take Profit", "Use take profit protection", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
var isInitialized = false;
subscription
.Bind(cci,
(candle, cciValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevCci = cciValue;
isInitialized = true;
return;
}
if (!isInitialized)
{
_prevCci = cciValue;
isInitialized = true;
return;
}
if (_prevCci > UpperLevel && cciValue <= UpperLevel && Position <= 0)
{
BuyMarket();
}
else if (_prevCci < LowerLevel && cciValue >= LowerLevel && Position >= 0)
{
SellMarket();
}
_prevCci = cciValue;
})
.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 cci_histogram_strategy(Strategy):
def __init__(self):
super(cci_histogram_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "Period length for the CCI indicator", "General")
self._upper_level = self.Param("UpperLevel", 100.0) \
.SetDisplay("Upper Level", "Upper CCI level", "General")
self._lower_level = self.Param("LowerLevel", -100.0) \
.SetDisplay("Lower Level", "Lower CCI level", "General")
self._stop_loss_points = self.Param("StopLossPoints", 100.0) \
.SetDisplay("Stop Loss", "Stop loss in points", "Risk Management")
self._take_profit_points = self.Param("TakeProfitPoints", 200.0) \
.SetDisplay("Take Profit", "Take profit in points", "Risk Management")
self._use_stop_loss = self.Param("UseStopLoss", False) \
.SetDisplay("Enable Stop Loss", "Use stop loss protection", "Risk Management")
self._use_take_profit = self.Param("UseTakeProfit", False) \
.SetDisplay("Enable Take Profit", "Use take profit protection", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_cci = 0.0
self._initialized = False
@property
def cci_period(self):
return self._cci_period.Value
@property
def upper_level(self):
return self._upper_level.Value
@property
def lower_level(self):
return self._lower_level.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cci_histogram_strategy, self).OnReseted()
self._prev_cci = 0.0
self._initialized = False
def OnStarted2(self, time):
super(cci_histogram_strategy, self).OnStarted2(time)
cci = CommodityChannelIndex()
cci.Length = self.cci_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, cci)
self.DrawOwnTrades(area)
def process_candle(self, candle, cci_val):
if candle.State != CandleStates.Finished:
return
cci_val = float(cci_val)
if not self._initialized:
self._prev_cci = cci_val
self._initialized = True
return
upper = float(self.upper_level)
lower = float(self.lower_level)
if self._prev_cci > upper and cci_val <= upper and self.Position <= 0:
self.BuyMarket()
elif self._prev_cci < lower and cci_val >= lower and self.Position >= 0:
self.SellMarket()
self._prev_cci = cci_val
def CreateClone(self):
return cci_histogram_strategy()