Estrategia VIDYA de Auto-Trading (Lógica de Reversión)
Esta estrategia aplica una media dinámica variable VIDYA con bandas ATR amplias. Se abre una operación larga cuando el precio rompe por encima de la banda superior, y una operación corta cuando el precio rompe por debajo de la banda inferior.
Detalles
- Criterios de entrada: el precio cruza la banda ATR alrededor de VIDYA
- Largo/Corto: Ambos
- Criterios de salida: ruptura de banda opuesta
- Stops: No
- Valores predeterminados:
VidyaLength= 10VidyaMomentum= 20BandDistance= 2
- Filtros:
- Categoría: Tendencia
- Dirección: Ambos
- Indicadores: VIDYA, ATR
- Stops: No
- Complejidad: Básico
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// VIDYA Auto-Trading strategy based on reversal logic.
/// Uses Variable Index Dynamic Average with ATR bands and reverses on band breakouts.
/// </summary>
public class VidyaAutoTradingReversalLogicStrategy : Strategy
{
private readonly StrategyParam<int> _vidyaLength;
private readonly StrategyParam<int> _vidyaMomentum;
private readonly StrategyParam<decimal> _bandDistance;
private readonly StrategyParam<DataType> _candleType;
private decimal? _vidya;
private decimal _prevUpper;
private decimal _prevLower;
private decimal _prevClose;
private int _cooldown;
public int VidyaLength { get => _vidyaLength.Value; set => _vidyaLength.Value = value; }
public int VidyaMomentum { get => _vidyaMomentum.Value; set => _vidyaMomentum.Value = value; }
public decimal BandDistance { get => _bandDistance.Value; set => _bandDistance.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public VidyaAutoTradingReversalLogicStrategy()
{
_vidyaLength = Param(nameof(VidyaLength), 10)
.SetGreaterThanZero()
.SetDisplay("VIDYA Length", "Length of VIDYA", "General");
_vidyaMomentum = Param(nameof(VidyaMomentum), 20)
.SetGreaterThanZero()
.SetDisplay("Momentum Length", "Length for momentum", "General");
_bandDistance = Param(nameof(BandDistance), 3m)
.SetDisplay("Band Distance", "ATR multiplier for bands", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_vidya = null;
_prevUpper = 0;
_prevLower = 0;
_prevClose = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var cmo = new ChandeMomentumOscillator { Length = VidyaMomentum };
var atr = new AverageTrueRange { Length = 14 };
_vidya = null;
_prevUpper = 0;
_prevLower = 0;
_prevClose = 0;
_cooldown = 0;
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cmo, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cmoValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (_cooldown > 0)
_cooldown--;
var alpha = 2m / (VidyaLength + 1);
var absCmo = Math.Abs(cmoValue);
var prev = _vidya ?? candle.ClosePrice;
_vidya = alpha * absCmo / 100m * candle.ClosePrice + (1 - alpha * absCmo / 100m) * prev;
var upper = _vidya.Value + atrValue * BandDistance;
var lower = _vidya.Value - atrValue * BandDistance;
if (_prevClose != 0 && _cooldown <= 0)
{
var trendCrossUp = _prevClose <= _prevUpper && candle.ClosePrice > upper;
var trendCrossDown = _prevClose >= _prevLower && candle.ClosePrice < lower;
if (trendCrossUp && Position <= 0)
{
BuyMarket();
_cooldown = 25;
}
else if (trendCrossDown && Position >= 0)
{
SellMarket();
_cooldown = 25;
}
}
_prevUpper = upper;
_prevLower = lower;
_prevClose = candle.ClosePrice;
}
}
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 AverageTrueRange, ChandeMomentumOscillator
from StockSharp.Algo.Strategies import Strategy
class vidya_auto_trading_reversal_logic_strategy(Strategy):
def __init__(self):
super(vidya_auto_trading_reversal_logic_strategy, self).__init__()
self._vidya_length = self.Param("VidyaLength", 10) \
.SetDisplay("VIDYA Length", "Length of VIDYA", "General")
self._vidya_momentum = self.Param("VidyaMomentum", 20) \
.SetDisplay("Momentum Length", "Length for momentum", "General")
self._band_distance = self.Param("BandDistance", 3.0) \
.SetDisplay("Band Distance", "ATR multiplier for bands", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._vidya = 0.0
self._prev_upper = 0.0
self._prev_lower = 0.0
self._prev_close = 0.0
self._cooldown = 0
@property
def vidya_length(self):
return self._vidya_length.Value
@property
def vidya_momentum(self):
return self._vidya_momentum.Value
@property
def band_distance(self):
return self._band_distance.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(vidya_auto_trading_reversal_logic_strategy, self).OnReseted()
self._vidya = 0.0
self._prev_upper = 0.0
self._prev_lower = 0.0
self._prev_close = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(vidya_auto_trading_reversal_logic_strategy, self).OnStarted2(time)
cmo = ChandeMomentumOscillator()
cmo.Length = self.vidya_momentum
atr = AverageTrueRange()
atr.Length = 14
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cmo, atr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, cmo_value, atr_value):
if candle.State != CandleStates.Finished:
return
cmo_value = float(cmo_value)
atr_value = float(atr_value)
close = float(candle.ClosePrice)
if self._cooldown > 0:
self._cooldown -= 1
alpha = 2.0 / (self.vidya_length + 1)
abs_cmo = abs(cmo_value)
prev = (self._vidya if self._vidya != 0.0 else close)
self._vidya = alpha * abs_cmo / 100.0 * close + (1 - alpha * abs_cmo / 100.0) * prev
upper = self._vidya + atr_value * float(self.band_distance)
lower = self._vidya - atr_value * float(self.band_distance)
if self._prev_close != 0 and self._cooldown <= 0:
trend_cross_up = self._prev_close <= self._prev_upper and close > upper
trend_cross_down = self._prev_close >= self._prev_lower and close < lower
if trend_cross_up and self.Position <= 0:
self.BuyMarket()
self._cooldown = 25
elif trend_cross_down and self.Position >= 0:
self.SellMarket()
self._cooldown = 25
self._prev_upper = upper
self._prev_lower = lower
self._prev_close = close
def CreateClone(self):
return vidya_auto_trading_reversal_logic_strategy()