GitHub で見る

大ヒット作 Bollinger ブレイクアウト戦略

Blockbuster Bollinger ブレイクアウト戦略は、MetaTrader 4 エキスパート アドバイザー「BLOCKBUSTER EA」を直接移植したものです。元のシステムは、価格が設定可能な距離だけ Bollinger バンドを超えた後、積極的な反転を探しました。この StockSharp バージョンは、同じロジックを維持しながら、ローソク足のサブスクリプション、インジケーター バインディング、ポジション管理のための高レベルの API を採用しています。

コアアイデア

  1. ユーザー定義の周期と偏差を使用して Bollinger バンドを構築します。
  2. 現在のローソク足の終値が、追加のオフセット (ポイント単位) によって上部バンドを上回るか、下部バンドを下回るときを測定します。
  3. 終値がアッパーバンドにオフセットを加えた値を超える場合はショートと入力します。終値が下限バンドからオフセットを引いた値を下回った場合はロングと入力します。
  4. MQL 設定と同じポイントベースの損益しきい値を使用してポジションを管理します。

距離、停止、ターゲットは計器点で表されます。これらは商品の価格ステップに適応するため、3 の値は、基礎となるシンボルに関係なく、3 つの PriceStep 単位を意味します。

詳細なロジック

  • 指標の計算

    • インジケーター: Bollinger バンド。
    • 入力: ローソク足の終値 (MT4 コードでは PRICE_OPEN が使用されました。このポートは、バンドの長さと偏差パラメーターを維持しながら、StockSharp の互換性を向上させるために終値を維持します)。
    • パラメータ:
      • BollingerPeriod: 移動平均と標準偏差で使用されるローソク足の数。
      • BollingerDeviation: 上部バンドと下部バンドの標準偏差乗数。
    • 追加のオフセット DistancePoints (商品 PriceStep を使用して価格に変換)。
  • エントリー条件

    • ロング: Close < LowerBand - Distance、現在のネットポジションはフラットまたはショートです。
    • ショート: Close > UpperBand + Distance、現在のネット ポジションはフラットまたはロングです。
    • オープン反対ポジションは、MT4 の「1 つの注文のみ」の動作を反映するために、成行注文サイズ TradeVolume + |Position| によってフラット化されます。
  • Exit Conditions

    • 完成したキャンドルごとに位置が監視されます。ポイント単位の未実現利益は、商品 PriceStep を使用して計算されます。
    • 利益確定: 利益が ProfitTargetPoints に達したか、それを超えた場合。
    • ストップロス: 損失が LossLimitPoints に達したか、それを超えた場合。
    • 決済は、ポジション全体を決済する成行注文で実行されます。
  • リスクと資金の管理

    • TradeVolume は基本注文サイズを設定します。 MetaTrader の「Lots」入力との一致は、同じ数値を設定するのと同じくらい簡単です。
    • ストップとターゲットの両方を無効にするには、それぞれのパラメータを 0 に設定します。
    • 両方のしきい値が有効になっている場合、元の EA が最初に利益ブランチをチェックしたのとまったく同じように、ターゲットの後にストップが評価されます。
  • 状態の追跡

    • この戦略はシグナル時のエントリー価格を記録し、それをその後のすべての損益計算に使用します。
    • 手仕舞い注文によってポジションがフラットになると、状態は自動的にリセットされます。

パラメーター

パラメータ デフォルト 説明
BollingerPeriod 20 Bollinger バンド移動平均内のローソク足の数。
BollingerDeviation 2.0 標準偏差の乗数。
DistancePoints 3 取引が行われる前のバンドを超える追加距離 (商品ポイント)。
ProfitTargetPoints 3 商品ポイントでのテイクプロフィットしきい値。無効にするには 0 に設定します。
LossLimitPoints 20 商品ポイント単位のストップロスしきい値。無効にするには 0 に設定します。
TradeVolume 1 新しいエントリのボリューム。
CandleType 1分の時間枠 計算に使用されるローソクの種類。

使用上の注意

  • キャンドルとゼロ以外の PriceStep を供給するあらゆる機器で動作します。外国為替ペア、インデックス CFD、流動先物は、元の EA 環境を最も良く反映しています。
  • このインジケーターは終値に依存しているため、MT4 バージョンと同様の動作を保証するために、意図した時間枠でテストすることをお勧めします。
  • この戦略は、UI でチャートが利用可能な場合に、CreateChartArea ヘルパーを使用して、ローソク足、Bollinger バンド、および実行された取引を視覚化します。
  • このロジックは完成したローソク足の継続的な評価を前提としており、バックテストやライブ取引での決定的な動作を保証します。

タグ

  • カテゴリ: カウンタートレンドのブレイクアウト
  • 方向: 両方
  • インジケーター: Bollinger バンド
  • 停止: はい (設定可能)
  • 期間: 短期 (デフォルトは 1 分)
  • 複雑さ: シンプル
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Blockbuster Bollinger breakout strategy.
/// Buys when price closes below lower Bollinger band (mean reversion).
/// Sells when price closes above upper Bollinger band.
/// Exits at middle band.
/// </summary>
public class BlockbusterBollingerStrategy : Strategy
{
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerWidth;
	private readonly StrategyParam<DataType> _candleType;

	public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
	public decimal BollingerWidth { get => _bollingerWidth.Value; set => _bollingerWidth.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BlockbusterBollingerStrategy()
	{
		_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
			.SetDisplay("BB Period", "Bollinger bands period", "Indicators");

		_bollingerWidth = Param(nameof(BollingerWidth), 1m)
			.SetDisplay("BB Width", "Bollinger bands deviation", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); }

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var bb = new BollingerBands { Length = BollingerPeriod, Width = BollingerWidth };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(bb, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue value)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!value.IsFinal || value.IsEmpty)
			return;

		var bbVal = value as BollingerBandsValue;
		if (bbVal == null)
			return;

		var upper = bbVal.UpBand;
		var lower = bbVal.LowBand;
		var middle = bbVal.MovingAverage;

		if (upper == null || lower == null || middle == null)
			return;

		var close = candle.ClosePrice;

		// Breakout above upper band - momentum buy
		if (close > upper.Value && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Breakout below lower band - momentum sell
		else if (close < lower.Value && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
		// Exit long at middle
		else if (Position > 0 && close < middle.Value)
		{
			SellMarket();
		}
		// Exit short at middle
		else if (Position < 0 && close > middle.Value)
		{
			BuyMarket();
		}
	}
}