Stochasticブレイクアウト戦略
このブレイクアウトアプローチは、Stochasticオシレーターが最近の平均から急激に動くことを監視します。%Kラインがボラティリティ調整された閾値を上下にブレイクすると、トレンドを開始する可能性のあるモメンタムの爆発を示します。
テストでは平均年間リターンが約181%であることが示されています。暗号資産市場で最も良いパフォーマンスを発揮します。
%Kが収縮期間後に上部閾値を上回ったときにロングポジションが発動されます。%Kが下部閾値を下回ったときにショートポジションが取られます。オシレーターが平均値に向かって戻るか保護的なストップに達したら取引を決済します。
この戦略はモメンタムスイングへの早期エントリーを望むイントラデイトレーダー向けに設計されています。ボラティリティベースのバンドを使用することでノイズを排除し、決定的な動きのみがシグナルを生成します。
詳細
- エントリー条件:
- ロング: %K > Avg + DeviationMultiplier * StdDev
- ショート: %K < Avg - DeviationMultiplier * StdDev
- ロング/ショート: 両方。
- エグジット条件:
- ロング: %K < Avg のときに決済
- ショート: %K > Avg のときに決済
- ストップ: あり、パーセントストップロス。
- デフォルト値:
StochasticPeriod= 14KPeriod= 3DPeriod= 3LookbackPeriod= 20DeviationMultiplier= 2.0mCandleType= TimeSpan.FromMinutes(5)
- フィルター:
- カテゴリ: ブレイクアウト
- 方向: 両方
- インジケーター: Stochastic Oscillator
- ストップ: あり
- 複雑さ: 中級
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// Stochastic Breakout Strategy.
/// This strategy identifies breakouts based on the Stochastic oscillator values compared to their historical average.
/// </summary>
public class StochasticBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _stochasticPeriod;
private readonly StrategyParam<int> _kPeriod;
private readonly StrategyParam<int> _dPeriod;
private readonly StrategyParam<int> _lookbackPeriod;
private readonly StrategyParam<decimal> _deviationMultiplier;
private readonly StrategyParam<DataType> _candleType;
private StochasticOscillator _stochastic;
private SimpleMovingAverage _stochAverage;
private StandardDeviation _stochStdDev;
private decimal _prevStochValue;
private decimal _prevStochAverage;
private decimal _prevStochStdDev;
/// <summary>
/// Stochastic oscillator period.
/// </summary>
public int StochasticPeriod
{
get => _stochasticPeriod.Value;
set => _stochasticPeriod.Value = value;
}
/// <summary>
/// Stochastic %K smoothing period.
/// </summary>
public int KPeriod
{
get => _kPeriod.Value;
set => _kPeriod.Value = value;
}
/// <summary>
/// Stochastic %D smoothing period.
/// </summary>
public int DPeriod
{
get => _dPeriod.Value;
set => _dPeriod.Value = value;
}
/// <summary>
/// Lookback period for calculating the average and standard deviation.
/// </summary>
public int LookbackPeriod
{
get => _lookbackPeriod.Value;
set => _lookbackPeriod.Value = value;
}
/// <summary>
/// Deviation multiplier for breakout detection.
/// </summary>
public decimal DeviationMultiplier
{
get => _deviationMultiplier.Value;
set => _deviationMultiplier.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public StochasticBreakoutStrategy()
{
_stochasticPeriod = Param(nameof(StochasticPeriod), 14)
.SetDisplay("Stochastic Period", "Stochastic oscillator period", "Stochastic")
.SetOptimize(5, 30, 5);
_kPeriod = Param(nameof(KPeriod), 3)
.SetDisplay("K Period", "Stochastic %K smoothing period", "Stochastic")
.SetOptimize(1, 5, 1);
_dPeriod = Param(nameof(DPeriod), 3)
.SetDisplay("D Period", "Stochastic %D smoothing period", "Stochastic")
.SetOptimize(1, 5, 1);
_lookbackPeriod = Param(nameof(LookbackPeriod), 20)
.SetDisplay("Lookback Period", "Lookback period for calculating the average and standard deviation", "Breakout")
.SetOptimize(10, 50, 5);
_deviationMultiplier = Param(nameof(DeviationMultiplier), 2.0m)
.SetDisplay("Deviation Multiplier", "Deviation multiplier for breakout detection", "Breakout")
.SetOptimize(1.0m, 3.0m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevStochValue = 0;
_prevStochAverage = 0;
_prevStochStdDev = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Initialize indicators
_stochastic = new StochasticOscillator
{
K = { Length = StochasticPeriod },
D = { Length = DPeriod },
};
_stochAverage = new SMA { Length = LookbackPeriod };
_stochStdDev = new StandardDeviation { Length = LookbackPeriod };
Indicators.Add(_stochastic);
// Create subscription and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _stochastic);
DrawOwnTrades(area);
}
// Start position protection
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(2, UnitTypes.Percent)
);
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var stochResult = _stochastic.Process(candle);
if (!_stochastic.IsFormed)
return;
var stochTyped = (StochasticOscillatorValue)stochResult;
if (stochTyped.K is not decimal stochK)
return;
// Calculate average and standard deviation of stochastic
var stochAvgValue = _stochAverage.Process(new DecimalIndicatorValue(_stochAverage, stochK, candle.ServerTime) { IsFinal = true }).ToDecimal();
var tempStdDevValue = _stochStdDev.Process(new DecimalIndicatorValue(_stochStdDev, stochK, candle.ServerTime) { IsFinal = true }).ToDecimal();
if (!_stochAverage.IsFormed || !_stochStdDev.IsFormed)
{
_prevStochValue = stochK;
_prevStochAverage = stochAvgValue;
_prevStochStdDev = tempStdDevValue;
return;
}
// First values initialization - skip trading decision
if (_prevStochValue == 0)
{
_prevStochValue = stochK;
_prevStochAverage = stochAvgValue;
_prevStochStdDev = tempStdDevValue;
return;
}
// Calculate breakout thresholds
var upperThreshold = _prevStochAverage + _prevStochStdDev * DeviationMultiplier;
var lowerThreshold = _prevStochAverage - _prevStochStdDev * DeviationMultiplier;
// Buy when stochastic breaks above upper threshold
if (stochK > upperThreshold && _prevStochValue <= upperThreshold && Position == 0)
{
BuyMarket();
}
// Sell when stochastic breaks below lower threshold
else if (stochK < lowerThreshold && _prevStochValue >= lowerThreshold && Position == 0)
{
SellMarket();
}
// Store current values for next comparison
_prevStochValue = stochK;
_prevStochAverage = stochAvgValue;
_prevStochStdDev = tempStdDevValue;
}
}
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, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import StochasticOscillator, SimpleMovingAverage, StandardDeviation, StochasticOscillatorValue
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
from indicator_extensions import *
class stochastic_breakout_strategy(Strategy):
"""
Stochastic Breakout Strategy.
This strategy identifies breakouts based on the Stochastic oscillator values compared to their historical average.
"""
def __init__(self):
super(stochastic_breakout_strategy, self).__init__()
# Initialize strategy parameters
self._stochasticPeriod = self.Param("StochasticPeriod", 14) \
.SetDisplay("Stochastic Period", "Stochastic oscillator period", "Stochastic")
self._kPeriod = self.Param("KPeriod", 3) \
.SetDisplay("K Period", "Stochastic %K smoothing period", "Stochastic")
self._dPeriod = self.Param("DPeriod", 3) \
.SetDisplay("D Period", "Stochastic %D smoothing period", "Stochastic")
self._lookbackPeriod = self.Param("LookbackPeriod", 20) \
.SetDisplay("Lookback Period", "Lookback period for calculating the average and standard deviation", "Breakout")
self._deviationMultiplier = self.Param("DeviationMultiplier", 2.0) \
.SetDisplay("Deviation Multiplier", "Deviation multiplier for breakout detection", "Breakout")
self._candleType = self.Param("CandleType", tf(5)) \
.SetDisplay("Candle Type", "Candle type for strategy", "General")
# Internal indicators and state
self._stochastic = None
self._stochAverage = None
self._stochStdDev = None
self._prevStochValue = 0
self._prevStochAverage = 0
self._prevStochStdDev = 0
@property
def StochasticPeriod(self):
"""Stochastic oscillator period."""
return self._stochasticPeriod.Value
@StochasticPeriod.setter
def StochasticPeriod(self, value):
self._stochasticPeriod.Value = value
@property
def KPeriod(self):
"""Stochastic %K smoothing period."""
return self._kPeriod.Value
@KPeriod.setter
def KPeriod(self, value):
self._kPeriod.Value = value
@property
def DPeriod(self):
"""Stochastic %D smoothing period."""
return self._dPeriod.Value
@DPeriod.setter
def DPeriod(self, value):
self._dPeriod.Value = value
@property
def LookbackPeriod(self):
"""Lookback period for calculating the average and standard deviation."""
return self._lookbackPeriod.Value
@LookbackPeriod.setter
def LookbackPeriod(self, value):
self._lookbackPeriod.Value = value
@property
def DeviationMultiplier(self):
"""Deviation multiplier for breakout detection."""
return self._deviationMultiplier.Value
@DeviationMultiplier.setter
def DeviationMultiplier(self, value):
self._deviationMultiplier.Value = value
@property
def CandleType(self):
"""Candle type."""
return self._candleType.Value
@CandleType.setter
def CandleType(self, value):
self._candleType.Value = value
def GetWorkingSecurities(self):
"""!! REQUIRED!! Return securities and candle types used."""
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(stochastic_breakout_strategy, self).OnReseted()
self._prevStochValue = 0
self._prevStochAverage = 0
self._prevStochStdDev = 0
def OnStarted2(self, time):
"""Called when the strategy starts."""
super(stochastic_breakout_strategy, self).OnStarted2(time)
# Initialize indicators
self._stochastic = StochasticOscillator()
self._stochastic.K.Length = self.StochasticPeriod
self._stochastic.D.Length = self.DPeriod
self._stochAverage = SimpleMovingAverage()
self._stochAverage.Length = self.LookbackPeriod
self._stochStdDev = StandardDeviation()
self._stochStdDev.Length = self.LookbackPeriod
self.Indicators.Add(self._stochastic)
# Create subscription and bind indicators
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessStochastic).Start()
# Setup chart visualization if available
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._stochastic)
self.DrawOwnTrades(area)
# Start position protection
self.StartProtection(
takeProfit=Unit(2, UnitTypes.Percent),
stopLoss=Unit(2, UnitTypes.Percent)
)
def ProcessStochastic(self, candle):
if candle.State != CandleStates.Finished:
return
stoch_result = process_candle(self._stochastic, candle)
if not self._stochastic.IsFormed:
return
k_val = stoch_result.K
if k_val is None:
return
stochK = float(k_val)
# Calculate average and standard deviation of stochastic
stochAvgValue = float(process_float(self._stochAverage, stochK, candle.ServerTime, True))
tempStdDevValue = float(process_float(self._stochStdDev, stochK, candle.ServerTime, True))
if not self._stochAverage.IsFormed or not self._stochStdDev.IsFormed:
self._prevStochValue = stochK
self._prevStochAverage = stochAvgValue
self._prevStochStdDev = tempStdDevValue
return
# First values initialization - skip trading decision
if self._prevStochValue == 0:
self._prevStochValue = stochK
self._prevStochAverage = stochAvgValue
self._prevStochStdDev = tempStdDevValue
return
# Calculate breakout thresholds
upperThreshold = self._prevStochAverage + self._prevStochStdDev * float(self.DeviationMultiplier)
lowerThreshold = self._prevStochAverage - self._prevStochStdDev * float(self.DeviationMultiplier)
# Entry only when flat (no exit logic in CS)
if stochK > upperThreshold and self._prevStochValue <= upperThreshold and self.Position == 0:
self.BuyMarket()
elif stochK < lowerThreshold and self._prevStochValue >= lowerThreshold and self.Position == 0:
self.SellMarket()
# Store current values for next comparison
self._prevStochValue = stochK
self._prevStochAverage = stochAvgValue
self._prevStochStdDev = tempStdDevValue
def CreateClone(self):
"""!! REQUIRED!! Creates a new instance of the strategy."""
return stochastic_breakout_strategy()