GitHub で見る

LCS MACD トレーダー戦略

この戦略は、「LCS-MACD-Trader」MetaTrader 4 エキスパート アドバイザーの StockSharp 移植です。ゼロラインの下/上で発生する MACD クロスオーバーを取引し、オプションで Stochastic オシレーターからの確認を必要とします。このロジックは、元の時刻フィルターと MetaTrader スタイルのトレーリング ストップ/損益分岐点管理も反映しています。

仕組み

  • ロングエントリーは、MACD ラインがシグナルラインの上を横切り、両方ともゼロ未満のままの場合にトリガーされます。確率的フィルターが有効な場合、%D ラインは指定されたルックバック内で %K を上回っている必要があり、現在のローソク足は %D が %K を下回っていることを示している必要があります。
  • ショートエントリーは、MACD ラインがシグナルラインの下を横切り、両方がゼロより上に留まったときにトリガーされます。確率的フィルターを有効にすると、%D ラインは最近 %K を下回っていたはずですが、現在は再び上に上昇しています。
  • 取引は、EA 設定を複製する 3 つの構成可能な日中ウィンドウ内でのみ許可されます。
  • テイクプロフィット、ストップロス、損益分岐点、トレーリングストップの距離はピップ単位で表され、商品ポイントサイズを使用して変換されます。
  • 維持されるネット ポジションは方向ごとに 1 つだけです (StockSharp ネット)。ポジションのスタックは最大 MaxOrders ロットまで許可されます。逆のシグナルは、リスク管理によって現在のネットポジションがクローズされるまで待機します。

パラメーター

名前 説明 デフォルト
CandleType インジケーターの計算に使用されるローソク足シリーズ。 15分の時間枠
FastEmaPeriod MACD の EMA 期間が早いです。 12
SlowEmaPeriod MACDのEMA期間が遅い。 26
SignalPeriod MACD の信号線期間。 9
UseStochasticFilter エントリー前に確率的確認を要求します。 本当の
BarsToCheckStochastic 逆の確率的関係以降の最大の閉じたバー。 5
StochasticKPeriod ルックバックの長さは %K です。 5
StochasticDPeriod %D のスムージング長。 3
StochasticSlowing 追加の平滑化が %K に適用されました。 3
TradeVolume エントリーごとに使用されるロットサイズ。 0.1
TakeProfitPips 利益確定距離 (pips)。 100
StopLossPips ピップス単位のストップロス距離。 100
MaxOrders 方向ごとの最大スタックエントリ。 5
EnableTrailing MetaTrader スタイルのトレーリング ストップ ロジックを有効にします。
TrailingActivationPips トレーリングが始まる前に利益が必要です。 50
TrailingDistancePips トレーリングストップによって維持される距離。 25
BreakEvenActivationPips ストップを損益分岐点に移動するために必要な利益。 25
BreakEvenOffsetPips 損益分岐点ストップを設定すると追加のピップが追加されます。 1
Session1Start/End, Session2Start/End, Session3Start/End 日中の取引ウィンドウ。 08:15~08:35、13:45~14:42、22:15~22:45

注意事項

  • この戦略はネッティング口座を前提としています。オリジナルの MT4 バージョンのように反対注文をヘッジするのではなく、設定されたリスク ルールを通じて既存のポジションをクローズします。
  • Pip 変換では、インストゥルメント ポイント サイズが使用されます。 5 桁の FX シンボルの場合、ロジックは EA 乗数設定に一致するように pip 値を 10 ずつ自動的にスケーリングします。
  • トレーリング ストップと損益分岐点ロジックは完成したローソク足で評価され、各バーの高値/安値を使用してティックベースの MetaTrader の動作をエミュレートします。
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// LCS MACD Trader: MACD zero-line cross with RSI filter and ATR stops.
/// </summary>
public class LcsMacdTraderStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastEmaLength;
	private readonly StrategyParam<int> _slowEmaLength;
	private readonly StrategyParam<int> _rsiLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevMacd;
	private decimal _entryPrice;

	public LcsMacdTraderStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_fastEmaLength = Param(nameof(FastEmaLength), 12)
			.SetDisplay("Fast EMA", "Fast EMA period.", "Indicators");

		_slowEmaLength = Param(nameof(SlowEmaLength), 26)
			.SetDisplay("Slow EMA", "Slow EMA period.", "Indicators");

		_rsiLength = Param(nameof(RsiLength), 14)
			.SetDisplay("RSI Length", "RSI period.", "Indicators");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR period.", "Indicators");
	}

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

	public int FastEmaLength
	{
		get => _fastEmaLength.Value;
		set => _fastEmaLength.Value = value;
	}

	public int SlowEmaLength
	{
		get => _slowEmaLength.Value;
		set => _slowEmaLength.Value = value;
	}

	public int RsiLength
	{
		get => _rsiLength.Value;
		set => _rsiLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevMacd = 0;
		_entryPrice = 0;
	}

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

		_prevMacd = 0;
		_entryPrice = 0;

		var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
		var rsi = new RelativeStrengthIndex { Length = RsiLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, rsi, atr, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal rsiVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var macd = fastVal - slowVal;

		if (_prevMacd == 0 || atrVal <= 0)
		{
			_prevMacd = macd;
			return;
		}

		var close = candle.ClosePrice;

		if (Position > 0)
		{
			if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || macd < 0)
			{
				SellMarket();
				_entryPrice = 0;
			}
		}
		else if (Position < 0)
		{
			if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || macd > 0)
			{
				BuyMarket();
				_entryPrice = 0;
			}
		}

		if (Position == 0)
		{
			if (macd > 0 && _prevMacd <= 0 && rsiVal > 45)
			{
				_entryPrice = close;
				BuyMarket();
			}
			else if (macd < 0 && _prevMacd >= 0 && rsiVal < 55)
			{
				_entryPrice = close;
				SellMarket();
			}
		}

		_prevMacd = macd;
	}
}