Die Volatilitäts-Ausbruch-Strategie sucht nach starken gerichteten Bewegungen, wenn der Preis aus seinem durchschnittlichen Bereich ausbricht. Durch die Messung des Abstands von einem einfachen gleitenden Durchschnitt mithilfe des ATR definiert der Algorithmus Ausbruchsschwellen, die mit der Volatilität skalieren.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 97%. Sie funktioniert am besten auf dem Kryptomarkt.
Ein Kaufauftrag wird ausgelöst, wenn der Schlusskurs die SMA um mehr als Multiplier mal den ATR übersteigt. Ein Verkaufssignal erscheint, wenn der Schlusskurs um denselben Abstand unter die SMA fällt. Positionen bleiben offen, bis ein entgegengesetzter Ausbruch auftritt oder ein Schutz-Stop getroffen wird.
Diese Technik eignet sich für Intraday-Trader, die von Momentum-Schüben profitieren. ATR-basierte Schwellen helfen, Rauschen herauszufiltern, sodass nur signifikante Bewegungen Trades erzeugen.
Details
Einstiegskriterien:
Long: Close > SMA + Multiplier * ATR
Short: Close < SMA - Multiplier * ATR
Long/Short: Beide Seiten.
Ausstiegskriterien:
Long: Ausstieg, wenn ein entgegengesetzter Ausbruch ausgelöst wird oder Stop-Loss getroffen wird
Short: Ausstieg, wenn ein entgegengesetzter Ausbruch ausgelöst wird oder Stop-Loss getroffen wird
Stops: Ja, Stop-Loss bei Multiplier * ATR vom Einstieg.
Standardwerte:
Period = 20
Multiplier = 2.0m
CandleType = TimeSpan.FromMinutes(5)
Filter:
Kategorie: Ausbruch
Richtung: Beide
Indikatoren: SMA, ATR
Stops: Ja
Komplexität: Mittel
Zeitrahmen: Intraday
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Volatility Breakout strategy. Enters trades when price breaks out from average price with volatility threshold.
/// </summary>
public class VolatilityBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _periodParam;
private readonly StrategyParam<decimal> _multiplierParam;
private readonly StrategyParam<DataType> _candleTypeParam;
private SimpleMovingAverage _sma;
private AverageTrueRange _atr;
private decimal _prevSma;
private decimal _prevAtr;
/// <summary>
/// Period for SMA and ATR calculations.
/// </summary>
public int Period
{
get => _periodParam.Value;
set => _periodParam.Value = value;
}
/// <summary>
/// Volatility multiplier for breakout threshold.
/// </summary>
public decimal Multiplier
{
get => _multiplierParam.Value;
set => _multiplierParam.Value = value;
}
/// <summary>
/// Candle type for strategy.
/// </summary>
public DataType CandleType
{
get => _candleTypeParam.Value;
set => _candleTypeParam.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public VolatilityBreakoutStrategy()
{
_periodParam = Param(nameof(Period), 20)
.SetGreaterThanZero()
.SetDisplay("Period", "Period for SMA and ATR", "Parameters")
.SetOptimize(10, 50, 5);
_multiplierParam = Param(nameof(Multiplier), 2.0m)
.SetRange(0.1m, decimal.MaxValue)
.SetDisplay("Multiplier", "Volatility multiplier for breakout threshold", "Parameters")
.SetOptimize(1.0m, 3.0m, 0.5m);
_candleTypeParam = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "Common");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_sma = null;
_atr = null;
_prevSma = 0;
_prevAtr = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
_sma = new SMA { Length = Period };
_atr = new AverageTrueRange { Length = Period };
// Create subscription and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_sma, _atr, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _sma);
DrawOwnTrades(area);
}
// Enable position protection
StartProtection(
takeProfit: new Unit(0, UnitTypes.Absolute), // No take profit
stopLoss: new Unit(Multiplier, UnitTypes.Absolute) // Stop loss at 2*ATR
);
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Save values for the next candle
var currentSma = smaValue;
var currentAtr = atrValue;
// Skip first candle after indicators become formed
if (_prevSma == 0 || _prevAtr == 0)
{
_prevSma = currentSma;
_prevAtr = currentAtr;
return;
}
// Calculate volatility threshold
var threshold = Multiplier * currentAtr;
// Check for long setup - price breaks above SMA + threshold
if (candle.ClosePrice > currentSma + threshold && Position <= 0)
{
// Close any short position and open long
BuyMarket(Volume + Math.Abs(Position));
}
// Check for short setup - price breaks below SMA - threshold
else if (candle.ClosePrice < currentSma - threshold && Position >= 0)
{
// Close any long position and open short
SellMarket(Volume + Math.Abs(Position));
}
// Update previous values for next candle
_prevSma = currentSma;
_prevAtr = currentAtr;
}
}
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, UnitTypes, Unit, ICandleMessage, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class volatility_breakout_strategy(Strategy):
"""
Volatility Breakout strategy. Enters trades when price breaks out from average price with volatility threshold.
"""
def __init__(self):
super(volatility_breakout_strategy, self).__init__()
# Period for SMA and ATR calculations.
self._period_param = self.Param("Period", 20) \
.SetGreaterThanZero() \
.SetDisplay("Period", "Period for SMA and ATR", "Parameters") \
.SetCanOptimize(True) \
.SetOptimize(10, 50, 5)
# Volatility multiplier for breakout threshold.
self._multiplier_param = self.Param("Multiplier", 2.0) \
.SetRange(0.1, float('inf')) \
.SetDisplay("Multiplier", "Volatility multiplier for breakout threshold", "Parameters") \
.SetCanOptimize(True) \
.SetOptimize(1.0, 3.0, 0.5)
# Candle type for strategy.
self._candle_type_param = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Candle type for strategy", "Common")
# Indicators and state variables
self._sma = None
self._atr = None
self._prev_sma = 0.0
self._prev_atr = 0.0
@property
def Period(self):
"""Period for SMA and ATR calculations."""
return self._period_param.Value
@Period.setter
def Period(self, value):
self._period_param.Value = value
@property
def Multiplier(self):
"""Volatility multiplier for breakout threshold."""
return self._multiplier_param.Value
@Multiplier.setter
def Multiplier(self, value):
self._multiplier_param.Value = value
@property
def CandleType(self):
"""Candle type for strategy."""
return self._candle_type_param.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type_param.Value = value
def GetWorkingSecurities(self):
"""See base class for details."""
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(volatility_breakout_strategy, self).OnReseted()
self._sma = None
self._atr = None
self._prev_sma = 0.0
self._prev_atr = 0.0
def OnStarted2(self, time):
"""Called when the strategy starts."""
super(volatility_breakout_strategy, self).OnStarted2(time)
# Create indicators
self._sma = SimpleMovingAverage()
self._sma.Length = self.Period
self._atr = AverageTrueRange()
self._atr.Length = self.Period
# Create subscription and bind indicators
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._sma, self._atr, self.ProcessCandle).Start()
# Setup chart visualization if available
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._sma)
self.DrawOwnTrades(area)
# Enable position protection
self.StartProtection(
takeProfit=Unit(0, UnitTypes.Absolute),
stopLoss=Unit(self.Multiplier, UnitTypes.Absolute)
)
def ProcessCandle(self, candle, sma_value, atr_value):
"""Process candle with SMA and ATR values."""
# Skip unfinished candles
if candle.State != CandleStates.Finished:
return
# Save values for the next candle
current_sma = sma_value
current_atr = atr_value
# Skip first candle after indicators become formed
if self._prev_sma == 0 or self._prev_atr == 0:
self._prev_sma = current_sma
self._prev_atr = current_atr
return
# Calculate volatility threshold
threshold = self.Multiplier * current_atr
# Check for long setup - price breaks above SMA + threshold
if candle.ClosePrice > current_sma + threshold and self.Position <= 0:
# Close any short position and open long
self.BuyMarket(self.Volume + Math.Abs(self.Position))
# Check for short setup - price breaks below SMA - threshold
elif candle.ClosePrice < current_sma - threshold and self.Position >= 0:
# Close any long position and open short
self.SellMarket(self.Volume + Math.Abs(self.Position))
# Update previous values for next candle
self._prev_sma = current_sma
self._prev_atr = current_atr
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return volatility_breakout_strategy()