Connors VIX Umkehr III
Konträre Strategie, die VIX-Spitzen relativ zu seinem gleitenden Durchschnitt nutzt. Sie kauft, wenn der VIX um einen festgelegten Prozentsatz über den Durchschnitt springt, und geht short, wenn der VIX darunter fällt.
Positionen werden geschlossen, wenn der VIX den gleitenden Durchschnitt des Vortages kreuzt.
Details
- Einstiegskriterien: VIX-Tief über MA und Schlusskurs über MA um Schwellenwert für Käufe; VIX-Hoch unter MA und Schlusskurs unter Schwellenwert für Verkäufe.
- Long/Short: Beide.
- Ausstiegskriterien: VIX kreuzt den gestrigen MA.
- Stops: Nein.
- Standardwerte:
LengthMA= 10PercentThreshold= 10mCandleType= TimeSpan.FromDays(1)
- Filter:
- Kategorie: Konträr
- Richtung: Beide
- Indikatoren: VIX, SMA
- Stops: Nein
- Komplexität: Grundlegend
- Zeitrahmen: Täglich
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Connors VIX Reversal III strategy.
/// The candles are the VIX series of the traded security. A bar whose low is above the LengthMA simple average and whose close is
/// PercentThreshold percent above it buys; a bar whose high is below the average and whose close is PercentThreshold percent below
/// it sells short. A long closes when the close falls below the previous bar's average and a short when it rises above it.
/// </summary>
public class ConnorsVixReversalIIIStrategy : Strategy
{
private readonly StrategyParam<int> _lengthMA;
private readonly StrategyParam<decimal> _percentThreshold;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevMa;
/// <summary>
/// Moving average length.
/// </summary>
public int LengthMA
{
get => _lengthMA.Value;
set => _lengthMA.Value = value;
}
/// <summary>
/// Distance from the average in percent that confirms a spike.
/// </summary>
public decimal PercentThreshold
{
get => _percentThreshold.Value;
set => _percentThreshold.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ConnorsVixReversalIIIStrategy()
{
_lengthMA = Param(nameof(LengthMA), 10)
.SetGreaterThanZero()
.SetDisplay("MA Length", "Moving average length", "Indicators");
_percentThreshold = Param(nameof(PercentThreshold), 10m)
.SetNotNegative()
.SetDisplay("Percent Threshold", "Distance from the average in percent that confirms a spike", "Signals");
_candleType = Param(nameof(CandleType), TimeSpan.FromDays(1).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();
_prevMa = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevMa = null;
var sma = new SimpleMovingAverage { Length = LengthMA };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!smaValue.IsFormed)
return;
var ma = smaValue.ToDecimal();
var prevMa = _prevMa;
_prevMa = ma;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var factor = PercentThreshold / 100m;
if (candle.LowPrice > ma && close > ma * (1m + factor) && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (candle.HighPrice < ma && close < ma * (1m - factor) && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (prevMa is decimal yesterdayMa)
{
if (Position > 0 && close < yesterdayMa)
SellMarket(Position);
else if (Position < 0 && close > yesterdayMa)
BuyMarket(-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, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class connors_vix_reversal_iii_strategy(Strategy):
"""
Connors VIX Reversal III strategy.
The candles are the VIX series of the traded security. A bar whose low is above the LengthMA simple average and whose close is
PercentThreshold percent above it buys; a bar whose high is below the average and whose close is PercentThreshold percent below
it sells short. A long closes when the close falls below the previous bar's average and a short when it rises above it.
"""
def __init__(self):
super(connors_vix_reversal_iii_strategy, self).__init__()
self._length_ma = self.Param("LengthMA", 10).SetGreaterThanZero().SetDisplay("MA Length", "Moving average length", "Indicators")
self._percent_threshold = self.Param("PercentThreshold", 10.0).SetNotNegative().SetDisplay("Percent Threshold", "Distance from the average in percent that confirms a spike", "Signals")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromDays(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_ma = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(connors_vix_reversal_iii_strategy, self).OnReseted()
self._prev_ma = None
def OnStarted2(self, time):
super(connors_vix_reversal_iii_strategy, self).OnStarted2(time)
self._prev_ma = None
sma = SimpleMovingAverage()
sma.Length = self._length_ma.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
if not sma_value.IsFormed:
return
ma = sma_value.GetValue[Decimal](None)
prev_ma = self._prev_ma
self._prev_ma = ma
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
factor = Decimal(self._percent_threshold.Value) / Decimal(100)
if candle.LowPrice > ma and close > ma * (Decimal(1) + factor) and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif candle.HighPrice < ma and close < ma * (Decimal(1) - factor) and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif prev_ma is not None:
if self.Position > 0 and close < prev_ma:
self.SellMarket(self.Position)
elif self.Position < 0 and close > prev_ma:
self.BuyMarket(-self.Position)
def CreateClone(self):
return connors_vix_reversal_iii_strategy()