Die XRVI Crossover-Strategie basiert auf dem Extended Relative Vigor Index (XRVI).
Der XRVI wird berechnet, indem der Relative Vigor Index geglättet und anschließend ein zweiter gleitender Durchschnitt zur Erzeugung einer Signallinie angewendet wird.
Die Strategie geht Long, wenn der XRVI die Signallinie von unten kreuzt, und Short, wenn er sie von oben kreuzt.
Bestehende Positionen werden bei entgegengesetzten Signalen umgekehrt.
Details
Einstiegskriterien: XRVI-Kreuzung seiner Signallinie
Long/Short: Beide
Ausstiegskriterien: Entgegengesetzte Kreuzung
Stops: Nein
Standardwerte:
RviLength = 10
SignalLength = 5
CandleType = H4-Zeitrahmen
Filter:
Kategorie: Oszillator
Richtung: Beide
Indikatoren: Relative Vigor Index, Simple Moving Average
Stops: Nein
Komplexität: Grundlegend
Zeitrahmen: Intraday
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>
/// XRVI crossover strategy.
/// Buys when RVI Average crosses above Signal, sells when it crosses below.
/// </summary>
public class XrviCrossoverStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevAvg;
private decimal? _prevSig;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public XrviCrossoverStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevAvg = null;
_prevSig = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rvi = new RelativeVigorIndex();
SubscribeCandles(CandleType)
.BindEx(rvi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue rviValue)
{
if (candle.State != CandleStates.Finished)
return;
var value = (IRelativeVigorIndexValue)rviValue;
if (value.Average is not decimal avg || value.Signal is not decimal sig)
return;
if (_prevAvg is not null && _prevSig is not null)
{
var crossUp = _prevAvg <= _prevSig && avg > sig;
var crossDown = _prevAvg >= _prevSig && avg < sig;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prevAvg = avg;
_prevSig = sig;
}
}
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 RelativeVigorIndex
from StockSharp.Algo.Strategies import Strategy
class xrvi_crossover_strategy(Strategy):
def __init__(self):
super(xrvi_crossover_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_avg = None
self._prev_sig = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(xrvi_crossover_strategy, self).OnStarted2(time)
rvi = RelativeVigorIndex()
self.SubscribeCandles(self.CandleType) \
.BindEx(rvi, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, rvi_value):
if candle.State != CandleStates.Finished:
return
avg_raw = rvi_value.Average
sig_raw = rvi_value.Signal
if avg_raw is None or sig_raw is None:
return
avg = float(avg_raw)
sig = float(sig_raw)
if self._prev_avg is not None and self._prev_sig is not None:
cross_up = self._prev_avg <= self._prev_sig and avg > sig
cross_down = self._prev_avg >= self._prev_sig and avg < sig
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_avg = avg
self._prev_sig = sig
def OnReseted(self):
super(xrvi_crossover_strategy, self).OnReseted()
self._prev_avg = None
self._prev_sig = None
def CreateClone(self):
return xrvi_crossover_strategy()