GitHub で見る

Martingale 賢い戦略

概要

Martingale Smart は、MetaTrader エキスパート アドバイザー「Martingale Smart」の変換です。この戦略では、一度に 1 つのオープン ポジションのみを保持し、負けるサイクルごとに 2 つの異なるエントリー フィルターを切り替えます。

  1. プライマリ フィルター – より高い時間枠 MACD ヒストグラムの方向と組み合わせた 2 つの単純な移動平均間のクロスオーバー。これはデフォルトの入力モードです。
  2. 二次フィルター – 移動平均エンベロープ。前のサイクルの浮動損失が負の場合、戦略はこのフィルターに切り替わります。別の損失が発生すると、一次フィルタに戻ります。

マーチンゲール成分により、損失サイクル後の次の取引の量が増加します。最後のボリュームを乗算するか (クラシック マーチンゲール)、固定増分を追加することができます。

データサブスクリプション

  • CandleType – 主な計算と取引管理に使用される時間枠。
  • MacdTimeFrame – MACD フィルター専用の 2 番目の時間枠。 PERIOD_MN1 の期間を使用した元の EA を模倣するために、デフォルトは 1 か月になります。

どちらのサブスクリプションも OnStarted で自動的に開始されます。

取引ロジック

  1. 新しい取引は、オープンポジションがなく、すべての指標が形成された場合にのみ考慮されます。
  2. 高速 MA が低速 MA を下回り、MACD ラインがシグナルより上にある場合、一次フィルターはロングになります (弱気の場合も同じロジック)。これらの条件は、1 小節シフトして iMAiMACD を使用した元の EA に従います。
  3. 2 次フィルターは単純な移動平均エンベロープを使用します。下側のバンドを上回る終値はロングエントリーを示し、上側のバンドを下回る終値はショートエントリーを示します。これにより、iEnvelopes に基づいたロジックが再現されます。
  4. サイクルがマイナスの利益で終了すると、戦略は代替フィルターに切り替わり、マーチンゲール パラメーターに従って次のボリュームを計算します。収益性の高いサイクルでは、現在のフィルターが維持され、ボリュームが初期値にリセットされます。
  5. 保護的なストップロスとテイクプロフィットレベルは、ピップベースの距離を使用して各エントリーの直後に付加されます。

リスク管理

  • 損益分岐点 – 未実現利益が BreakEvenTriggerPips に達すると、ストップロスはエントリー価格にオプションのオフセットを加えた値に跳ね上がります。
  • クラシック トレーリング ストップ – 最新の終値から TrailingStopPips 離れた位置に移動ストップを維持します。
  • マネーでの利益確定 – 変動利益が MoneyTakeProfit を超えたときにポジションを閉じます。
  • パーセントでのテイクプロフィット – 目標金額と似ていますが、現在のポートフォリオ値のパーセンテージで表されます。
  • マネー トレーリング ストップ – 変動利益が MoneyTrailingTarget に達すると有効になります。その後、この戦略は利益のピークを追跡し、ドローダウンが MoneyTrailingDrawdown を超えたときにポジションを清算します。

すべての金銭計算は、商品の PriceStepStepPrice に依存します。データ ソースがそれらを提供しない場合、戦略は単純な価格×数量の見積もりに戻ります。

パラメーター

パラメータ 説明
UseMoneyTakeProfit 固定金額テイクプロフィットルールを有効にします。
MoneyTakeProfit アカウント通貨での変動利益目標。
UsePercentTakeProfit パーセンテージベースのテイクプロフィットを有効にします。
PercentTakeProfit ポートフォリオ価値の%としての変動利益目標。
EnableMoneyTrailing お金に追随する利益を可能にします。
MoneyTrailingTarget トレーリングブロックを有効にする利益レベル。
MoneyTrailingDrawdown トレーリングがアクティブになった場合の最大許容利益還元。
UseBreakEven 設定された距離の後にストップロスを損益分岐点に移動します。
BreakEvenTriggerPips ストップが移動するまでに必要な利益距離 (ピップ単位)。
BreakEvenOffsetPips 追加のピップが損益分岐点に追加されました。
MartingaleMultiplier 負けたサイクルの後に適用される乗算係数。
InitialVolume 各サイクルの最初の注文に使用されるボリューム。
UseDoubleVolume true の場合、ボリュームを乗算します。それ以外の場合は、LotIncrement を適用します。
LotIncrement 倍増が無効な場合に使用される固定ロット増分。
TrailingStopPips 古典的なトレーリングストップの距離 (ピップ単位)。
StopLossPips 初期のストップロス距離 (pips)。
TakeProfitPips 初期のテイクプロフィット距離 (pips)。
FastMaPeriod 高速移動平均の期間。
SlowMaPeriod ゆっくりとした移動平均の期間。
EnvelopePeriod エンベロープ移動平均の期間。
EnvelopeDeviation 封筒の幅 (パーセント単位)。
MacdFastLength MACD 内の高速な EMA の長さ。
MacdSlowLength MACD 内の EMA の長さが遅い。
MacdSignalLength MACD 内の信号 EMA の長さ。
CandleType メインシグナルの時間枠。
MacdTimeFrame MACD ローソク足のタイムフレーム。

使用上の注意

  1. マーチンゲール ステップは、前のポジションが損失で完全にクローズされた場合にのみ実行されます。
  2. この戦略では、一度に 1 つのオープン ポジションが想定されます。反対方向にエントリーする前に、常に現在のポジションを清算します。
  3. 正確な金額ベースのしきい値を得るには、商品の契約仕様 (PriceStepStepPrice、および VolumeStep) を設定します。
  4. 損益分岐点とトレーリングストップは、メインタイムフレームの閉じたローソク足で評価されます。バー内スパイクは無視されます。

MetaTrader EA との違い

  • 変換では、iMACD への直接呼び出しの代わりに、StockSharp の高レベルの API (SubscribeCandles + Bind) と MovingAverageConvergenceDivergenceSignal インジケーターが使用されます。
  • 一部のブローカー固有のチェック (フリーズ レベル、手動メール/通知呼び出し、チケットベースのループ) は、StockSharp エンジンが内部で管理するため省略されます。
  • 金銭ベースの保護は、StockSharp のアカウント モデルに合わせて、チケットごとの計算ではなく、集計されたポジションに基づいて機能します。
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// Smart Martingale strategy: MACD + MA filter with martingale volume on loss.
/// Buys when fast MA crosses above slow MA. Sells on cross below.
/// </summary>
public class MartingaleSmartStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

	public MartingaleSmartStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast MA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow MA", "Slow SMA period", "Indicators");
	}

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

		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };

		decimal? prevFast = null;
		decimal? prevSlow = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, (candle, fastVal, slowVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevFast.HasValue && prevSlow.HasValue)
				{
					if (prevFast.Value <= prevSlow.Value && fastVal > slowVal && Position <= 0)
						BuyMarket();
					else if (prevFast.Value >= prevSlow.Value && fastVal < slowVal && Position >= 0)
						SellMarket();
				}

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fast);
			DrawIndicator(area, slow);
			DrawOwnTrades(area);
		}
	}
}