Триггер по VIX
Стратегия реагирует на изменения индекса волатильности VIX. Рост VIX сигнализирует страх и возможные развороты базового инструмента. Система сравнивает направление VIX с положением цены относительно скользящей средней.
Тестирование показывает среднегодичную доходность около 148%. Стратегию лучше запускать на рынке Форекс.
Когда VIX растёт и цена ниже средней, открывается длинная позиция в ожидании восстановления. Напротив, растущий VIX при цене выше средней предполагает короткую позицию.
Позиции закрываются при снижении VIX или достижении стоп-процента.
Подробности
- Условия входа: рост VIX и положение цены относительно MA задают лонг или шорт.
- Длинные/короткие позиции: обе стороны.
- Условия выхода: снижение VIX или стоп.
- Стопы: да.
- Значения по умолчанию:
MAPeriod= 20StopLossPercent= 2.0mCandleType= TimeSpan.FromMinutes(5)
- Фильтры:
- Категория: Contrarian
- Направление: обе стороны
- Индикаторы: VIX, MA
- Стопы: да
- Сложность: средняя
- Таймфрейм: внутридневной
- Сезонность: нет
- Нейросети: нет
- Дивергенция: нет
- Уровень риска: средний
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using Ecng.ComponentModel;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that trades based on VIX (Volatility Index) movements.
/// It enters positions when VIX is rising (indicating increasing fear/volatility in the market)
/// and price is moving in an expected direction relative to its moving average.
/// </summary>
public class VixTriggerStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<Security> _vixSecurity;
private decimal _prevVix;
// Latest VIX value and trend flags
private decimal _latestVix;
private bool _isVixRising;
/// <summary>
/// Period for Moving Average calculation (default: 20)
/// </summary>
public int MAPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Stop-loss as percentage from entry price (default: 2%)
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Type of candles used for strategy calculation
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// VIX Security (required)
/// </summary>
public Security VixSecurity
{
get => _vixSecurity.Value;
set => _vixSecurity.Value = value;
}
/// <summary>
/// Initialize the VIX Trigger strategy
/// </summary>
public VixTriggerStrategy()
{
_maPeriod = Param(nameof(MAPeriod), 20)
.SetDisplay("MA Period", "Period for Moving Average calculation", "Technical Parameters")
.SetOptimize(10, 50, 5);
_stopLossPercent = Param(nameof(StopLossPercent), 2.0m)
.SetDisplay("Stop Loss %", "Stop loss as percentage from entry price", "Risk Management")
.SetOptimize(1.0m, 5.0m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "Data");
_vixSecurity = Param<Security>(nameof(VixSecurity))
.SetDisplay("VIX Security", "VIX Security to use for signals", "Data")
.SetRequired();
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
// We need both the primary security and VIX
return
[
(Security, CandleType),
(VixSecurity, CandleType)
];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
// Reset state variables
_prevVix = 0;
_latestVix = 0;
_isVixRising = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicator
var sma = new SMA { Length = MAPeriod };
// Create subscriptions
var mainSubscription = SubscribeCandles(CandleType);
var vixSubscription = SubscribeCandles(CandleType, security: VixSecurity);
// Bind indicator to main security candles
mainSubscription
.Bind(sma, ProcessMainCandle)
.Start();
// Process VIX candles separately
vixSubscription
.Bind(ProcessVixCandle)
.Start();
// Configure chart
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, mainSubscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
// Setup protection with stop-loss
StartProtection(
new Unit(0), // No take profit
new Unit(StopLossPercent, UnitTypes.Percent) // Stop loss as percentage of entry price
);
}
/// <summary>
/// Process VIX candle to track VIX movements
/// </summary>
private void ProcessVixCandle(ICandleMessage candle)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Store latest VIX value
_latestVix = candle.ClosePrice;
// Initialize _prevVix on first VIX candle
if (_prevVix == 0)
{
_prevVix = _latestVix;
return;
}
// Check if VIX is rising
_isVixRising = _latestVix > _prevVix;
// Update previous VIX value
_prevVix = _latestVix;
}
/// <summary>
/// Process main security candle and check for trading signals
/// </summary>
private void ProcessMainCandle(ICandleMessage candle, decimal smaValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Check if strategy is ready to trade
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Check if we have received VIX data
if (_prevVix == 0)
return;
// Determine price position relative to MA
bool isPriceBelowMA = candle.ClosePrice < smaValue;
if (Position == 0)
{
// No position - check for entry signals
if (_isVixRising && isPriceBelowMA)
{
// VIX is rising and price is below MA - buy (contrarian strategy)
BuyMarket(Volume);
}
else if (_isVixRising && !isPriceBelowMA)
{
// VIX is rising and price is above MA - sell (contrarian strategy)
SellMarket(Volume);
}
}
else if (Position > 0)
{
// Long position - check for exit signal
if (!_isVixRising)
{
// VIX is decreasing - exit long
SellMarket(Position);
}
}
else if (Position < 0)
{
// Short position - check for exit signal
if (!_isVixRising)
{
// VIX is decreasing - exit short
BuyMarket(Math.Abs(Position));
}
}
}
}
import clr
clr.AddReference("System.Drawing")
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.BusinessEntities")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from System.Drawing import Color
from StockSharp.Messages import UnitTypes, Unit, DataType, ICandleMessage, CandleStates, Sides
from StockSharp.Algo.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
from StockSharp.BusinessEntities import Security, Subscription
from datatype_extensions import *
class vix_trigger_strategy(Strategy):
"""
Strategy that trades based on VIX (Volatility Index) movements.
It enters positions when VIX is rising (indicating increasing fear/volatility in the market)
and price is moving in an expected direction relative to its moving average.
"""
def __init__(self):
super(vix_trigger_strategy, self).__init__()
# Initialize internal state
self._prevVix = 0
self._latestVix = 0
self._isVixRising = False
# Initialize strategy parameters
self._maPeriod = self.Param("MAPeriod", 20) \
.SetDisplay("MA Period", "Period for Moving Average calculation", "Technical Parameters")
self._stopLossPercent = self.Param("StopLossPercent", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss as percentage from entry price", "Risk Management")
self._candleType = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Type of candles to use", "Data")
self._vixSecurity = self.Param[Security]("VixSecurity", None) \
.SetDisplay("VIX Security", "VIX Security to use for signals", "Data")
@property
def MAPeriod(self):
return self._maPeriod.Value
@MAPeriod.setter
def MAPeriod(self, value):
self._maPeriod.Value = value
@property
def StopLossPercent(self):
return self._stopLossPercent.Value
@StopLossPercent.setter
def StopLossPercent(self, value):
self._stopLossPercent.Value = value
@property
def CandleType(self):
return self._candleType.Value
@CandleType.setter
def CandleType(self, value):
self._candleType.Value = value
@property
def VixSecurity(self):
return self._vixSecurity.Value
@VixSecurity.setter
def VixSecurity(self, value):
self._vixSecurity.Value = value
def OnReseted(self):
"""
Resets internal state when strategy is reset.
"""
super(vix_trigger_strategy, self).OnReseted()
self._prevVix = 0
self._latestVix = 0
self._isVixRising = False
def OnStarted2(self, time):
"""
Called when the strategy starts. Sets up indicators, subscriptions, and charting.
:param time: The time when the strategy started.
"""
super(vix_trigger_strategy, self).OnStarted2(time)
# Create indicator
sma = SimpleMovingAverage()
sma.Length = self.MAPeriod
# Create subscriptions
mainSubscription = self.SubscribeCandles(self.CandleType)
vixSubscription = self.SubscribeCandles(self.CandleType, self.VixSecurity)
# Bind indicator to main security candles
mainSubscription.Bind(sma, self.ProcessMainCandle).Start()
# Process VIX candles separately
vixSubscription.Bind(self.ProcessVixCandle).Start()
# Configure chart if GUI is available
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, mainSubscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
# Setup protection with stop-loss
self.StartProtection(
takeProfit=Unit(0, UnitTypes.Absolute),
stopLoss=Unit(self.StopLossPercent, UnitTypes.Percent)
)
def ProcessVixCandle(self, candle):
"""
Process VIX candle to track VIX movements
:param candle: The VIX candle message.
"""
# Skip unfinished candles
if candle.State != CandleStates.Finished:
return
# Store latest VIX value
self._latestVix = float(candle.ClosePrice)
# Initialize _prevVix on first VIX candle
if self._prevVix == 0:
self._prevVix = self._latestVix
return
# Check if VIX is rising
self._isVixRising = self._latestVix > self._prevVix
# Update previous VIX value
self._prevVix = self._latestVix
def ProcessMainCandle(self, candle, smaValue):
"""
Process main security candle and check for trading signals
:param candle: The main security candle message.
:param smaValue: The current SMA value.
"""
# Skip unfinished candles
if candle.State != CandleStates.Finished:
return
# Check if strategy is ready to trade
# Check if we have received VIX data
if self._prevVix == 0:
return
# Determine price position relative to MA
isPriceBelowMA = candle.ClosePrice < smaValue
if self.Position == 0:
# No position - check for entry signals
if self._isVixRising and isPriceBelowMA:
# VIX is rising and price is below MA - buy (contrarian strategy)
self.BuyMarket(self.Volume)
elif self._isVixRising and not isPriceBelowMA:
# VIX is rising and price is above MA - sell (contrarian strategy)
self.SellMarket(self.Volume)
elif self.Position > 0:
# Long position - check for exit signal
if not self._isVixRising:
# VIX is decreasing - exit long
self.SellMarket(self.Position)
elif self.Position < 0:
# Short position - check for exit signal
if not self._isVixRising:
# VIX is decreasing - exit short
self.BuyMarket(Math.Abs(self.Position))
def CreateClone(self):
"""
!! REQUIRED!! Creates a new instance of the strategy.
"""
return vix_trigger_strategy()