GitHub で見る

CCFp通貨強弱戦略

概要

この戦略はクラシックなMetaTrader CCFpエキスパートアドバイザーをStockSharpの高レベルAPIにポートします。7つのUSDベースの主要通貨ペア(EURUSD、GBPUSD、AUDUSD、NZDUSD、USDCAD、USDCHF、USDJPY)の速い・遅い単純移動平均の比率を使用して、8つの主要通貨(USD、EUR、GBP、CHF、JPY、AUD、CAD、NZD)の相対的な強さスコアを計算します。2つの通貨強度の差が設定可能なしきい値を上回ると、戦略は弱い通貨に対して強い通貨を表現する成行ポジションを開設します。

実装は推奨された高レベルアーキテクチャに従っています:各インストゥルメントには独自のローソク足サブスクリプションがあり、インジケーターはBindを通じてバインドされ、注文管理は成行注文でRegisterOrderを使用します。実行された注文のコメントは元の(TOPDOWN)フォーマットを再利用して、MQLバージョンと同じ簿記スタイルを維持します。

必要なインストゥルメント

戦略パラメーターに以下の証券を添付します:

  • EURUSD
  • GBPUSD
  • AUDUSD
  • NZDUSD
  • USDCAD
  • USDCHF
  • USDJPY

7つのペアはすべてCandle Typeパラメーターを通じて設定された同じ時間軸を共有する必要があります。

パラメーター

パラメーター 説明
Fast MA 強度計算に使用される速い移動平均期間。
Slow MA 強度計算に使用される遅い移動平均期間。
Strength Step 新しいシグナルをトリガーするために超えなければならない2つの通貨間の最小差。
Close Opposite 有効にすると、戦略は新しい注文を送る前に反対のポジションをクローズします。
Candle Type インジケーターによって処理されるローソク足シリーズ。
基本Volume 標準のStrategy.Volumeプロパティから取得され、送信された各成行注文に使用されます。

取引ロジック

  1. 7つのUSD主要ペアのそれぞれは独自の単純移動平均ペア(速い・遅い)でサブスクライブされます。
  2. 完了したローソク足が届くたびに、戦略は遅い・速い平均の比率をオリジナルのCCFpインジケーターによって生成されるのと同じ合成強度値に変換します。
  3. 7つのペアすべてが更新された後、8つの通貨強度スコアが再計算されます。
  4. 「top」通貨と「down」通貨の差がStrength Stepレベルを上方に超え、top通貨が上昇しdown通貨が下落している場合、機会が検出されます。
  5. 戦略は強い通貨へのロングエクスポージャーと弱い通貨へのショートエクスポージャーを表現する成行注文を開設します:
    • USDが強い通貨の場合、相手ペアに1つの注文のみが置かれます(例:short EURUSD)。
    • USDが弱い通貨の場合、戦略は強い通貨が基軸通貨であるペアを買います(例:long EURUSD)。
    • 両方の通貨が非USDの場合、戦略は2つの注文を送ります:top通貨のUSDに対するロングとdown通貨のUSDに対するショート。
  6. Close Oppositeが有効で、ターゲットペアにまだ反対のポジションが開いている場合、戦略は新しいトレードに入る前にまず成行クローズ注文を送ります。

リスク管理

  • 戦略は明示的なストップロスまたはテイクプロフィット注文を添付しません;リスク管理はClose Oppositeフラグと手動ポートフォリオ管理ツールによって処理されます。
  • エントリーサイズはVolumeプロパティによって制御されます。口座サイズと各セグメントの希望するエクスポージャーに応じて設定します。

オリジナルMQL実装との違い

  • 通貨強度計算は単一の時間軸でStockSharpのSimpleMovingAverageインジケーターを使用します。MQLインジケーターからのマルチタイムフレーム係数スタッキングは、Fast MASlow MA期間を調整することでエミュレートできます。
  • 保護ストップは自動的にトレーリングされません;代わりに、戦略はエントリー/エグジットロジックの再現に集中し、高度なリスク管理をStockSharpのポートフォリオ層に任せます。
  • 注文ルーティングはMetaTraderトレードオブジェクトの代わりに高レベルのRegisterOrderヘルパーとStockSharpのセキュリティ参照を使用します。
using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// CCFp Currency Strength strategy (simplified). Uses fast/slow EMA crossover
/// to detect momentum shifts, inspired by currency strength comparison.
/// </summary>
public class CcfpCurrencyStrengthStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;

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

	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

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

		_fastLength = Param(nameof(FastLength), 5)
			.SetGreaterThanZero()
			.SetDisplay("Fast Length", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "Indicators");
	}

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

		var emaFast = new ExponentialMovingAverage { Length = FastLength };
		var emaSlow = new ExponentialMovingAverage { Length = SlowLength };

		decimal prevFast = 0, prevSlow = 0;
		var hasPrev = false;

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(emaFast, emaSlow, (ICandleMessage candle, decimal fastVal, decimal slowVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!hasPrev)
				{
					prevFast = fastVal;
					prevSlow = slowVal;
					hasPrev = true;
					return;
				}

				if (!IsFormedAndOnlineAndAllowTrading())
				{
					prevFast = fastVal;
					prevSlow = slowVal;
					return;
				}

				// Fast EMA crosses above slow - bullish
				if (prevFast <= prevSlow && fastVal > slowVal && Position <= 0)
					BuyMarket();
				// Fast EMA crosses below slow - bearish
				else if (prevFast >= prevSlow && fastVal < slowVal && Position >= 0)
					SellMarket();

				prevFast = fastVal;
				prevSlow = slowVal;
			})
			.Start();

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