GitHub で見る

ダーククラウドピアシングCCI戦略

概要

この戦略は、MetaTrader Expert_ADC_PL_CCI アドバイザーの StockSharp 移植です。ピアシング ラインとダーク クラウド カバーのローソク足反転の価格アクションをスキャンし、確認としてコモディティ チャネル インデックス (CCI) を使用します。有効なパターンと極端な CCI の読み取り値が検出されると、この戦略は反転の方向に市場ポジションを開き、その後、CCI が極端なゾーンから出たときに終了します。

インジケーター

  • 商品チャネル指数 (CCI): モメンタムの極値を確認し、出口条件を生成します。
  • 平均実体長 (SMA): パターン定義内の「長い」ローソク足を検証するために、ローソク体のサイズを測定します。
  • 平均終値 (SMA): は、元の MQL ロジックで使用される移動平均を反映する単純なトレンド フィルターとして機能します。

取引ルール

Entry

  • 強気シグナル (ピアシングライン):
    1. 前のローソク足は終値を超えて始まる長い弱気のローソク足でなければなりません。
    2. Latest candle must be a long bullish candle that opens below the previous low and closes within the previous body, above its midpoint but below the prior open.
    3. 短期的な下降トレンドを確認するには、古いローソク足の中間点が移動平均を下回る必要があります。
    4. 最後に完了した CCI 値は、-EntryConfirmationLevel (デフォルトは 50) 以下である必要があります。
    5. ショート ポジションが存在する場合は、ロングに入る前に完全にクローズされます。
  • 弱気シグナル (暗雲カバー): 強気シグナルのミラーロジックで、長い強気ローソク足の後に長い弱気ローソク足が続き、CCI が EntryConfirmationLevel 以上である間にギャップアップし、前の実体を貫通し、中点以下で閉じる。

終了

  • ロングポジション: CCI が上から ExitLevel を下回るか、-ExitLevel を下にクロスするとクローズされ、勢いが正常化したことが示されます。
  • ショート ポジション: CCI が下から -ExitLevel または ExitLevel を上抜けたときにクローズされます。

ポジションサイズ

  • 基本の Volume プロパティを使用します。シグナルが既存のポジションを反転する必要がある場合、ストラテジーは現在のポジションの絶対サイズを注文量に自動的に追加し、完全な反転を保証します。

パラメーター

名前 説明 デフォルト
CandleType 検出に使用されるローソクの種類と時間枠。 1H 時間枠
CciPeriod 商品チャネルインデックスのルックバックの長さ。 49
AverageBodyPeriod 本体サイズ移動平均のローソク足の数。 11
EntryConfirmationLevel パターンエントリを検証する絶対的な CCI レベル。 50
ExitLevel ポジション出口をトリガーする絶対的な CCI レベル。 80

注意事項

  • この戦略は完了したキャンドルのみを処理し、部分的な更新を無視します。
  • ストップロス注文や利食い注文は自動的に設定されません。 exit は、元の Expert Advisor と同様に純粋にシグナルベースです。
  • ローソク足ロジックの等値許容差はセキュリティ設定に依存するため、商品に価格ステップが設定されていることを確認してください。
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>
/// Dark Cloud Piercing CCI strategy: trades Dark Cloud Cover and Piercing Line
/// candlestick patterns confirmed by CCI indicator levels.
/// </summary>
public class DarkCloudPiercingCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _entryLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

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

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal EntryLevel { get => _entryLevel.Value; set => _entryLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public DarkCloudPiercingCciStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_entryLevel = Param(nameof(EntryLevel), 50m)
			.SetDisplay("Entry Level", "CCI level for confirmation", "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();
		_prevCci = 0m;
		_hasPrevCci = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

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

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

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

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

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

			// Piercing Line: prev bearish, curr bullish, curr opens below prev low, closes above midpoint
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover: prev bullish, curr bearish, curr opens above prev high, closes below midpoint
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && cciValue < -EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && cciValue > EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevCci = cciValue;
		_hasPrevCci = true;
	}
}