Estratégia de Rompimento de Volatilidade
A estratégia de Rompimento de Volatilidade busca movimentos direcionais fortes quando o preço escapa de seu intervalo médio. Medindo a distância de uma média móvel simples usando o ATR, o algoritmo define limiares de rompimento que escalam com a volatilidade.
Os testes indicam um retorno anual médio de aproximadamente 97%. Funciona melhor no mercado de criptomoedas.
Uma ordem de compra é acionada quando o fechamento sobe acima da SMA em mais de Multiplier vezes o ATR. Um sinal de venda aparece quando o fechamento cai abaixo da SMA pela mesma distância. As posições permanecem abertas até que um rompimento oposto ocorra ou um stop de proteção seja atingido.
Esta técnica atende traders intradia que prosperam com surtos de momentum. O uso de limiares baseados em ATR ajuda a filtrar o ruído para que apenas movimentos significativos gerem operações.
Detalhes
- Critérios de entrada:
- Comprado: Close > SMA + Multiplier * ATR
- Vendido: Close < SMA - Multiplier * ATR
- Comprado/Vendido: Ambos os lados.
- Critérios de saída:
- Comprado: Sair quando um rompimento oposto for acionado ou o stop-loss for atingido
- Vendido: Sair quando um rompimento oposto for acionado ou o stop-loss for atingido
- Stops: Sim, stop-loss a
Multiplier * ATR da entrada.
- Valores padrão:
Period = 20
Multiplier = 2.0m
CandleType = TimeSpan.FromMinutes(5)
- Filtros:
- Categoria: Rompimento
- Direção: Ambos
- Indicadores: SMA, ATR
- Stops: Sim
- Complexidade: Intermediário
- Período: Intradiário
- Sazonalidade: Não
- Redes neurais: Não
- Divergência: Não
- Nível de risco: Médio
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()