GitHub で見る

SMC トレーダー キャメル CCI MACD 戦略

概要

この戦略は、MetaTrader 4 エキスパート アドバイザー 「Steve Cartwright Trader Camel CCI MACD」 の StockSharp 移植です。 キャメルスタイルの指数移動平均チャネルに基づいたオリジナルの取引ロジックを再現します。 MACD トレンド フィルターと商品チャネル インデックス (CCI) のしきい値。取引は完了した時点で実行されます キャンドルを使用して、決定的な動作を保証し、MQL バージョンの小節ごとのワークフローに近い状態を保ちます。

取引ロジック

  1. 指標
    • 同じ期間の 2 つの指数移動平均 (EMA) がローソク足の高値と安値に適用されて、 ラクダチャンネル。これらのエンベロープを超える前の終値のブレイクアウトは、勢いの強さを示します。
    • 標準の MACD インジケーター (速い EMA、遅い EMA およびシグナル ライン) は、基本的なトレンドの方向を確認するために使用されます。
    • CCI インジケーターは、デフォルトで ±100 の買われすぎ/売られすぎレベルを使用して勢いの強さを検証します。
  2. 長いエントリ
    • 前回のローソク足の終値はラクダの高値 EMA を上回っています。
    • 以前の MACD のメイン値はゼロより上で かつ 信号線よりも上です。
    • 以前の CCI の値は正のしきい値を超えています。
    • アクティブなポジションがオープンしておらず、現在のローソク足の時間枠内にエグジットが発生しませんでした (急速なリエントリーが防止されます)。
  3. 短いエントリー
    • 前回のローソク足の終値はラクダ安値 EMA を下回っています。
    • 以前の MACD の主要値はゼロ未満であり、**かつ信号線を下回っています。
    • 以前の CCI の値は負のしきい値を下回っています。
    • ロングセットアップと同じフラットポジションとクールダウン条件。
  4. 出口
    • 前の MACD のメイン値がシグナルラインを下回ったとき、または前の CCI のときにロングポジションが閉じられます。 値が正のしきい値を下回ります。
    • 前の MACD メイン値がシグナルラインを上抜けたときにショートポジションが閉じられます。
    • 終了後、新しいエントリーの前に、ローソク足の 1 本の期間に等しいクールダウンが適用されます。

すべての決定は以前に完了したローソク足のデータに基づいているため、この戦略はバーごとに最大 1 回取引されます。

パラメーター

パラメータ 説明 デフォルト
CandleType すべてのインジケーターに使用されるローソク足のデータ型/タイムフレーム。 1時間枠
CamelLength 高/低 EMA チャンネルの長さ。 34
CciPeriod CCI フィルターの長さ。 20
MacdFastPeriod MACD の高速な EMA の長さ。 12
MacdSlowPeriod MACD の EMA の長さが遅いです。 26
MacdSignalPeriod MACD の信号平滑化期間。 9
CciThreshold エントリに対して超える必要がある絶対的な CCI レベル (対称的に適用)。 100

すべてのパラメータは、SetOptimize 呼び出しのおかげで、StockSharp オプティマイザーを通じて最適化できます。

リスク管理

  • 注文は BuyMarket および SellMarket を介して送信され、戦略 Volume プロパティを継承します。
  • StartProtection() は、標準の StockSharp 保護ヘルパーを初期化するために有効になっています。
  • 元のアルゴリズムでは固定のストップロスやテイクプロフィットは定義されていません。イグジットはインジケーター信号のみに依存します。

グラフ化

この戦略は、ラクダの EMA チャネル、MACD、および CCI インジケーターを独自の取引とともに自動的にプロットします。 これは、MT4 実装で使用される視覚的なキューを複製します。

注意事項

  • クールダウン タイマーは、CandleType.Arg から導出されたローソク足の継続時間を使用します。 CandleType に 期間を変更する場合は、TimeSpan 引数を使用します。
  • すべての決定は前のバーの値に基づいているため、操作の順序は iMACDiCCI を反映します。 および iMA (shift=1 を指定) はソース EA を呼び出します。
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;

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

/// <summary>
/// Strategy combining CCI and MACD signal crossover with EMA trend filter.
/// Buy when MACD crosses above signal with CCI positive and price above EMA.
/// Sell when MACD crosses below signal with CCI negative and price below EMA.
/// </summary>
public class SmcTraderCamelCciMacd1Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _cciPeriod;

	private decimal? _prevMacdMain;
	private decimal? _prevMacdSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }
	public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }
	public int MacdSignalPeriod { get => _macdSignalPeriod.Value; set => _macdSignalPeriod.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }

	public SmcTraderCamelCciMacd1Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_emaLength = Param(nameof(EmaLength), 34)
			.SetDisplay("EMA Length", "Trend EMA period", "Indicators");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 12)
			.SetDisplay("MACD Fast", "Fast EMA for MACD", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 26)
			.SetDisplay("MACD Slow", "Slow EMA for MACD", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 9)
			.SetDisplay("MACD Signal", "Signal line period", "Indicators");

		_cciPeriod = Param(nameof(CciPeriod), 20)
			.SetDisplay("CCI Period", "CCI period", "Indicators");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

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

		_prevMacdMain = null;
		_prevMacdSignal = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevMacdMain = null;
		_prevMacdSignal = null;

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};
		var cci = new CommodityChannelIndex { Length = CciPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, cci, ema, ProcessCandle)
			.Start();
	}

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

		if (!macdValue.IsFinal || !cciValue.IsFinal || !emaValue.IsFinal)
			return;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue macdData)
			return;

		if (macdData.Macd is not decimal macdMain || macdData.Signal is not decimal macdSignal)
			return;

		var cci = cciValue.ToDecimal();
		var emaVal = emaValue.ToDecimal();

		if (_prevMacdMain is not decimal prevMain || _prevMacdSignal is not decimal prevSignal)
		{
			_prevMacdMain = macdMain;
			_prevMacdSignal = macdSignal;
			return;
		}

		var macdBullCross = prevMain <= prevSignal && macdMain > macdSignal;
		var macdBearCross = prevMain >= prevSignal && macdMain < macdSignal;

		// Long: MACD bullish cross + CCI > 0 + price above EMA
		if (Position <= 0 && macdBullCross && cci > 0 && candle.ClosePrice > emaVal)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Short: MACD bearish cross + CCI < 0 + price below EMA
		else if (Position >= 0 && macdBearCross && cci < 0 && candle.ClosePrice < emaVal)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevMacdMain = macdMain;
		_prevMacdSignal = macdSignal;
	}
}