GitHub で見る

カラカティカ戦略

概要

Karakatica Strategy は、オリジナルの MetaTrader 4 エキスパート アドバイザー「Exp_karakatica」から移植された中期トレンド追跡システムです。この戦略は、デフォルトで EUR/USD を M15 タイムフレームで取引し、移動平均クロスオーバー モデルでオリジナルの「iKarakatica」インジケーターの動作をエミュレートするカスタム シグナル エンジンを使用します。クロスオーバーはバーごとに再計算され、最も収益性の高い最近の体制に従うために信号周期が継続的に再最適化されます。

この戦略は、現在オープンなポジションがない場合にのみ、成行注文で市場に参入します。プロテクション注文 (ストップロスとテイクプロフィット) は、StockSharp プロテクション サブシステムを通じて自動的に付加されます。

取引ロジック

  1. シグナル生成 – この戦略は、ローソク足終値の単純移動平均 (SMA) を計算します。強気シグナルは、前のローソク足が SMA の下または SMA で終了し、最後に終了したローソク足がその上で終了したときに表示されます。弱気シグナルは、前のローソク足が SMA の上または SMA で閉じ、最新のローソク足がその下で閉じたときに生成されます。シグナルは常に 前の 完了バーで評価され、iKarakatica インジケーターの Shift=1 値を使用した MT4 実装を反映します。
  2. ポジション管理
    • ポジションがオープン中に反対のシグナルが現れた場合、そのポジションは成行注文で直ちにクローズされます。
    • 新しい取引は、ポジションが存在せず、戦略が最適化ステージによってブロックされていない場合にのみ許可されます。同じ方向への連続取引は、市場が反対のシグナルを確認するまでブロックされます。
  3. 注文サイズ – ポジション サイズは、設定された Risk パラメーターから導出されます。このアルゴリズムは、現在のポートフォリオ値に基づいてリスクを希望のボリュームに変換し、それを商品のボリュームステップに合わせて、元のエキスパートアドバイザーのロット計算方法を模倣します。
  4. 貿易保護 – ストップロスとテイクプロフィットの距離は価格ポイントで設定されます。これらは、ポイント値に商品価格ステップを乗算することによって絶対価格に変換されます。

適応的な最適化

エキスパートアドバイザーは、変化する市場の動きに適応するためにシグナル期間を継続的に再最適化します。

  1. この戦略は、ReoptimizeEvery バーごとに、前の OptimizationDepth バーをカバーする履歴シミュレーションを開始します。
  2. ステップ OptimizationStep を持つ範囲 [OptimizationStart, OptimizationEnd] 内の各候補期間について、バックテスターは単純な移動平均クロスオーバー モデルをシミュレートします。
    • シミュレーターはアクティブな仮想ポジションを追跡し、反対のシグナルがトリガーされるたびに利益を更新します。
    • 合計の利益に加えて、ロングトレードとショートトレードに対して個別の利益カウンターが維持されます。
  3. すべての候補をスキャンした後、戦略は次のルールを適用します。
    • ロング利益とショート利益の両方がマイナスの場合、次の最適化サイクルまで両方向の取引が無効になります。
    • ロングとショートの最良の結果が等しい場合は、全体の最良の期間が使用され、両方向が有効なままになります。
    • それ以外の場合は、最も利益が高い方向のみが有効のままとなり、対応する最良の期間が選択されます。

最適化を開始するには、少なくとも OptimizationDepth + OptimizationEnd + 2 個の完了したキャンドルが必要です。十分な履歴が収集されるまで、戦略は取引を遅らせます。

パラメーター

名前 説明 デフォルト 最適化可能
Risk 目標注文量を定義するポートフォリオ値 (1000 ユニットあたり) の割合。 0.5 はい
StopLossPoints 価格ポイントでのストップロス距離。 50 はい
TakeProfitPoints 価格ポイントでの利食い距離。 150 はい
Period 信号生成に使用されるアクティブな SMA 期間。オプティマイザによって自動的に更新されます。 70 はい
OptimizationDepth サンプル内バックテストに使用された過去のバーの数。 250 いいえ
ReoptimizeEvery 完成したバーで測定された最適化実行の頻度。 50 いいえ
OptimizationStart 最適化中に考慮される最小期間。 10 いいえ
OptimizationStep 隣接する期間間のステップ。 5 いいえ
OptimizationEnd 最適化中に考慮される最大期間。 150 いいえ
CandleType ローソク足のデータ型 (デフォルトは 15 分の時間枠)。 M15 タイムフレーム キャンドル いいえ

使用上の注意

  • この戦略は、15 分の時間枠で EUR/USD 向けに設計されました。別の商品に移植する場合は、ポイント値、ボリュームステップ、スプレッドの仮定を確認してください。
  • データ フィードが最良の買値/売値を提供していることを確認してください。これらは、最適化プロセス中に取引スプレッドを推定するために使用されます。相場が利用できない場合、アルゴリズムは単一の価格ステップ スプレッドに戻ります。
  • 最適化ロジックには数百の履歴バーが必要なため、ライブ取引を有効にする前にストラテジーでデータをプリロードできるようにしてください。

ファイル

  • CS/KarakaticaStrategy.cs – StockSharp 戦略の実装。
  • README.md – 英語の説明 (このファイル)。
  • README_ru.md – ロシア語の説明。
  • README_zh.md – 中国語の説明。
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>
/// Karakatica strategy - adaptive SMA crossover with RSI filter.
/// Buys on fast/slow SMA bullish crossover with RSI above 50.
/// Sells on bearish crossover with RSI below 50.
/// </summary>
public class KarakaticaStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public KarakaticaStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 5)
			.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 15)
			.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");

		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetDisplay("RSI Period", "RSI period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
	protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }

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

		_hasPrev = false;

		var fast = new SimpleMovingAverage { Length = FastPeriod };
		var slow = new SimpleMovingAverage { Length = SlowPeriod };
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, rsi, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fast > slow;
		var crossDown = _prevFast >= _prevSlow && fast < slow;

		if (crossUp && rsi > 50 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (crossDown && rsi < 50 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}