GitHub で見る

Bread and Butter 2(ADX + AMA)

概要

この戦略はRon Thompsonが作成したMetaTrader 5エキスパートアドバイザーBreadandbutter2のポートです。元のロジックは新しいバーを待ち、最新のAverage Directional Index(ADX)値を前の値と比較し、Kaufman Adaptive Moving Average(KAMA、AMAとも呼ばれる)が上昇しているか下降しているかを確認します。トレンドの強さが弱まりながら価格モメンタムが改善するとロングポジションが開かれ、トレンドの強さが増しながらモメンタムが悪化するとショートポジションが開かれます。StockSharpバージョンは新しい注文を開く前に反対側のエクスポージャーをクローズする動作を維持し、元のスクリプトでピップで指定されたのと同じ固定のストップロスとテイクプロフィット距離を適用します。

インジケーター

  • Average Directional Index(ADX) – 現在のトレンドの強さを測定します。戦略はADXのメインラインを見て、最後の2つの値を比較してトレンドの強さが増加しているか減少しているかを判断します。
  • Kaufman Adaptive Moving Average(KAMA/AMA) – 個別の速い・遅い平滑化定数を使用して市場のボラティリティに適応します。戦略は最後の2つの値を比較してモメンタムの方向を評価します。

戦略ロジック

  1. 設定されたローソク足タイプ(デフォルト:1時間バー)で作業し、処理前にローソク足が完全にクローズするまで待ちます。
  2. 選択した長さ、速い期間、遅い期間でKAMAを計算します。
  3. 設定された平均化期間でADXを計算し、メインラインの値を抽出します。
  4. 現在と前のインジケーターの読みを比較します:
    • ロングセットアップ – ADX値が減少(トレンドの強さが弱まる)しながらKAMAが上昇(価格モメンタムが改善)。
    • ショートセットアップ – ADX値が増加しながらKAMAが下落。
  5. シグナルが現れると、反対側のエクスポージャーをクローズし、最終的なポジションが戦略の基本ボリュームと一致するよう新しいマーケット注文を開きます。
  6. アクティブポジションを継続的に監視します。価格が設定されたストップロスまたはテイクプロフィットレベル(ピップで表現され、インストゥルメントのティックサイズに従って価格単位に変換)に触れたら、すぐにトレードを終了します。

トレード管理

  • ストップロス – ピップで表現され、インストゥルメントのPriceStepを使用して価格単位に変換されます。3桁または5桁の小数で表示されるシンボルの場合、ピップサイズは価格ステップの10倍で、MetaTraderの実装に対応します。
  • テイクプロフィット – ピップで表現され、ストップロス距離と同様に処理されます。
  • 戦略はエントリーとエグジットにマーケット注文を使用し、反対のシグナルが発生するとポジションを反転します。

パラメーター

名前 デフォルト 説明
CandleType TimeSpan.FromHours(1).TimeFrame() すべての計算に使用されるローソク足タイプ。
AdxPeriod 14 ADXメインラインの平均化の長さ。
AmaPeriod 9 Kaufman Adaptive Moving Averageの基本期間。
AmaFastPeriod 2 AMA内で使用される速いEMAの期間。
AmaSlowPeriod 30 AMA内で使用される遅いEMAの期間。
StopLossPips 50 ピップ単位の保護ストップロスへの距離。0に設定すると無効化。
TakeProfitPips 50 ピップ単位の利益目標への距離。0に設定すると無効化。

使用上の注意

  • 戦略が有効なPriceStepを公開するインストゥルメントに付属していることを確認します。分数ピップを持つFXシンボルの場合、ピップサイズは自動的に計算されます。
  • Volumeは基本注文サイズを制御します。反転シグナルが現れると、アルゴリズムは反対側のエクスポージャーをクローズし、新しい方向にVolumeと等しいポジションを確立するのに十分なボリュームを追加します。
  • ストップロスとテイクプロフィットのエグジットはローソク足の高値と安値で評価されるため、動作はMetaTraderの保留注文実行を近似します。

参照

  • 元のMetaTrader 5戦略:MQL/22003/Breadandbutter2.mq5
  • StockSharpインジケーター:KaufmanAdaptiveMovingAverageAverageDirectionalIndex
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>
/// Bread and Butter 2 ADX AMA strategy. Uses KAMA direction with ADX filter.
/// </summary>
public class Breadandbutter2AdxAmaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _kamaPeriod;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private decimal? _prevKama;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int KamaPeriod { get => _kamaPeriod.Value; set => _kamaPeriod.Value = value; }
	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }

	public Breadandbutter2AdxAmaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_kamaPeriod = Param(nameof(KamaPeriod), 10).SetGreaterThanZero().SetDisplay("KAMA Period", "KAMA lookback", "Indicators");
		_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 21).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevKama = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevKama = null;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevKama = fast; return; }
		if (_prevKama == null) { _prevKama = fast; return; }
		var prevAbove = _prevKama.Value > slow;
		var currAbove = fast > slow;
		_prevKama = fast;
		if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
	}
}