Esta estrategia negocia puntos de giro en la volatilidad usando un indicador de desviación estándar. Interpreta los mínimos y máximos locales del indicador como posibles reversiones en la acción del precio. Cuando la desviación estándar forma un valle, el sistema espera que la volatilidad se expanda al alza y entra en una posición larga. Cuando aparece un pico, vende en corto anticipando una contracción de la volatilidad.
El enfoque está diseñado para operaciones tanto largas como cortas en un marco temporal de cuatro horas por defecto. No aplica órdenes de stop-loss, centrándose en cambio en salidas basadas en señales.
Detalles
Criterios de entrada:
Largo: El valor de la desviación estándar en la barra anterior es menor que sus vecinos (mínimo local).
Corto: El valor de la desviación estándar en la barra anterior es mayor que sus vecinos (máximo local).
Largo/Corto: Ambos.
Criterios de salida:
Una señal opuesta desencadena una reversión.
Stops: No.
Valores predeterminados:
StdDev Period = 9.
Candle Type = velas de 4 horas.
Filtros:
Categoría: Reversión a la media
Dirección: Ambos
Indicadores: Desviación estándar
Stops: No
Complejidad: Simple
Marco temporal: Medio plazo
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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>
/// Strategy based on standard deviation turning points.
/// Opens long at local minima and short at local maxima of the indicator.
/// </summary>
public class BezierStDevStrategy : Strategy
{
private readonly StrategyParam<int> _stdDevPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevValue1;
private decimal _prevValue2;
/// <summary>
/// Standard deviation calculation period.
/// </summary>
public int StdDevPeriod
{
get => _stdDevPeriod.Value;
set => _stdDevPeriod.Value = value;
}
/// <summary>
/// Type of candles used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public BezierStDevStrategy()
{
_stdDevPeriod = Param(nameof(StdDevPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("StdDev Period", "Period for standard deviation calculation", "General")
.SetOptimize(5, 20, 1);
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles used", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevValue1 = 0m;
_prevValue2 = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var stdDev = new StandardDeviation { Length = StdDevPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(stdDev, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, stdDev);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal stdDevValue)
{
// We only work with finished candles.
if (candle.State != CandleStates.Finished)
return;
// Ensure the strategy is ready for trading.
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Check for local minima and maxima at the previous value.
if (_prevValue2 != 0m)
{
var isLocalMin = _prevValue1 < _prevValue2 && _prevValue1 < stdDevValue;
var isLocalMax = _prevValue1 > _prevValue2 && _prevValue1 > stdDevValue;
if (isLocalMin)
{
if (Position <= 0)
BuyMarket();
}
else if (isLocalMax)
{
if (Position >= 0)
SellMarket();
}
}
// Shift stored values for next calculation.
_prevValue2 = _prevValue1;
_prevValue1 = stdDevValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class bezier_st_dev_strategy(Strategy):
def __init__(self):
super(bezier_st_dev_strategy, self).__init__()
self._std_dev_period = self.Param("StdDevPeriod", 9) \
.SetDisplay("StdDev Period", "Period for standard deviation calculation", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles used", "General")
self._prev_value1 = 0.0
self._prev_value2 = 0.0
@property
def std_dev_period(self):
return self._std_dev_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bezier_st_dev_strategy, self).OnReseted()
self._prev_value1 = 0.0
self._prev_value2 = 0.0
def OnStarted2(self, time):
super(bezier_st_dev_strategy, self).OnStarted2(time)
std_dev = StandardDeviation()
std_dev.Length = self.std_dev_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(std_dev, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, std_dev)
self.DrawOwnTrades(area)
def process_candle(self, candle, std_dev_value):
if candle.State != CandleStates.Finished:
return
std_dev_value = float(std_dev_value)
if self._prev_value2 != 0.0:
is_local_min = self._prev_value1 < self._prev_value2 and self._prev_value1 < std_dev_value
is_local_max = self._prev_value1 > self._prev_value2 and self._prev_value1 > std_dev_value
if is_local_min:
if self.Position <= 0:
self.BuyMarket()
elif is_local_max:
if self.Position >= 0:
self.SellMarket()
self._prev_value2 = self._prev_value1
self._prev_value1 = std_dev_value
def CreateClone(self):
return bezier_st_dev_strategy()