ボリンジャーバンドリバーサル戦略
ボリンジャーバンドの外側での価格の極端な値は、多くの場合中央バンドに向かって戻ります。このアプローチはその拡張に逆らい、ロウソクが緑で引けると下限バンドを下回る急落で買い、赤いロウソクの後に上限バンドを上回る反発で売ります。
テストでは年平均リターン約94%を示しています。株式市場で最もよく機能します。
アルゴリズムは各バーでボリンジャーバンドを計算し、引け値が外側のバンドを突破するかどうかを確認します。強気ロウソクが下限バンドの下で引けるとロングが開かれ、弱気ロウソクが上限バンドの上で引けるとショートが取られます。ストップはATRの倍数に基づき、価格が中央バンドに戻るとエグジットが発生します。
平均回帰トレードは通常わずか数バーしか続かないため、このセットアップは短期のボラティリティ収縮に適しています。
詳細
- エントリー条件: 強気ロウソクで下限バンドを下回る引けか、弱気ロウソクで上限バンドを上回る引け。
- ロング/ショート: 両方。
- エグジット条件: 価格が中央バンドを越えるかストップロス。
- ストップ: はい、ATRベース。
- デフォルト値:
BollingerPeriod= 20BollingerDeviation= 2.0AtrMultiplier= 2.0CandleType= 5 minute
- フィルター:
- カテゴリ: 平均回帰
- 方向: 両方
- インジケーター: Bollinger Bands, ATR
- ストップ: はい
- 複雑さ: 基本
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Bollinger Band Reversal strategy.
/// Enters long when price is below the lower Bollinger Band and candle is bullish.
/// Enters short when price is above the upper Bollinger Band and candle is bearish.
/// Exits at middle band.
/// </summary>
public class BollingerBandReversalStrategy : Strategy
{
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerDeviation;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private int _cooldown;
/// <summary>
/// Bollinger Bands period.
/// </summary>
public int BollingerPeriod
{
get => _bollingerPeriod.Value;
set => _bollingerPeriod.Value = value;
}
/// <summary>
/// Bollinger Bands deviation multiplier.
/// </summary>
public decimal BollingerDeviation
{
get => _bollingerDeviation.Value;
set => _bollingerDeviation.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public BollingerBandReversalStrategy()
{
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Bollinger Period", "Period for Bollinger Bands", "Indicators");
_bollingerDeviation = Param(nameof(BollingerDeviation), 2.0m)
.SetNotNegative()
.SetDisplay("Bollinger Deviation", "Standard deviations for Bollinger Bands", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_cooldown = 0;
var bollingerBands = new BollingerBands
{
Length = BollingerPeriod,
Width = BollingerDeviation
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bollingerBands, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bollingerBands);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bollingerValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!bollingerValue.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_cooldown > 0)
{
_cooldown--;
return;
}
var bb = (BollingerBandsValue)bollingerValue;
var upperBand = bb.UpBand;
var lowerBand = bb.LowBand;
var middleBand = bb.MovingAverage;
var isBullish = candle.ClosePrice > candle.OpenPrice;
var isBearish = candle.ClosePrice < candle.OpenPrice;
if (Position == 0 && candle.ClosePrice < lowerBand && isBullish)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && candle.ClosePrice > upperBand && isBearish)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && candle.ClosePrice > middleBand)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice < middleBand)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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 BollingerBands
from StockSharp.Algo.Strategies import Strategy
class bollinger_band_reversal_strategy(Strategy):
"""
Bollinger Band Reversal strategy.
Enters long when price is below the lower Bollinger Band and candle is bullish.
Enters short when price is above the upper Bollinger Band and candle is bearish.
Exits at middle band.
"""
def __init__(self):
super(bollinger_band_reversal_strategy, self).__init__()
self._bollinger_period = self.Param("BollingerPeriod", 20).SetDisplay("Bollinger Period", "Period for Bollinger Bands", "Indicators")
self._bollinger_deviation = self.Param("BollingerDeviation", 2.0).SetDisplay("Bollinger Deviation", "Standard deviations for Bollinger Bands", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bollinger_band_reversal_strategy, self).OnReseted()
self._cooldown = 0
def OnStarted2(self, time):
super(bollinger_band_reversal_strategy, self).OnStarted2(time)
self._cooldown = 0
bb = BollingerBands()
bb.Length = self._bollinger_period.Value
bb.Width = self._bollinger_deviation.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(bb, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bb)
self.DrawOwnTrades(area)
def _process_candle(self, candle, bb_value):
if candle.State != CandleStates.Finished:
return
if not bb_value.IsFormed:
return
if self._cooldown > 0:
self._cooldown -= 1
return
upper_band = bb_value.UpBand
lower_band = bb_value.LowBand
middle_band = bb_value.MovingAverage
if upper_band is None or lower_band is None or middle_band is None:
return
close = float(candle.ClosePrice)
ub = float(upper_band)
lb = float(lower_band)
mb = float(middle_band)
cd = self._cooldown_bars.Value
is_bullish = candle.ClosePrice > candle.OpenPrice
is_bearish = candle.ClosePrice < candle.OpenPrice
if self.Position == 0 and close < lb and is_bullish:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and close > ub and is_bearish:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and close > mb:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and close < mb:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return bollinger_band_reversal_strategy()