ホーム
/
戦略のサンプル
GitHub で見る
カラカティカ戦略
概要
Karakatica Strategy は、オリジナルの MetaTrader 4 エキスパート アドバイザー「Exp_karakatica」から移植された中期トレンド追跡システムです。この戦略は、デフォルトで EUR/USD を M15 タイムフレーム で取引し、移動平均クロスオーバー モデルでオリジナルの「iKarakatica」インジケーターの動作をエミュレートするカスタム シグナル エンジンを使用します。クロスオーバーはバーごとに再計算され、最も収益性の高い最近の体制に従うために信号周期が継続的に再最適化されます。
この戦略は、現在オープンなポジションがない場合にのみ、成行注文で市場に参入します。プロテクション注文 (ストップロスとテイクプロフィット) は、StockSharp プロテクション サブシステムを通じて自動的に付加されます。
取引ロジック
シグナル生成 – この戦略は、ローソク足終値の単純移動平均 (SMA) を計算します。強気シグナルは、前のローソク足が SMA の下または SMA で終了し、最後に終了したローソク足がその上で終了したときに表示されます。弱気シグナルは、前のローソク足が SMA の上または SMA で閉じ、最新のローソク足がその下で閉じたときに生成されます。シグナルは常に 前の 完了バーで評価され、iKarakatica インジケーターの Shift=1 値を使用した MT4 実装を反映します。
ポジション管理 –
ポジションがオープン中に反対のシグナルが現れた場合、そのポジションは成行注文で直ちにクローズされます。
新しい取引は、ポジションが存在せず、戦略が最適化ステージによってブロックされていない場合にのみ許可されます。同じ方向への連続取引は、市場が反対のシグナルを確認するまでブロックされます。
注文サイズ – ポジション サイズは、設定された Risk パラメーターから導出されます。このアルゴリズムは、現在のポートフォリオ値に基づいてリスクを希望のボリュームに変換し、それを商品のボリュームステップに合わせて、元のエキスパートアドバイザーのロット計算方法を模倣します。
貿易保護 – ストップロスとテイクプロフィットの距離は価格ポイントで設定されます。これらは、ポイント値に商品価格ステップを乗算することによって絶対価格に変換されます。
適応的な最適化
エキスパートアドバイザーは、変化する市場の動きに適応するためにシグナル期間を継続的に再最適化します。
この戦略は、ReoptimizeEvery バーごとに、前の OptimizationDepth バーをカバーする履歴シミュレーションを開始します。
ステップ OptimizationStep を持つ範囲 [OptimizationStart, OptimizationEnd] 内の各候補期間について、バックテスターは単純な移動平均クロスオーバー モデルをシミュレートします。
シミュレーターはアクティブな仮想ポジションを追跡し、反対のシグナルがトリガーされるたびに利益を更新します。
合計の利益に加えて、ロングトレードとショートトレードに対して個別の利益カウンターが維持されます。
すべての候補をスキャンした後、戦略は次のルールを適用します。
ロング利益とショート利益の両方がマイナスの場合、次の最適化サイクルまで両方向の取引が無効になります。
ロングとショートの最良の結果が等しい場合は、全体の最良の期間が使用され、両方向が有効なままになります。
それ以外の場合は、最も利益が高い方向のみが有効のままとなり、対応する最良の期間が選択されます。
最適化を開始するには、少なくとも 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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class karakatica_strategy(Strategy):
def __init__(self):
super(karakatica_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(karakatica_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(karakatica_strategy, self).OnStarted2(time)
self._has_prev = False
fast = SimpleMovingAverage()
fast.Length = self.fast_period
slow = SimpleMovingAverage()
slow.Length = self.slow_period
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, rsi, self.process_candle).Start()
def process_candle(self, candle, fast, slow, rsi):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast)
slow_val = float(slow)
rsi_val = float(rsi)
if not self._has_prev:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._has_prev = True
return
cross_up = self._prev_fast <= self._prev_slow and fast_val > slow_val
cross_down = self._prev_fast >= self._prev_slow and fast_val < slow_val
if cross_up and rsi_val > 50 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and rsi_val < 50 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return karakatica_strategy()