GitHub で見る

マクロス戦略

この戦略は、StockSharp の高レベル API を使用して、元の MQL/34176/MACross.mq4 エキスパート アドバイザーの動作を複製します。単一商品を移動平均クロスオーバーで取引し、ピップと口座資本で表現されるすべてのリスク管理を維持します。

取引ロジック

  1. 2 つの単純移動平均 (SMA) は、設定されたローソク足タイプに基づいて構築されます。
    • FastPeriod は価格の変更にすぐに反応します。
    • SlowPeriod は長期トレンドを平滑化します。
  2. 終了した各ローソク足の終値で、高速平均と低速平均が比較されます。
    • 強気のクロスオーバー(低速を高速でクロスオーバー)すると、ロングポジションがオープンします。アクティブなショートは最初にフラット化されます。
    • 弱気のクロスオーバー (低速を下回る高速クロス) は、既存のロングポジションを閉じた後、ショートポジションをオープンします。
  3. すべてのエントリーは、LotSize から派生し、商品の制限 (VolumeStepMinVolumeMaxVolume) に合わせた固定市場ボリュームを使用します。
  4. ポジションがオープンされた後、戦略は pips で測定される 2 つのリスク目標を追跡します。 pip サイズは、Security.Decimals (またはフォールバックとして PriceStep) から自動的に推測されます。
    • TakeProfitPips は利益目標までの距離を定義します。これにヒットすると、現在の方向への市場の出口が発行されます。
    • StopLossPips は保護停止距離を定義します。これを突破するとポジションは直ちにクローズされます。
  5. 取引は MinEquity の警備員によって一時停止されることがあります。現在のポートフォリオ値がしきい値を下回る場合、戦略はアクティブなポジションを管理し続けますが、新しいエントリーは許可されません。

すべての計算は完了したローソク足に対してのみ機能し、移動平均を評価する前に新しいバーを待機した元のエキスパートアドバイザーと完全に一致します。

可視化

チャート ペインが使用可能な場合、戦略は次のようにプロットします。

  • 購読中のシリーズからキャンドルを入力します。
  • 高速 SMA と低速 SMA。
  • クロスオーバー ルールによってトリガーされるエントリーとエグジットを強調表示する独自の取引。

パラメーター

名前 種類 デフォルト 説明
FastPeriod int 8 クロスオーバー信号を生成する高速 SMA の長さ。
SlowPeriod int 20 基準トレンドラインとして使用される遅い SMA の長さ。
TakeProfitPips decimal 20 利益目標までの距離をピップ単位で表します。ピップサイズは商品の小数点から推測されます。
StopLossPips decimal 20 ピップ単位の保護停止距離。利益目標と同じピップサイズ計算を使用します。
LotSize decimal 1 基本注文量。この戦略では、成行注文を送信する前に、許容される最も近いサイズに丸められます。
MinEquity decimal 100 口座の最低資本。ポートフォリオの価値がこのレベルを下回っている間、新しい取引はブロックされます。
CandleType DataType TimeSpan.FromMinutes(1).TimeFrame() SMA の計算と信号評価に使用されるローソク足シリーズ。

MQL バージョンとの違い

  • 元の MQL のエキスパートは、ストップロスとテイクプロフィットの価格をゼロとして OrderSend に渡しました。 StockSharp ポートは、完成した各ローソク足の終値を監視する手動終了と同じ動作をエミュレートします。
  • 株式検証 (cekMinEquity) は、AccountEquity() ではなく Portfolio.CurrentValuePortfolio.BeginValue を読み取るようになりましたが、しきい値ロジックは保持されます。
  • Pip サイズ検出は、GetPipPoint ヘルパーを反映します。2 桁または 3 桁の引用符は 0.01 を使用し、4 桁または 5 桁の引用符は 0.0001 を使用します。それ以外の場合は、PriceStep が使用されます。

結果として得られる戦略は、公開されているすべてのパラメータを通じて最適化でき、StockSharp のグラフ作成およびリスク管理インフラストラクチャとシームレスに組み合わせることができます。

namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// MA Cross strategy: SMA crossover.
/// Buys when fast SMA crosses above slow SMA, sells on cross below.
/// </summary>
public class MacrossStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	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 MacrossStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_fastPeriod = Param(nameof(FastPeriod), 10)
			.SetGreaterThanZero()
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
		_slowPeriod = Param(nameof(SlowPeriod), 30)
			.SetGreaterThanZero()
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, ProcessCandle).Start();
	}

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

		if (_hasPrev)
		{
			if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
				SellMarket();
		}
		else
		{
			if (fastValue > slowValue && Position <= 0)
				BuyMarket();
			else if (fastValue < slowValue && Position >= 0)
				SellMarket();
		}

		_prevFast = fastValue;
		_prevSlow = slowValue;
		_hasPrev = true;
	}
}