GitHub で見る

ミッションインポッシブル パワーツーオープン戦略

概要

この戦略は、MetaTrader エキスパート アドバイザー「ミッション インポッシブル パワー ツー オープン」の StockSharp 移植です。最も最近完了したローソク足の方向を監視し、その方向に新しい取引バスケットを開きます。価格がアクティブなバスケットに対して変動すると、この戦略は固定ピップグリッドに従って新しい平均エントリを追加します。新しい各エントリの量は、元の EA の power ベースのサイジング ルールを模倣し、バスケットの浮動損失に応じて増加します。バスケット全体が単一のテイクプロフィットとストップロスのレベルを共有するように、約定のたびにエグジットターゲットが再計算されます。

取引ロジック

  1. シグナル検出 – 終了したローソク足ごとに、戦略は前のローソク足の終値と始値を比較します。
    • 前のローソク足が始値を上回って終了した場合、ロングシグナルがアクティブになります。
    • オープンより下でクローズした場合、ショート信号がアクティブになります。
    • 内側のバー (クローズとオープンが等しい) では、新しいバスケットは生成されません。
  2. 最初の取引を開始する – シグナルされた方向でアクティブなグリッドがない場合、ストラテジーは BaseVolume サイズの成行注文を出します。
  3. 平均グリッド – バスケットが存在する場合、ストラテジーは最後に約定した価格と現在の終値との間の距離を測定し続けます。
    • ロングの場合、価格が最後の約定より少なくとも GridStepPips * PriceStep 下がった時点で新しいエントリーが追加されます。
    • 空売りの場合、この戦略は価格が最後の約定から同じ距離だけ上昇するまで待ちます。
    • それぞれの方向で MaxTrades の塗りつぶしに達すると、グリッドは新しい位置の追加を停止します。
  4. ダイナミックボリューム – 新しい注文を送信する前に、ストラテジーはバスケットの含み損を計算し、それに Power * 0.0001 を乗算し、その結果を BaseVolume に加算します。最終的なサイズは取引量ステップに四捨五入され、セキュリティ制限内に固定され、MaxVolume によって上限が設定されます。
  5. 出口管理 – 毎回の充填後に、戦略はバスケット全体の共有目標を再計算します。
    • 単一のポジションでは、テイクプロフィットはエントリーから TakeProfitFirstPips 離れており、ストップロスは反対方向の StopLossPips 離れています。
    • 2 つ以上のポジションがある場合、両方のレベルはバスケットの出来高加重平均価格に固定され、ターゲット距離には TakeProfitNextPips、保護には StopLossPips が使用されます。
    • 価格がテイクプロフィットまたはストップロスのいずれかに触れると、その方向のすべてのポジションが市場でクローズされます。
  6. 独立したバスケット – 長いグリッドと短いグリッドは独立して追跡されます。この戦略は、交流信号が到着したときに両方を同時に保持できます。

パラメーター

名前 種類 デフォルト 説明
BaseVolume decimal 0.01 スケーリング前の新しいバスケットの最初の注文サイズ。
MaxVolume decimal 2 四捨五入後の単一成行注文のハードキャップ。
Power decimal 13 新規エントリーの追加量を計算する際に、浮動損失に適用される乗数。
StopLossPips int 400 共有ストップロスに使用される価格ステップの距離。
TakeProfitFirstPips int 15 バスケットの最初のエントリーのテイクプロフィット距離。
TakeProfitNextPips int 7 平均バスケット (2 つ以上のエントリー) のテイクプロフィット距離。
GridStepPips int 21 別の平均エントリーが許可されるまでの最小の逆方向の動き (価格ステップ単位)。
MaxTrades int 16 方向ごとのグリッド取引の最大数。
CandleType DataType TimeSpan.FromMinutes(5).TimeFrame() 信号の生成とバスケットの管理に使用されるキャンドル。

注意事項

  • 注文量は常に商品の VolumeStep に合わせられますが、取引板からこれらの制限が利用可能な場合は、証券の MinVolume および MaxVolume によって制限されます。
  • ロングステートマシンとショートステートマシンは完全に分離されているため、市場の方向性が急速に切り替わる場合でも、ヘッジされたバスケットを維持する戦略が可能です。
  • 保護レベルは約定ごとに再計算され、最も近い PriceStep に四捨五入され、MetaTrader バージョンで頻繁に実行されるテイクプロフィット修正ルーチンと一致します。
  • インジケーターバッファは使用されません。すべての決定は、ソース EA と同様に、生のローソク足データとポートフォリオ情報に基づいています。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Mission Impossible Power Two Open strategy: Candle direction with EMA trend filter.
/// Buys on bullish candle when above EMA, sells on bearish candle when below EMA.
/// </summary>
public class MissionImpossiblePowerTwoOpenStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaPeriod;
	private bool _wasBullishSignal;
	private bool _hasPrevSignal;

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

	public MissionImpossiblePowerTwoOpenStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_emaPeriod = Param(nameof(EmaPeriod), 50)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_wasBullishSignal = false;
		_hasPrevSignal = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_wasBullishSignal = false;
		_hasPrevSignal = 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 close = candle.ClosePrice;
		var open = candle.OpenPrice;
		var bullish = close > open;
		var bearish = close < open;
		var bullishSignal = bullish && close > emaValue;
		var bearishSignal = bearish && close < emaValue;
		var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
		var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);

		if (crossedUp && Position <= 0)
			BuyMarket();
		else if (crossedDown && Position >= 0)
			SellMarket();

		if (bullishSignal || bearishSignal)
		{
			_wasBullishSignal = bullishSignal;
			_hasPrevSignal = true;
		}
	}
}