GitHub で見る

5/8 EMA クロスプロテクト戦略

概要

5/8 EMA クロスプロテクト戦略 は、同じシンボル上の 2 つの構成可能な移動平均を比較することで、MetaTrader エキスパートアドバイザー 5_8macrossv2.mq4 を複製します。遅い移動平均を上回る速い移動平均の強気のクロスオーバーはロングポジションをオープンし、弱気のクロスオーバーはショートポジションをオープンします。移植されたバージョンは、StockSharp の高レベルのパターンに従い、オプションのテイクプロフィット、ストップロス、トレーリングストップ管理を追加します。

取引ロジック

  • 選択したローソク足サブスクリプションで 2 つの移動平均が計算されます。デフォルトでは、終値の 5 期間の指数関数的 MA が始値の 8 期間の指数関数 MA と比較されます。
  • 直近に完成したローソク足で速いMAが遅いMAを上抜けると、戦略はオープンまたは反転してロングポジションになります。ショートポジションがアクティブな場合、そのボリュームは方向を反転する新しい市場の買い注文に含まれます。
  • 高速 MA が低速 MA を下回ると、同じボリューム正規化ロジックを使用して、戦略がオープンまたはショート ポジションに反転します。
  • MA シフト パラメータは、元の水平オフセットをエミュレートします。正の値は、閉じたローソク足の数だけ信号を遅らせます。前方シフトされた値はリアルタイム データでは利用できないため、負の値はゼロに丸められます。

リスク管理

  • 利食いストップロスの距離はピップ(価格ステップ)で表されます。ロングポジションがオープンされると、エントリー価格の上と下にそれぞれ保護レベルが設定されます。ロジックはショートのミラーです。
  • トレーリングストップ (pips 単位) は、価格がポジションに有利に動くにつれて保護レベルを常に強化します。長い間、トレーリングストップは上向きにしか動きません。ショートパンツの場合は下方向にのみ動きます。
  • 終了したローソク足で何らかの保護条件 (高値のテイクプロフィット、低値のストップロスまたはトレーリングレベル) が満たされた場合、ストラテジーは成行注文でポジションを終了し、内部状態をリセットします。

パラメーター

名前 種類 デフォルト 説明
TradeVolume decimal 0.1 新規エントリーの注文量。この戦略は、反転時に絶対ポジション サイズを追加します。
TakeProfitPips decimal 40 利益を出してポジションを決済するまでのエントリーからの距離 (pips)。無効にするには、0 に設定します。
StopLossPips decimal 0 保護的なストップロスのエントリーからの距離 (ピップ単位)。無効にするには、0 に設定します。
TrailingStopPips decimal 0 トレーリングストップの距離 (pips)。無効にするには、0 に設定します。
FastPeriod int 5 高速移動平均の期間。
FastShift int -1 高速MAの水平シフト。このポートでは、負の値はゼロとして扱われます。
FastMethod MovingAverageMethod Exponential 高速 MA の平滑化アルゴリズム (Simple、Exponential、Smoothed、LinearWeighted)。
FastPrice AppliedPrice Close 高速MAに使用されるローソク足価格。
SlowPeriod int 8 ゆっくりとした移動平均の期間。
SlowShift int 0 遅いMAの横シフト。
SlowMethod MovingAverageMethod Exponential 低速 MA の平滑化アルゴリズム。
SlowPrice AppliedPrice Open スローMAに使用されるローソク足の価格。
CandleType DataType TimeSpan.FromMinutes(30).TimeFrame() 計算に使用されるローソク足シリーズ。

注意事項

  • 変換により、ロジックは完了したローソク足に集中し、時期尚早のシグナルを回避します。
  • トレーリング ストップと利益目標は Security.PriceStep で計算されます。シンボルで定義されていない場合、リスク パラメータは非アクティブのままになります。
  • Python のバージョンは、タスク要件ごとに意図的に省略されています。
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// 5/8 MA Cross Protect strategy - EMA(5) and EMA(8) crossover.
/// Buys when EMA(5) crosses above EMA(8).
/// Sells when EMA(5) crosses below EMA(8).
/// </summary>
public class FiveEightMaCrossProtectStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

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

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FiveEightMaCrossProtectStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 8)
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_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 fast, decimal slow)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}