GitHub で見る

XCCI Histogram Vol Direct戦略

概要

XCCI Histogram Vol Direct戦略は、MQL5エキスパートExp_XCCI_Histogram_Vol_Directの移植版です。このシステムはCommodity Channel Index(CCI)にボリュームを掛け合わせ、両系列を設定可能な移動平均で平滑化し、平滑化されたオシレーターの傾きを評価します。ヒストグラムの方向色が反転すると、戦略は動きに逆らうポジションをクローズし、新たな方向にトレードを開きます。ロジックは完成したローソク足のみで動作するため、履歴データとライブデータの両方で決定論的に動作します。

元のエキスパートアドバイザーは、複数のアルゴリズム、ボリュームベースのしきい値バンド、時間シフトされた注文実行を持つ独自の平滑化ライブラリを使用していました。StockSharpポートは設定可能な入力を保持し、利用可能なインジケーターで平滑化の選択を近似し、ハイレベルAPIを使用して同じオープン/クローズシーケンスを実装します。

市場レジームとエッジ

  • ボリューム拡大がモメンタムの急増を伴う市場向けに設計されています。
  • 明確なスイングを持つ時間軸を好みます(デフォルト:2時間ローソク足)が、イントラデイからスイングホライズンまで調整可能です。
  • シグナルは平滑化されたCCI×ボリュームの傾きの変化に反応するため、モメンタムリバーサル検出器として機能します。

インジケーターと処理パイプライン

  1. Commodity Channel Index(CCI) – 選択されたローソク足タイプで期間CciPeriodを使って計算されます。
  2. ボリュームソースTickまたはReal(StockSharpローソク足ではティック数が利用できないため、両方ともローソク足ボリュームにマッピングされます)。
  3. 加重オシレーター – CCIを選択したボリュームストリームで掛け合わせます。
  4. 平滑化 – 選択した移動平均ファミリーを加重オシレーターとロウボリュームの両方に長さSmoothingLengthで適用します。
    • Sma → SimpleMovingAverage
    • Ema → ExponentialMovingAverage
    • Smma → SmoothedMovingAverage
    • Lwma → WeightedMovingAverage
    • Jjma → JurikMovingAverage
    • Jurx → ZeroLagExponentialMovingAverage
    • Parabolic → ArnaudLegouxMovingAverage(フェーズパラメーターはALMAオフセットにマッピング)
    • T3 → TripleExponentialMovingAverage
    • Vidya → ExponentialMovingAverage(最も近い近似値)
    • Ama → KaufmanAdaptiveMovingAverage
  5. 方向色 – 最新の平滑化オシレーター値と前の値を比較します。上昇値は0(強気)、下降値は1(弱気)に色付けされ、等しい値は元のインジケーターバッファーと同様に前の色を継承します。
  6. シグナルメモリ – 戦略がSignalBarで指定されたバーとその前のバーを検査できるよう、最近の色を保存します。

取引ルール

ロング管理

  • エントリー: シグナルバーの色が1(弱気)だが前のバーが0(強気)だった場合、AllowLongEntries = trueで現在のネットポジションがすでにロングでなければロングポジションをオープンします。注文サイズはVolume + |Position|で、ショートエクスポージャーが最初にフラット化されます。
  • エグジット: シグナルバーの前のバーが強気(0)でAllowShortExits = trueの場合、新しい上昇スイングに逆らわないよう、オープンなショートポジションをクローズします。

ショート管理

  • エントリー: シグナルバーの色が前の1の後に0になった場合、AllowShortEntries = trueでアカウントがすでにネットショートでなければショートポジションをオープンします。注文サイズはロングロジックを反映します。
  • エグジット: シグナルバーの前のバーが弱気(1)でAllowLongExits = trueの場合、ロングエクスポージャーをクローズします。

リスクコントロール

  • StopLossPointsTakeProfitPointsは、インストゥルメントのPriceStepを使用して価格点オフセットに変換され、StartProtectionを通じて適用されます。
  • 保護注文はすべてのトレードに対してアクティブ化されます。個別のレグを無効にするには両方の値を0に設定します。

パラメーター参照

パラメーター 説明 デフォルト
CciPeriod Commodity Channel Indexの長さ。 14
Smoothing オシレーターとボリュームの平滑化に使用される移動平均ファミリー。 T3
SmoothingLength 平滑化フィルターの期間。 12
SmoothingPhase ALMAオフセットにマッピングされるフェーズ/オフセット値。互換性のために保持。 15
HighLevel2, HighLevel1, LowLevel1, LowLevel2 インジケーターから保存されたしきい値乗数(診断/可視化に有用)。 100, 80, -80, -100
SignalBar シグナルを定義するバーのルックバックインデックス(0 = 最後に閉じたローソク足)。 1
AllowLongEntries / AllowShortEntries 方向へのトレードのオープンを有効/無効にします。 true
AllowLongExits / AllowShortExits 方向へのトレードのクローズを有効/無効にします。 true
StopLossPoints 価格点単位のストップロス距離。 1000
TakeProfitPoints 価格点単位のテイクプロフィット距離。 2000
VolumeSource ボリュームストリーム(TickまたはReal)。このポートでは両方ともローソク足ボリュームを使用します。 Tick
CandleType 分析の時間軸。 2h

ローソク足処理ワークフロー

  1. 設定されたタイプの完成したローソク足を待ちます。
  2. CCI値を計算し、選択したボリュームストリームで掛け合わせます。
  3. 加重CCIとロウボリュームを平滑化フィルターに入力します。
  4. 両方のスムーザーが形成されたら、新しい色を決定してヒストリーバッファーを更新します。
  5. SignalBarSignalBar+1の色を検査して、対立するポジションをクローズするか、新しいトレードをオープンするかを決定します。
  6. 事前設定されたストップロスとテイクプロフィットによりリスク管理を適用します。

使用上の注意

  • ベースのStrategy.Volumeは正の値に設定する必要があります。これが各エントリーのサイズを定義します。
  • StockSharpローソク足はティック数を公開していないため、TickRealの両方のボリュームモードはcandle.TotalVolumeを使用します。ティックレベルのデータが必要な場合は、TotalVolumeフィールドにティックボリュームをエンコードするカスタムローソク足で戦略を供給します。
  • 平滑化フェーズはALMAのみに影響します。他のフィルターでは無視されます。これはMQLインジケーターの動作を反映しており、特定のモードではフェーズ入力を無視します。
  • しきい値乗数(HighLevel*LowLevel*)は完全性のために保持されています。必要に応じて平滑化ボリュームをプロットし、乗数を外部で適用することで視覚化できます。

MQL5バージョンとの制限と違い

  • StockSharpは現在VIDYAとParabolic MAの直接実装を欠いています。EMAとALMAが最も近い代替として使用されます。これにより応答特性は元のカスタムライブラリに類似していますが、完全には一致しません。
  • 注文の実行はシグナルローソク足のクローズ時に即座に行われます。MQLエキスパートはTimeShiftSecを通じて次の期間の開始時にトレードをスケジュールしていました。ブローカーが市場注文をほぼ瞬時に実行する場合、この動作は機能的に同等です。
  • ティックボリュームは、標準のローソク足メッセージでは個々のティック数が公開されていないため、総取引ボリュームで近似されます。

始め方

  1. 戦略を目的のSecurityにアタッチし、シグナルあたりのロット/コントラクト数にVolumeを設定します。
  2. CandleTypeでローソク足の時間軸を選択します(デフォルト:2時間の時間軸)。
  3. 目標市場のボラティリティプロファイルに合わせて平滑化とリスクパラメーターを調整します。
  4. まず紙取引モードで実行し、チャートの平滑化オシレーターを確認し、シグナルが早すぎる・遅すぎる場合はSignalBarを微調整します。

最適化のアイデア

  • CciPeriodとともにSmoothingLengthを最適化して、目標資産との応答性を合わせます。
  • SignalBar01の周辺でストレステストして、速い/遅い反応を確認します。
  • インストゥルメントのATRに適応させるためにStopLossPoints / TakeProfitPointsの拡大・縮小を検討します。
  • 追加の確認が必要な場合、複数の時間軸で戦略を実行し、上位の時間軸のトレンド方向でトレードをフィルタリングします。

安全チェックリスト

  • ライブ実行前にSecurity.PriceStepVolumeがインストゥルメントの契約仕様と一致することを確認します。
  • スリッページを監視し、選択した市場が流動性が低い場合は外部リスクコントロールを調整します。
  • トレードログを定期的に確認して、方向フィルター(Allow*)が意図したエクスポージャーと一致していることを確かめます。
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>
/// XCCI Histogram Vol Direct strategy. Uses CCI zero-line crossover.
/// </summary>
public class XcciHistogramVolDirectStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private decimal? _prevCci;

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

	public XcciHistogramVolDirectStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14).SetGreaterThanZero().SetDisplay("CCI Period", "CCI lookback", "Indicators");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(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); DrawOwnTrades(area); }
	}

	private void ProcessCandle(ICandleMessage candle, decimal cciVal)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!IsFormedAndOnlineAndAllowTrading()) { _prevCci = cciVal; return; }
		if (_prevCci == null) { _prevCci = cciVal; return; }
		if (_prevCci.Value < 0m && cciVal >= 0m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
		else if (_prevCci.Value > 0m && cciVal <= 0m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
		_prevCci = cciVal;
	}
}