GitHub で見る

KWAN CCC戦略

概要

KWAN CCC戦略は、StockSharpの高レベルAPIを使用してMetaTraderエキスパートExp_KWAN_CCC.mq5を再現します。このシステムは、以下のように構築されたカスタムオシレーターからトレーディングシグナルを導出します:

  1. Chaikinオシレーターを計算します(累積/分配ラインの高速と低速移動平均の差)。
  2. ChaikinのValueをCommodity Channel Index(CCI)で乗算します。
  3. 結果をMomentumインジケーターの値で除算します。Momentumがゼロの場合、スクリプトはゼロ除算を避けるために定数値100を代入します — オリジナルコードと全く同じです。
  4. 結果の系列をユーザーが選択したXMAメソッドで平滑化します。
  5. 平滑化された系列の傾きを検出します。上昇バーは0、下降バーは2、それ以外は1で色付けされます。

色が0から他の値に変わると、戦略はショートを閉じてロングポジションを開きます。色が2から他の値に変わると、ロングを閉じてショートを開きます。これはオプションのシグナルシフト(SignalBar)を含むMQLエキスパートに実装されたロジックを反映しています。

トレーディングルール

  • ロングエントリー: SignalBar + 1のバーの色が0に等しく、SignalBarのバーが0と異なる。
  • ショートエントリー: SignalBar + 1のバーの色が2に等しく、SignalBarのバーが2と異なる。
  • ロングエグジット: EnableLongExits = trueでショートエントリー条件がトリガーされた場合に有効。
  • ショートエグジット: EnableShortExits = trueでロングエントリー条件がトリガーされた場合に有効。
  • 保護ストップとターゲット注文は、StopLossPointsTakeProfitPointsに楽器のPriceStepを掛けた絶対的な価格オフセットを使用してStartProtectionを通じて作成されます。

パラメーター

パラメーター 説明
OrderVolume 新しいポジションを開く際に使用する基本注文サイズ。
CandleType すべてのインジケーター計算の時間軸。デフォルトは1時間。
FastPeriod / SlowPeriod Chaikinオシレーター内の移動平均の長さ。
ChaikinMethod 累積/分配ラインに適用する移動平均タイプ(単純、指数、平滑、加重)。
CciPeriod Commodity Channel Indexのピリオド。
MomentumPeriod Momentumインジケーターのピリオド。
SmoothingMethod オリジナルオプションからマッピングされたXMA平滑化メソッド。JurXParabolicT3はJurik MAにフォールバック;VidyaはChande Momentumオシレーター駆動の適応型平滑化を使用;AdaptiveはKaufman AMAを使用。
SmoothingLength 選択した平滑化フィルターで使用するバーの数。
SmoothingPhase 特定のメソッドで使用される追加パラメーター(例:VIDYA CMO長、AMAスロー期間)。
SignalBar 色の遷移を評価するために使用するオフセット(完了したバーで)。1はMetaTraderのデフォルトを再現。
EnableLongEntries / EnableShortEntries 対応する方向への新しいポジションの開設を許可または禁止。
EnableLongExits / EnableShortExits インジケーター駆動のポジション決済を許可または禁止。
StopLossPoints / TakeProfitPoints 価格ステップで測定した保護ストップ/ターゲット(無効化するにはゼロに設定)。

実装ノート

  • 戦略は完成したローソク足にのみ作用し、StockSharpのBindヘルパーを使用してローソク足データをインジケーターにストリームします。
  • 平滑化メソッドリストはオリジナルライブラリのXMA実装を反映しています。StockSharpで利用できないメソッドは最も近い代替にマッピングされ、パラメーターテーブルに記載されています。
  • MetaTraderのVolumeType入力は省略されています。StockSharpのローソク足は既に累積/分配ラインで使用される総ボリューム情報をカプセル化しているためです。
  • オリジナルエキスパートのマネー管理はカスタムロットサイジングヘルパーに依存していました。変換ではOrderVolumeで指定された固定ボリュームを前提としています。

使用上のヒント

  • Chaikinオシレーターの動作が重要な場合は、インストゥルメントが意味のあるボリュームデータを提供していることを確認してください。流動性の低いインストゥルメントの場合は、ノイズを減らすためにMomentumPeriodを増やすことを検討してください。
  • 平滑化パラメーターを最適化する際は、SmoothingLengthSmoothingPhaseを慎重に組み合わせてください:極端な組み合わせはシグナルをかなり遅延させる可能性があります。
  • デフォルトの保護値(StopLossPoints = 1000TakeProfitPoints = 2000)は大きなオフセットに対応しています。インストゥルメントのティックサイズに合わせて調整してください。
namespace StockSharp.Samples.Strategies;

using System;

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

/// <summary>
/// Strategy converted from the KWAN_CCC expert advisor.
/// Uses CCI and Momentum to detect trend transitions.
/// Enters long when CCI turns up while momentum is positive,
/// enters short when CCI turns down while momentum is negative.
/// </summary>
public class KwanCccStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;

	private decimal _prevCci;
	private decimal _prevClose;
	private bool _initialized;

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

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

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCci = 0m;
		_prevClose = 0m;
		_initialized = false;
	}

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

		_prevCci = 0m;
		_prevClose = 0m;
		_initialized = false;

		var cci = new CommodityChannelIndex { Length = CciPeriod };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(cci, (ICandleMessage candle, decimal cciValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (!_initialized)
				{
					_prevCci = cciValue;
					_prevClose = candle.ClosePrice;
					_initialized = true;
					return;
				}

				var closeUp = candle.ClosePrice > _prevClose;
				var closeDown = candle.ClosePrice < _prevClose;

				// Buy when CCI crosses into positive territory and price confirms the move.
				if (_prevCci <= 0m && cciValue > 0m && closeUp && Position <= 0)
				{
					BuyMarket();
				}
				// Sell when CCI crosses into negative territory and price confirms the move.
				else if (_prevCci >= 0m && cciValue < 0m && closeDown && Position >= 0)
				{
					SellMarket();
				}

				_prevCci = cciValue;
				_prevClose = candle.ClosePrice;
			})
			.Start();

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