GitHub で見る

セットあたり N 取引 Martingale 戦略

概要

この戦略は、MetaTrader エキスパート アドバイザーの「セット マーチンゲールあたり N 取引 + 株式増加時にクローズおよびリセット」を直接変換したものです。 It keeps the market direction simple—only long trades are taken—but actively manages position sizing through a martingale cascade and an equity-based reset.新しい取引は前の取引が終了した直後に開始され、戦略が常に市場に関与し続けます。

取引ロジック

  1. シーケンシャルエントリー – この戦略は、アクティブなポジションがない場合は常にロング成行注文をオープンします。ストップロス注文とテイクプロフィット注文は約定直後に付けられます。
  2. 勝敗計算 – ポジションが決済された後、実現価格がエントリー価格と比較されます。収益性の高いクロージャーは勝利カウンターをインクリメントし、それ以外の場合は損失カウンターをインクリメントします。損益分岐点の結果は損失として扱われ、元の EA と一致します。
  3. セット完了 – 現在のセット内の取引数も追跡されます。カウンタが Trades Per Set に達すると、サイクルが完了したとみなされ、次の 3 つの結果のいずれかが発生します。
    • 全勝Equity Divisor を使用して現在の資産からボリュームが再計算され、サイクル カウンターがリセットされます。
    • すべての損失 – ボリュームに Scale Factor が乗算され、サイクル カウンターがリセットされます。
    • 結果はまちまち – セットに勝ちと負けの両方が含まれている場合、カウンターは単純にリセットされ、現在のボリュームは保持されます。
  4. 株式のリセット – ポートフォリオの株式が少なくとも Equity Increase 増加するたびに、戦略はグローバル リセットを実行します。すべてのカウンタがクリアされ、資本から基本量が再計算され、資本目標が同じ増分だけ前方に移動されます。

この動作は、取引ブロックが fxDreema ロジック ノードを通じてチェーンされていた元の EA を反映しています。

パラメーター

パラメータ 説明
Trades Per Set 1 つのマーチンゲール サイクルを形成する連続取引の数。
Stop Loss (pips) 商品の価格ステップで測定されるストップロス距離。無効にするには、ゼロに設定します。
Take Profit (pips) 価格ステップで測定される利食い距離。無効にするには、ゼロに設定します。
Scale Factor 完全に負けたセット後の取引量に適用される乗数。 1 未満の値は自動的に 1 に固定されます。
Equity Divisor 完全に勝利したセットまたは資産リセット後の基本ロットサイズを導出するためにアカウント資産を分割します。
Equity Increase グローバルリセットを引き起こす株式の増加量。株式ベースのエグジットを無効にするには、ゼロに設定します。

資金管理

  • ボリュームは、元の EA と同じ方法で、楽器の制約 (VolumeStepMinVolumeMaxVolume) に合わせて調整されます。
  • 株式データが利用できない場合は、以前のボリュームが再利用され、これが最初の取引である場合は VolumeStep に戻ります。
  • ストップロスとテイクプロフィットの距離は、PriceStep を介して価格ステップに変換されます。商品が価格ステップを指定しない場合、生の値は最も近い整数に丸められます。

使用上の注意

  • この戦略は、MetaTrader スクリプトと同様に、ロングのみです。ブローカーがショートをサポートしている場合は、ストラテジーの実行時に手動で無効にします。
  • Because stop and target orders are recreated after every fill, partial fills are handled gracefully—the remaining volume inherits the same protective orders.
  • 株式のリセットは、クローズされたポジションごとに評価されます。リセットしきい値に到達できるように、ポートフォリオ接続が現在の株式価値を提供していることを確認してください。
namespace StockSharp.Samples.Strategies;

using System;

using Ecng.Common;

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

/// <summary>
/// N Trades Per Set Martingale: RSI-based entry with position tracking.
/// Buys when RSI oversold, sells when RSI overbought.
/// </summary>
public class NTradesPerSetMartingaleStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;

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

	public int RsiPeriod
	{
		get => _rsiPeriod.Value;
		set => _rsiPeriod.Value = value;
	}

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

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI calculation period", "Indicators");
	}

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

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		decimal? prevRsi = null;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(rsi, (candle, rsiVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (prevRsi.HasValue)
				{
					var crossBelowOversold = prevRsi.Value >= 30m && rsiVal < 30m;
					var crossAboveOverbought = prevRsi.Value <= 70m && rsiVal > 70m;

					if (crossBelowOversold && Position <= 0)
						BuyMarket();
					else if (crossAboveOverbought && Position >= 0)
						SellMarket();
				}

				prevRsi = rsiVal;
			})
			.Start();

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