GitHub で見る

CDC PL RSI 戦略

概要

CDC PL RSI 戦略 は、StockSharp エコシステム内で MQL Expert Advisor Expert_ADC_PL_RSI を複製します。システムは完成したローソク足をスキャンして日本のローソク足反転パターンを探し、相対強さ指数 (RSI) でエントリーを確認します。ロングトレードは売られ過ぎの RSI 条件の間の ピアシングライン パターンに依存しますが、ショートトレードでは Dark Cloud Cover パターンと買われ過ぎの RSI 測定値を組み合わせる必要があります。このアプローチでは、戦略ボリュームを使用し、StockSharp にポジションのサイジングを処理させることで、元の資金管理の概念をシンプルに保ちます。

パターンとインジケーターのロジック

  • ローソク足パターン: この戦略は、2 つの最新の完成したローソク足を分析することによって、MetaTrader ロジックを再構築します。ピアシング ラインとダーク クラウド カバー ルールは、ギャップのチェック、適応実体平均に対するロング実体、および基礎となるトレンドの方向を含む、元のコードを反映しています。
  • RSI フィルター: 20 周期の RSI (最適化可能) は勢いを確認します。売られすぎの測定値 (RSI < 40) はロングエントリーのロックを解除し、買われすぎの測定値 (RSI > 60) はショートのロックを解除します。 RSI 履歴は、オシレーターが逆方向に 30 レベルまたは 70 レベルを横切るときの出口を検出するためにも使用されます。
  • 実体平均とトレンド フィルター: ローソク足実体サイズの単純移動平均と終値の別の SMA は、MetaTrader ヘルパー関数 (AvgBody および CloseAvg) を複製します。これらの平均により、ノイズ中の信号が防止され、明確な移動の後にパターンが表示されるようになります。

取引ルール

長いセットアップ

  1. 最後に完成した 2 つのキャンドルでピアス ライン パターンを検出します。
  2. 前回終了したローソクの RSI が 40 未満である必要があります。
  3. 条件が整う場合は市場で購入します。反対のポジションが存在する場合、絶対ポジションサイズと設定されたボリュームを購入することで戦略が逆転します。

短いセットアップ

  1. 2 つの最新のローソク足で暗雲カバー パターンを検出します。
  2. 前回終了したローソクの RSI が 60 を超える必要があります。
  3. 条件が整う場合は市場で売却します。反対のポジションは、同じボリュームロジックを使用して閉じられ、反転されます。

終了条件

  • RSI が 70 を下抜けたとき、または 30 を超えて上昇したときにロングポジションを閉じ、勢いが弱まったか反転したことを示します。
  • RSI が 30 を超えて上昇するか、70 を超えて下降すると、ショート ポジションを閉じます。これは、MetaTrader の実装を反映しています。

パラメーター

名前 デフォルト 説明
RsiPeriod 20 RSI 回の振り返りの長さ。 10 ~ 40 の間で 5 段階で最適化できます。
BodyAveragePeriod 14 平均ローソク体サイズと終値トレンドフィルターの両方の期間。 10 ~ 30 の間で 5 段階で最適化できます。
CandleType 1時間枠 計算に使用されるローソク足シリーズ。 StockSharp でサポートされているキャンドル タイプを選択できます。
Volume (基本クラス) 開始前に戦略インスタンスに設定された取引量。

使用法

  1. StockSharp デザイナー、シェル、ランナーでポートフォリオとセキュリティに戦略を添付します。
  2. 取引される市場に応じてローソク足の種類と量を設定します。
  3. 必要に応じて、商品のボラティリティに合わせて RSI と実体平均期間を調整するか、StockSharp オプティマイザーを使用して最適化を実行します。
  4. 戦略を開始し、チャートのオーバーレイ (ローソク足、RSI、平均近くの線) を監視して、パターンの確認と実行された取引を確認します。

注意事項

  • このストラテジーは、必要に応じて組み込みの保護ルーチン (ストップロス、テイクプロフィット、トレーリングなど) を設定できるように、StartProtection() を呼び出します。
  • 完了したローソク足のみが処理され、MQL エキスパートアドバイザーとのロジックの一貫性が保たれます。
  • 追加のコレクションは保存されません。インジケーター インスタンスは、パターン チェックに必要なスライディング ウィンドウ計算を実行します。
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// CDC PL RSI strategy: Dark Cloud Cover and Piercing Line candlestick patterns
/// confirmed by RSI levels.
/// </summary>
public class CdcPlRsiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<decimal> _oversoldLevel;
	private readonly StrategyParam<decimal> _overboughtLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevRsi;
	private bool _hasPrevRsi;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public decimal OversoldLevel { get => _oversoldLevel.Value; set => _oversoldLevel.Value = value; }
	public decimal OverboughtLevel { get => _overboughtLevel.Value; set => _overboughtLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public CdcPlRsiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_oversoldLevel = Param(nameof(OversoldLevel), 40m)
			.SetDisplay("Oversold Level", "RSI below this for long entry", "Signals");
		_overboughtLevel = Param(nameof(OverboughtLevel), 60m)
			.SetDisplay("Overbought Level", "RSI above this for short entry", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevRsi = 0m;
		_hasPrevRsi = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_hasPrevRsi = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2 && _hasPrevRsi)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			// Piercing Line
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && rsiValue < OversoldLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && rsiValue > OverboughtLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevRsi = rsiValue;
		_hasPrevRsi = true;
	}
}