GitHub で見る

レンジブレイクアウト2 戦略

概要

RangeBreakout2 戦略 は、MetaTrader エキスパート アドバイザー「RangeBreakout2」の StockSharp 移植です。このアルゴリズムは、設定可能な時間 (毎週、毎日、または連続) で価格範囲を準備し、買値/売値がその範囲を外れると単一の成行注文を開きます。各取引の後、レンジ準備サイクルが再開されます。この実装では、元の資金管理ルール (一定、線形、マーチンゲール、および Fibonacci スケーリング) と、負けた取引後の利益確定距離のオプションの拡張が再現されます。

この戦略は単一の証券で機能し、最良の買値/売値に依存します。ブレークアウト検出の応答性を維持できるように、アダプターが最新の注文帳データを提供していることを確認してください。

取引ロジック

  1. スケジュール – 設定された時間に、戦略は現在の売値を設定の中心として記録し、生の範囲から上限/下限ブレイクアウト レベルを導き出します。
  2. 範囲計算 – 生の範囲は、次の 3 つのモードのいずれかから取得されます。
    • ATR – 最新の平均 True Range 値に AtrPercentage を乗算します。
    • パーセント – 現在の売値の PricePercentage パーセントを使用します。
    • 修正FixedRangePoints の価格ステップを絶対距離に変換します。
  3. ブレイクアウト検出Setup フェーズでは、戦略は最良の買値/売値を監視します。アスクが上限レベルを上回った場合、またはビッドが下限レベルを下回った場合、成行注文が発行されます。
  4. エントリ タイプTradeMode は、ブレイクアウト (Stop)、フェード (Limit)、またはランダム動作のいずれかを選択します。ランダム モードでは、各エントリでブレイクアウトまたはフェードのいずれかを選択します。
  5. 保護 – ストップロスとテイクプロフィットのオフセットは生のレンジから導出されます。前回の取引が損失で終了し、RangeMultiplier が 1 より大きい場合、利食い距離はその乗数によって拡大されます。
  6. 資金管理 – 注文量は、ポートフォリオの自由資本 (CurrentValue - BlockedValue) と選択したロット モードから計算されます。
    • 定数 – 常にベースボリュームを使用します。
    • 線形 – 損失が発生するたびに線形に増加します。
    • Martingale – 損失後、前のボリュームに LotMultiplier を掛けます。
    • Fibonacci – 損失後は Fibonacci シーケンスに従って成長します。

ポジションがクローズされると、戦略はスタンバイフェーズにリセットされ、次のスケジュールトリガーを待ちます。

パラメーター

グループ 名前 説明 デフォルト
スケジュール Periodicity レンジの準備頻度: 毎週、毎日、またはノンストップ。 Weekly
スケジュール Day Periodicity = 毎週の場合に使用される取引日。 Monday
スケジュール Hour セットアップが構築された時刻 (MetaTrader スタイルの調整: 保存された値 + 1、≥ 23 の場合は 0 に制限されます)。 0
範囲 RangeMode 生の範囲の計算方法 (ATR / パーセント / 固定)。 Atr
範囲 AtrPercentage ATR 値に適用されるパーセンテージ乗数。 50
範囲 AtrLength ATR インジケーターで使用されるローソク足の数。 20
範囲 PricePercentage RangeMode = Percent のときに使用される現在の売値のパーセンテージ。 1
範囲 FixedRangePoints RangeMode = Fixed の場合、価格ステップで表される固定範囲。 1000
取引 RangePercentage ブレイクアウト レベルに適用される生の範囲のパーセンテージ。 100
取引 TradeMode エントリースタイル: ストップ (ブレイクアウト)、リミット (フェード)、またはランダム。 Stop
取引 TakeProfitPercentage (オプションで拡張された) レンジのパーセンテージとしてのテイクプロフィット距離。 100
取引 StopLossPercentage 基本レンジのパーセンテージとしてのストップロス距離。 100
リスク LotMode ロット管理スキーム (定数 / 線形 / Martingale / Fibonacci)。 Martingale
リスク MarginPercentage 基本注文量のために確保されている自由資本の一部。 10
リスク LotMultiplier マーチンゲールのようなスケーリング モードで適用される乗数。 2
リスク RangeMultiplier 損失取引後に適用されるテイクプロフィット乗数。 1
データ SignalCandleType スケジュール条件を確認するために使用されるキャンドルのタイプ。 1m time-frame
データ AtrCandleType ATR の計算に使用されるローソクの種類。 RangeMode = Atr の場合にのみリクエストされます。 1d time-frame

実装メモ

  • この戦略では、ライブの入札/売値更新が必要です。これらがないと、ブレークアウト検出はトリガーされません。
  • 基本ボリュームの計算はポートフォリオの資本 (CurrentValue - BlockedValue) に依存します。コネクタがこれらのフィールドを提供しない場合、ボリュームは交換の最小値に戻ります。
  • 秘密保持命令は、SetStopLoss および SetTakeProfit を通じて発行されます。結果として得られるポジション (新しい取引後) は、基本クラスがスケーリング シナリオの組み合わせた保護を管理できるように渡されます。
  • ATR フォールバックは、元のエキスパート アドバイザを模倣します。インジケーターの準備ができていない場合、範囲はデフォルトで現在のアスク価格の 1% に設定されます。
  • ランダム取引モードでは、戦略構築にシードされた .NET Random クラスを使用します。したがって、2 つの連続したブレイクアウトでは異なるエントリー タイプが選択される可能性があります。

使用のヒント

  1. スケジュール チェックの目的の解決策に一致するように SignalCandleType を構成します。 1 分間のローソク足ストリームは、MQL バージョンのティック主導の動作を厳密に再現します。
  2. 毎週のスケジュールの場合、サーバーのタイムゾーンが元の EA の予想と一致していることを確認してください。
  3. マーチンゲールのようなロット モードを使用する場合は、RangeMultiplier の影響を監視します。ボリュームの増加とともにテイクプロフィット ディスタンスを拡大すると、連敗後のエクスポージャが増加します。
  4. ストップロスとテイクプロフィットの距離は生の範囲から導出されるため、RangePercentage の値が大きいと、保護オフセットも同様に大きくなります。
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Range Breakout 2 strategy: Donchian channel breakout.
/// Buys on new high breakout, sells on new low breakout.
/// </summary>
public class RangeBreakout2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelPeriod;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }

	public RangeBreakout2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_channelPeriod = Param(nameof(ChannelPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Channel Period", "Highest/Lowest period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = 0m;
		_prevLow = 0m;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_hasPrev = false;
		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(highest, lowest, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal highValue, decimal lowValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var close = candle.ClosePrice;

		if (_hasPrev)
		{
			if (close > _prevHigh && Position <= 0)
				BuyMarket();
			else if (close < _prevLow && Position >= 0)
				SellMarket();
		}

		_prevHigh = highValue;
		_prevLow = lowValue;
		_hasPrev = true;
	}
}