Diese Strategie handelt Wendepunkte in der Volatilität mithilfe eines Standardabweichungsindikators. Sie interpretiert lokale Minima und Maxima des Indikators als potenzielle Umkehrungen in der Preisbewegung. Wenn die Standardabweichung ein Tal bildet, erwartet das System eine Ausweitung der Volatilität nach oben und eröffnet eine Long-Position. Wenn ein Gipfel erscheint, wird eine Short-Position eröffnet in Erwartung einer Volatilitätskontraktion.
Der Ansatz ist standardmäßig für Long- und Short-Trades auf einem Vier-Stunden-Zeitrahmen ausgelegt. Er wendet keine Stop-Loss-Orders an und konzentriert sich stattdessen auf signalbasierte Ausstiege.
Details
Einstiegskriterien:
Long: Der Standardabweichungswert am vorherigen Balken ist niedriger als seine Nachbarn (lokales Minimum).
Short: Der Standardabweichungswert am vorherigen Balken ist höher als seine Nachbarn (lokales Maximum).
Long/Short: Beide.
Ausstiegskriterien:
Ein entgegengesetztes Signal löst eine Umkehr aus.
Stops: Nein.
Standardwerte:
StdDev Period = 9.
Candle Type = 4-Stunden-Kerzen.
Filter:
Kategorie: Mean Reversion
Richtung: Beide
Indikatoren: Standardabweichung
Stops: Nein
Komplexität: Einfach
Zeitrahmen: Mittelfristig
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>
/// 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()