GitHub で見る

M.Aブレイク戦略

この戦略は、両方のブレイクアウト方向を単一の StockSharp 実装に組み合わせることで、MetaTrader の「M.A ブレイク mt5 買い」と「M.A ブレイク mt5 売り」のエキスパートの動作を再現します。設定可能なローソク足シリーズを監視し、いくつかの指数移動平均を分析し、取引を開始する前に強いインパルスローソク足を確認します。ポジションは、固定された保護ストップとピップで測定されるターゲットによって管理されます。

取引ロジック

  1. トレンドの確認。 完成したローソク足の取引方向に 2 つの EMA ペア (速い対遅い) を揃える必要があります。ロングの場合、両方の高速平均が低速平均を上回っている必要があります。短編の場合、関係は逆転します。前のローソク足のオープンも、専用の EMA フィルターの正しい側にある必要があります。
  2. クワイエット範囲の測定。 設定可能な数の初期のキャンドル (最新のインパルス キャンドルを除く) が「クワイエット」期間を定義します。それらの最高範囲は、最小ピップしきい値と比較されます。
  3. インパルス検出。 最後に完成したキャンドルは、静かな範囲の少なくとも ImpulseStrength 倍拡大する必要があります。ピップ単位のローソク足のサイズ制限を強制して、異常に小さいまたは大きい動きを無視することができます。
  4. ローソク足テンプレート。 インパルス キャンドルは特定の芯構造を示す必要があります。
    • ロングトレード: 強気の実体、上芯がローソク足レンジの BullUpperWickPercent を超えず、下芯が少なくともレンジの BullLowerWickPercent 以上。
    • ショートトレード: 弱気の実体、少なくとも BearUpperWickPercent の上芯、レンジの BearLowerWickPercent 以下の下芯。
  5. プルバック条件。 インパルス ロー (ロングの場合) またはハイ (ショートの場合) は、プルバックからブレイクアウトが発生したことを保証するために、追加の EMA をテストする必要があります。
  6. ポジション制御 ネット ポジションは 1 つだけ許可されます。この戦略は、新しい取引に入る前に反対側をクローズし、トレンドフィルターに対してポジションをオープンすることはありません。
  7. 出口管理。 ストップロスとテイクプロフィットのレベルはエントリー価格からピップ単位で計算されます。完成した各ローソク足は、価格が保護レベルに達したかどうかを確認し、それに応じて終了します。

パラメーター

パラメータ 説明
キャンドルタイプ すべての計算に使用される主なローソク足シリーズ。
高速 MA 1 / 低速 MA 1 主要なトレンドを定義する最初の EMA ペアの期間。
高速 MA 2 / 低速 MA 2 追加のトレンド フィルターとして使用されるセカンダリ EMA ペアの期間。
フィルター MA を開く 以前のローソク足の始値をフィルターする EMA 期間。
プルバック MA EMA 期間の値はインパルス芯で触れる必要があります。
静かなバー 静かな市場範囲を測定するために使用される過去のローソク足の数。
静かな範囲 (pips) ブレイクアウトを検討する前に、静かなローソク足全体で必要な最小限のピップ範囲。
インパルス乗数 インパルスキャンドルのサイズと静かな範囲の間の最小比率。
最小/最大ローソク足サイズ (pips) インパルスキャンドル範囲のオプションの制限。ゼロはそれぞれの境界を無効にします。
雄牛の上部芯 % / 雄牛の下部芯 % 強気インパルスローソク足の形状フィルター。ローソク足範囲のパーセンテージとして表されます。
ベア上部芯 % / ベア下部芯 % 弱気インパルスローソク足の形状フィルター。
ボリューム ロングエントリーとショートエントリーの両方に使用されるロットの注文サイズ。
ストップロス (pips) エントリー価格から測定された保護ストップまでの距離。ゼロは停止を無効にします。
利益確定 (pips) 利益目標までの距離。ゼロはターゲットを無効にします。
ロングを有効にする/ショートを有効にする 各方向のブレイクアウト取引を個別に切り替えます。

使用上の注意

  • 元のエキスパートが使用した時間枠 (M5 や H1 など) に一致するようにローソク足シリーズを構成します。デフォルトの時間枠は 5 分です。
  • この戦略では、クワイエット レンジの計算に必要な最近の履歴のみが保存され、不必要なメモリ使用が防止されます。
  • エントリー価格はインパルスローソク足の終値で近似され、次の足の開始時に成行注文を発注するという元の MetaTrader の動作と一致します。
  • ストップロスとテイクプロフィットのレベルは、完了したローソク足ごとに評価されます。両方のレベルが同じバー内でヒットした場合は、ソースエキスパートで使用されている保守的な処理を反映して、ストップが優先されます。
  • 一方向のみを有効にすると、元の「買い」または「売り」のエキスパートアドバイザーが再現されますが、両方のトグルをアクティブのままにすると、対称的なブレイクアウト取引が可能になります。

変換の詳細

  • 元の MQ5 ファイルは両方とも UTF-16 でエンコードされ、FXD エンジンによって生成されたブロックから構築されました。各ブロックは明示的な C# ロジックに変換されています。
  • EMA の比較とローソク足テンプレートは、MetaTrader バージョン (Shift = 1) と同じシフトに従います。これは、戦略が常に完全に閉じたローソク足を評価することを意味します。
  • MQ5 スクリプトの仮想ストップ ロジックとチャート ラベルは、注文の配置に影響を与えないため、意図的に省略されました。

テスト

AlgoTrading.sln を通じてソリューションをコンパイルするか、StockSharp ストラテジー テスター内でストラテジーを実行します。セキュリティメタデータにこの情報が欠けている場合は、商品価格ステップを調整します。実装は一般的な FX pip 値をエミュレートするために 0.0001 にフォールバックします。

namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// MA Break strategy: EMA breakout with impulse candle confirmation.
/// Buys when close crosses above EMA with strong bullish candle body.
/// Sells when close crosses below EMA with strong bearish candle body.
/// </summary>
public class MaBreakStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _bodyRatio;

	private decimal _prevClose;
	private decimal _prevEma;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal BodyRatio { get => _bodyRatio.Value; set => _bodyRatio.Value = value; }

	public MaBreakStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for breakout", "Indicators");
		_bodyRatio = Param(nameof(BodyRatio), 0.7m)
			.SetDisplay("Body Ratio", "Min body/range ratio for impulse", "Pattern");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = 0;
		_prevEma = 0;
		_hasPrev = false;
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(ema, ProcessCandle).Start();
	}

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

		var range = candle.HighPrice - candle.LowPrice;
		var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);

		if (_hasPrev && range > 0)
		{
			var isImpulse = body >= range * BodyRatio;

			if (_prevClose <= _prevEma && candle.ClosePrice > emaValue
				&& candle.ClosePrice > candle.OpenPrice && isImpulse && Position <= 0)
				BuyMarket();
			else if (_prevClose >= _prevEma && candle.ClosePrice < emaValue
				&& candle.ClosePrice < candle.OpenPrice && isImpulse && Position >= 0)
				SellMarket();
		}

		_prevClose = candle.ClosePrice;
		_prevEma = emaValue;
		_hasPrev = true;
	}
}