Estrategia Vwap Cci
Implementación de la estrategia - VWAP + CCI. Compra cuando el precio está por debajo del VWAP y el CCI está por debajo de -100 (sobreventa). Vende cuando el precio está por encima del VWAP y el CCI está por encima de 100 (sobrecompra).
Las pruebas indican un rendimiento anual promedio de aproximadamente 82%. Funciona mejor en el mercado de acciones.
El VWAP actúa como referencia de valor, y el CCI destaca los movimientos de impulso que se alejan de él. Las entradas favorecen lecturas de CCI fuertes en relación con el VWAP.
Diseñado para traders intradía que se centran en la interacción con el VWAP. Los stops de ATR ayudan a mantener la disciplina.
Detalles
- Criterios de entrada:
- Largo:
Close < VWAP && CCI < CciOversold - Corto:
Close > VWAP && CCI > CciOverbought
- Largo:
- Largo/Corto: Ambos
- Criterios de salida:
- El precio cruza de regreso a través del VWAP
- Stops: Basados en porcentaje usando
StopLoss - Valores predeterminados:
CciPeriod= 20CciOversold= -100mCciOverbought= 100mStopLoss= new Unit(2, UnitTypes.Percent)CandleType= TimeSpan.FromMinutes(5).TimeFrame()
- Filtros:
- Categoría: Reversión a la media
- Dirección: Ambos
- Indicadores: VWAP, CCI
- Stops: Sí
- Complejidad: Intermedio
- Marco temporal: Medio plazo
- 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;
using StockSharp.Algo;
using StockSharp.Algo.Candles;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Implementation of strategy - VWAP + CCI.
/// Buy when price is below VWAP and CCI is below -100 (oversold).
/// Sell when price is above VWAP and CCI is above 100 (overbought).
/// </summary>
public class VwapCciStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _cciOversold;
private readonly StrategyParam<decimal> _cciOverbought;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<Unit> _stopLoss;
private readonly StrategyParam<DataType> _candleType;
private int _cooldown;
/// <summary>
/// CCI period.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// CCI oversold level.
/// </summary>
public decimal CciOversold
{
get => _cciOversold.Value;
set => _cciOversold.Value = value;
}
/// <summary>
/// CCI overbought level.
/// </summary>
public decimal CciOverbought
{
get => _cciOverbought.Value;
set => _cciOverbought.Value = value;
}
/// <summary>
/// Bars to wait between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Stop-loss value.
/// </summary>
public Unit StopLoss
{
get => _stopLoss.Value;
set => _stopLoss.Value = value;
}
/// <summary>
/// Candle type used for strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="VwapCciStrategy"/>.
/// </summary>
public VwapCciStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "Period for Commodity Channel Index", "CCI Parameters");
_cciOversold = Param(nameof(CciOversold), -20m)
.SetDisplay("CCI Oversold", "CCI level to consider market oversold", "CCI Parameters");
_cciOverbought = Param(nameof(CciOverbought), 20m)
.SetDisplay("CCI Overbought", "CCI level to consider market overbought", "CCI Parameters");
_cooldownBars = Param(nameof(CooldownBars), 120)
.SetRange(5, 500)
.SetDisplay("Cooldown Bars", "Bars between trades", "General");
_stopLoss = Param(nameof(StopLoss), new Unit(2, UnitTypes.Percent))
.SetDisplay("Stop Loss", "Stop loss percent or value", "Risk Management");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
var vwap = new VolumeWeightedMovingAverage();
var cci = new CommodityChannelIndex { Length = CciPeriod };
// Setup candle subscription
var subscription = SubscribeCandles(CandleType);
// Bind indicators to candles
subscription
.Bind(vwap, cci, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, vwap);
// Create separate area for CCI
var cciArea = CreateChartArea();
if (cciArea != null)
{
DrawIndicator(cciArea, cci);
}
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal vwapValue, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Current price
var price = candle.ClosePrice;
// Determine if price is above or below VWAP
var isPriceAboveVWAP = price > vwapValue;
LogInfo($"Candle: {candle.OpenTime}, Close: {price}, " +
$"VWAP: {vwapValue}, Price > VWAP: {isPriceAboveVWAP}, " +
$"CCI: {cciValue}");
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Trading rules
var belowVwap = price <= vwapValue * 1.001m;
var aboveVwap = price >= vwapValue * 0.999m;
if (belowVwap && cciValue <= CciOversold && Position == 0)
{
// Buy signal - price below VWAP and CCI oversold
BuyMarket();
_cooldown = CooldownBars;
LogInfo($"Buy signal: Price below VWAP and CCI oversold ({cciValue} <= {CciOversold}).");
}
else if (aboveVwap && cciValue >= CciOverbought && Position == 0)
{
// Sell signal - price above VWAP and CCI overbought
SellMarket();
_cooldown = CooldownBars;
LogInfo($"Sell signal: Price above VWAP and CCI overbought ({cciValue} >= {CciOverbought}).");
}
// Exit conditions
else if (isPriceAboveVWAP && Position > 0)
{
// Exit long position when price crosses above VWAP
SellMarket();
_cooldown = CooldownBars;
LogInfo($"Exit long: Price crossed above VWAP. Position: {Position}");
}
else if (!isPriceAboveVWAP && Position < 0)
{
// Exit short position when price crosses below VWAP
BuyMarket();
_cooldown = CooldownBars;
LogInfo($"Exit short: Price crossed below VWAP. Position: {Position}");
}
}
}
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, Unit, UnitTypes, CandleStates
from StockSharp.Algo.Indicators import VolumeWeightedMovingAverage, CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class vwap_cci_strategy(Strategy):
"""
Implementation of strategy - VWAP + CCI.
Buy when price is below VWAP and CCI is below -20 (oversold).
Sell when price is above VWAP and CCI is above 20 (overbought).
"""
def __init__(self):
super(vwap_cci_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("CCI Period", "Period for Commodity Channel Index", "CCI Parameters")
self._cci_oversold = self.Param("CciOversold", -20.0) \
.SetDisplay("CCI Oversold", "CCI level to consider market oversold", "CCI Parameters")
self._cci_overbought = self.Param("CciOverbought", 20.0) \
.SetDisplay("CCI Overbought", "CCI level to consider market overbought", "CCI Parameters")
self._cooldown_bars = self.Param("CooldownBars", 120) \
.SetRange(5, 500) \
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._stop_loss = self.Param("StopLoss", Unit(2, UnitTypes.Percent)) \
.SetDisplay("Stop Loss", "Stop loss percent or value", "Risk Management")
self._candle_type = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Candle type for strategy", "General")
self._cooldown = 0
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def CciOversold(self):
return self._cci_oversold.Value
@CciOversold.setter
def CciOversold(self, value):
self._cci_oversold.Value = value
@property
def CciOverbought(self):
return self._cci_overbought.Value
@CciOverbought.setter
def CciOverbought(self, value):
self._cci_overbought.Value = value
@property
def CooldownBars(self):
return self._cooldown_bars.Value
@CooldownBars.setter
def CooldownBars(self, value):
self._cooldown_bars.Value = value
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(vwap_cci_strategy, self).OnReseted()
self._cooldown = 0
def OnStarted2(self, time):
super(vwap_cci_strategy, self).OnStarted2(time)
# Create indicators
vwap = VolumeWeightedMovingAverage()
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
# Setup candle subscription
subscription = self.SubscribeCandles(self.CandleType)
# Bind indicators to candles
subscription.Bind(vwap, cci, self.ProcessCandle).Start()
# Setup chart visualization if available
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, vwap)
cci_area = self.CreateChartArea()
if cci_area is not None:
self.DrawIndicator(cci_area, cci)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, vwap_value, cci_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
# Current price
price = float(candle.ClosePrice)
vwap_val = float(vwap_value)
# Determine if price is above or below VWAP
isPriceAboveVWAP = price > vwap_val
if self._cooldown > 0:
self._cooldown -= 1
return
# Trading rules - with tolerance bands like CS
belowVwap = price <= vwap_val * 1.001
aboveVwap = price >= vwap_val * 0.999
if belowVwap and cci_value <= self.CciOversold and self.Position == 0:
# Buy signal - price below VWAP and CCI oversold
self.BuyMarket()
self._cooldown = self.CooldownBars
elif aboveVwap and cci_value >= self.CciOverbought and self.Position == 0:
# Sell signal - price above VWAP and CCI overbought
self.SellMarket()
self._cooldown = self.CooldownBars
# Exit conditions
elif isPriceAboveVWAP and self.Position > 0:
# Exit long position when price crosses above VWAP
self.SellMarket()
self._cooldown = self.CooldownBars
elif not isPriceAboveVWAP and self.Position < 0:
# Exit short position when price crosses below VWAP
self.BuyMarket()
self._cooldown = self.CooldownBars
def CreateClone(self):
return vwap_cci_strategy()