GitHub で見る

CCI and Martin戦略

概要

CCI and Martin戦略は、短い弱気または強気のシーケンスの後に急激な逆転を探し、商品チャネル指数(CCI)でムーブを確認します。ロジックはStockSharpの高レベルAPIを使用しながら、オリジナルのMetaTrader 5エキスパートアドバイザーを複製します。戦略は完成したローソク足のみで作業し、CCI値と価格ステップが利用可能な任意のインストゥルメントで動作できます。

トレードルール

  • 強気セットアップ
    • ローソク足-2とローソク足-1は共に弱気でなければなりません(始値が終値より大きい)。
    • ローソク足0は始値の上と、ローソク足-1の始値の上でクローズしなければなりません。
    • ローソク足-1のCCIは+5未満、ローソク足-2の値未満でなければならず、-2-3両方が減少シーケンスを示さなければなりません。現在のCCI(ローソク足0)は前の値の上方に向かって上昇しなければなりません。
    • すべての条件が成立してポジションが開いていない場合、戦略はロングトレードにエントリーします。
  • 弱気セットアップ
    • ローソク足-2とローソク足-1は共に強気でなければなりません(始値が終値より小さい)。
    • ローソク足0は始値の下と、ローソク足-1の始値の下でクローズしなければなりません。
    • ローソク足-1のCCIは-5を超え、ローソク足-2の値を超えなければならず、-2-3両方が増加シーケンスを形成しなければなりません。現在のCCI(ローソク足0)は前の値の下方に向かって下落しなければなりません。
    • すべての条件が成立してポジションが開いていない場合、戦略はショートトレードにエントリーします。

アルゴリズムは完成したローソク足のみを監視します。オリジナルのMQL実装は早期シグナルを避けるために分開始後40秒待機しました;完成したローソク足の使用によりこのフィルターは不要になります。

リスク管理

  • ストップロステイクプロフィットの距離はpipsで定義されます。ステップが3桁または5桁の引用に対応する場合、インストゥルメントの価格ステップを10倍にして価格オフセットに変換し、オリジナルのpip計算を反映します。
  • トレーリングストップは価格がトレーリングストップ距離とトレーリングステップを超えて進んだ後にアクティブになります。次にストップはトレーリング距離を維持するために移動し、価格改善が設定されたステップを超えた場合にのみ前進します。
  • ストップロスまたはテイクプロフィットがゼロに設定されると、それぞれのエグジットが無効になります。トレーリングはストップ距離とステップの両方が正である必要があります。

ボリューム管理

2つのオプションのポジションサイジングエンジンが各トレード後にロットサイズを変更できます。

  • マルティンゲールスケーリングは、連続損失の数がトリガーに達すると、現在のボリュームにマルティンゲール係数を掛けます。スケーリングは設定されたマルティンゲールステップ数の後に停止します。利益が出るトレードはボリュームを初期値にリセットします。
  • ステップ調整は選択されたモードに応じて、損失後または利益後のいずれかで固定量だけボリュームを増加します。増分はインストゥルメントのボリュームステップに正規化され、最大ボリュームパラメーターで制限されます。制限を超えるか、トレードがトリガー条件を満たさない場合、ボリュームは初期サイズに戻ります。

オリジナルのエキスパートアドバイザーはマルティンゲールとステップロジックを同時に有効にすることを禁じています;C#ポートは同じ制限を適用します。

パラメーター

  • CandleType – 分析に使用するローソク足シリーズ。
  • CciPeriod – 商品チャネル指数の平均長。
  • InitialVolume – スケーリング前のベース注文サイズ。
  • StopLossPips – pipsで表現されたストップロス距離。
  • TakeProfitPips – pipsで表現されたテイクプロフィット距離。
  • TrailingStopPips – pipsでのトレーリングストップ距離(0はトレーリングを無効にします)。
  • TrailingStepPips – トレーリングストップが移動する前に必要な最小価格改善。
  • EnableMartingale – 損失後のマルティンゲールスタイルのスケーリングを有効にします。
  • MartingaleCoefficient – マルティンゲールトレードで現在のボリュームに適用される乗数。
  • MartingaleTriggerLosses – スケーリング前に必要な連続負けトレードの数。
  • MartingaleMaxSteps – マルティンゲール乗算の最大数。
  • EnableStepAdjustments – ステップベースのボリューム増分を有効にします。
  • StepVolumeIncrement – ステップルールがトリガーされたときに適用される絶対増分。
  • StepVolumeMax – ステップベースのボリュームの上限。
  • StepAdjustmentMode – ステップ増分が損失後または利益後に発生するかを選択します。

注意事項

  • 戦略は成行注文が要求価格の近くで約定されると仮定します。オリジナルEAのtickベースのトレーリングをエミュレートするために、保護ロジックは各完成したローソク足でストップを再計算します。
  • インストゥルメントの価格ステップが従来のFX引用に対応していない場合、pip変換は引き続き機能しますが、pipベースの距離が異なる金銭的価値を表す場合があります。
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>
/// CCI based strategy with martingale-style entry.
/// Buys when CCI crosses above oversold level, sells when CCI crosses below overbought level.
/// </summary>
public class CCIAndMartinStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<decimal> _oversold;

	private decimal? _prevCci;

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

	public int CciPeriod
	{
		get => _cciPeriod.Value;
		set => _cciPeriod.Value = value;
	}

	public decimal Overbought
	{
		get => _overbought.Value;
		set => _overbought.Value = value;
	}

	public decimal Oversold
	{
		get => _oversold.Value;
		set => _oversold.Value = value;
	}

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

		_cciPeriod = Param(nameof(CciPeriod), 27)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI indicator length", "Indicators");

		_overbought = Param(nameof(Overbought), 100m)
			.SetDisplay("Overbought", "CCI overbought level", "Indicators");

		_oversold = Param(nameof(Oversold), -100m)
			.SetDisplay("Oversold", "CCI oversold level", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCci = null;
	}

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

		_prevCci = null;

		var cci = new CommodityChannelIndex { Length = CciPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(cci, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevCci = cciValue;
			return;
		}

		if (_prevCci == null)
		{
			_prevCci = cciValue;
			return;
		}

		var prev = _prevCci.Value;
		_prevCci = cciValue;

		// Buy signal: CCI crosses above oversold level from below
		if (prev < Oversold && cciValue >= Oversold && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Sell signal: CCI crosses below overbought level from above
		else if (prev > Overbought && cciValue <= Overbought && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}