Inicio
/
Ejemplos de estrategias
Ver en GitHub
Estrategia CCI VWAP
El enfoque CCI VWAP intenta capturar reversiones intradía cuando el momentum y el precio se alejan del precio promedio ponderado por volumen. Al observar el Índice de Canal de Materias Primas junto con el nivel VWAP, el sistema mide la fuerza de los movimientos recientes en relación con un punto de referencia de valor justo.
Las pruebas indican un rendimiento anual promedio de aproximadamente 70%. Funciona mejor en el mercado de acciones.
Una configuración de compra surge cuando el CCI cae por debajo de -100 y el mercado cotiza por debajo del VWAP, señalando que la presión vendedora puede estar agotada. Un corto ocurre cuando el CCI sube por encima de +100 con el precio sobre el VWAP, destacando un rally extendido vulnerable a una corrección. Las posiciones se cierran una vez que el precio recupera el VWAP en dirección opuesta.
Esta estrategia está diseñada para traders intradía que prefieren operar en los extremos pero aun así confían en niveles objetivos para las salidas. El stop-loss definido ayuda a gestionar el riesgo si el momentum no revierte rápidamente a la media.
Detalles
Criterios de entrada :
Largo : CCI < -100 && Price < VWAP (oversold below VWAP)
Corto : CCI > 100 && Price > VWAP (overbought above VWAP)
Largo/Corto : Ambos lados.
Criterios de salida :
Largo : Salir del largo cuando el precio suba por encima del VWAP
Corto : Salir del corto cuando el precio caiga por debajo del VWAP
Stops : Sí.
Valores predeterminados :
CciPeriod = 20
StopLossPercent = 2m
CandleType = TimeSpan.FromMinutes(5)
Filtros :
Categoría: Mixto
Dirección: Ambos
Indicadores: CCI VWAP
Stops: Sí
Complejidad: Intermedio
Marco temporal: Intradía
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>
/// Strategy that uses CCI and VWAP indicators to identify oversold and overbought conditions.
/// Enters long when CCI is below -100 and price is below VWAP.
/// Enters short when CCI is above 100 and price is above VWAP.
/// </summary>
public class CciVwapStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private CommodityChannelIndex _cci;
private int _cooldown;
private DateTime _vwapDate;
private decimal _vwapCumPv;
private decimal _vwapCumVol;
/// <summary>
/// CCI period parameter.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// Bars to wait between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Stop-loss percentage parameter.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type parameter.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Strategy constructor.
/// </summary>
public CciVwapStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("CCI period", "CCI indicator period", "Indicators")
.SetOptimize(10, 30, 5);
_cooldownBars = Param(nameof(CooldownBars), 60)
.SetRange(1, 200)
.SetDisplay("Cooldown Bars", "Bars between trades", "General");
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetGreaterThanZero()
.SetDisplay("Stop-loss %", "Stop-loss as percentage of entry price", "Risk Management")
.SetOptimize(1m, 3m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();
_cci = null;
_cooldown = 0;
_vwapDate = default;
_vwapCumPv = 0m;
_vwapCumVol = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Initialize CCI indicator
_cci = new CommodityChannelIndex
{
Length = CciPeriod
};
var dummyEma = new ExponentialMovingAverage { Length = 10 };
// Bind CCI to candle subscription
var candlesSubscription = SubscribeCandles(CandleType)
.Bind(_cci, dummyEma, ProcessCandle)
.Start();
// Setup chart if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, candlesSubscription);
DrawIndicator(area, _cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cci, decimal dummyValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
var date = candle.ServerTime.Date;
if (_vwapDate != date)
{
_vwapDate = date;
_vwapCumPv = 0m;
_vwapCumVol = 0m;
}
_vwapCumPv += candle.ClosePrice * candle.TotalVolume;
_vwapCumVol += candle.TotalVolume;
if (_vwapCumVol <= 0m)
return;
var currentVwap = _vwapCumPv / _vwapCumVol;
if (currentVwap == 0)
return;
if (_cooldown > 0)
_cooldown--;
// Long signal: CCI below -100 and price below VWAP
if (_cooldown == 0 && cci < -100 && candle.ClosePrice < currentVwap && Position <= 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (_cooldown == 0 && cci > 100 && candle.ClosePrice > currentVwap && Position >= 0)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && candle.ClosePrice > currentVwap)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice < currentVwap)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class cci_vwap_strategy(Strategy):
"""
CCI + VWAP strategy.
Enters long when CCI < -100 and price < VWAP.
Enters short when CCI > 100 and price > VWAP.
"""
def __init__(self):
super(cci_vwap_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 20) \
.SetDisplay("CCI period", "CCI indicator period", "Indicators")
self._cooldown_bars = self.Param("CooldownBars", 60) \
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle type", "Type of candles to use", "General")
self._cooldown = 0
self._vwap_date = None
self._vwap_cum_pv = 0.0
self._vwap_cum_vol = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cci_vwap_strategy, self).OnReseted()
self._cooldown = 0
self._vwap_date = None
self._vwap_cum_pv = 0.0
self._vwap_cum_vol = 0.0
def OnStarted2(self, time):
super(cci_vwap_strategy, self).OnStarted2(time)
cci = CommodityChannelIndex()
cci.Length = self._cci_period.Value
dummy_ema = ExponentialMovingAverage()
dummy_ema.Length = 10
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, dummy_ema, 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_val, dummy_val):
if candle.State != CandleStates.Finished:
return
date = candle.ServerTime.Date
if self._vwap_date != date:
self._vwap_date = date
self._vwap_cum_pv = 0.0
self._vwap_cum_vol = 0.0
self._vwap_cum_pv += float(candle.ClosePrice) * float(candle.TotalVolume)
self._vwap_cum_vol += float(candle.TotalVolume)
if self._vwap_cum_vol <= 0:
return
current_vwap = self._vwap_cum_pv / self._vwap_cum_vol
if current_vwap == 0:
return
if self._cooldown > 0:
self._cooldown -= 1
close = float(candle.ClosePrice)
if self._cooldown == 0 and cci_val < -100 and close < current_vwap and self.Position <= 0:
self.BuyMarket()
self._cooldown = self._cooldown_bars.Value
elif self._cooldown == 0 and cci_val > 100 and close > current_vwap and self.Position >= 0:
self.SellMarket()
self._cooldown = self._cooldown_bars.Value
elif self.Position > 0 and close > current_vwap:
self.SellMarket()
self._cooldown = self._cooldown_bars.Value
elif self.Position < 0 and close < current_vwap:
self.BuyMarket()
self._cooldown = self._cooldown_bars.Value
def CreateClone(self):
return cci_vwap_strategy()