VIDYA Auto-Trading (Reversal Logic) 策略
本策略使用 VIDYA 移动平均和宽 ATR 通道。 价格上破上轨时做多,下破下轨时做空。
细节
- 入场条件: 价格穿越 VIDYA 的 ATR 通道
- 多空方向: 双向
- 出场条件: 反向突破
- 止损: 无
- 默认值:
VidyaLength= 10VidyaMomentum= 20BandDistance= 2
- 过滤器:
- 分类: 趋势
- 方向: 双向
- 指标: VIDYA, ATR
- 止损: 无
- 复杂度: 基础
- 时间框架: 日内
- 季节性: 否
- 神经网络: 否
- 背离: 否
- 风险等级: 中等
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()