GitHub で見る
FT CCI 戦略
この戦略はMetaTrader 5のエキスパートアドバイザー「FT_CCI (barabashkakvn's edition)」をStockSharpに移植したものです。Commodity Channel Index (CCI)を使用してオシレーターが平均から大きく乖離した時の急激な反転を捉えます。システムは元のロジックを再現します:CCIが下限バンドを突き抜けるとロングに転換し、上限バンドを突き抜けるとショートに転換します。オプションのストップロスとテイクプロフィットはpipsで入力され、自動的に価格オフセットに変換されます。
概要
- コア指標: 設定可能な平均化期間を持つCommodity Channel Index(デフォルト14)。
- バイアス: 対称的なロング/ショート。戦略は最大1つのネットポジションを保持し、逆シグナルで反転します。
- 実行: 選択された時間軸の完成したローソク足のクローズ時に成行注文。
- リスク管理: pipsで表されたオプションのストップロスとテイクプロフィットの距離。どちらかの値がゼロの場合、対応する保護は無効化されます。
- デフォルト時間軸: 30分ローソク足(元のエキスパートの
Period()選択に相当)。
仕組み
ロング設定
- 選択した時間軸の完成したローソク足をサブスクライブ。
- 典型的な価格値でCCI指標を更新。
- 最新のCCI値が設定された下限閾値以下(デフォルト -210)の場合:
- 開いているショートポジションをすべてクローズ。
- 設定された取引ボリュームでロングポジションに入るか追加。
- 逆のショート設定が発動するか、ストップロス/テイクプロフィットイベントが発生するか、戦略が手動で停止されるまでポジションを維持。
ショート設定
- 完成したローソク足で同じCCC値を監視。
- 指標が上限閾値以上(デフォルト +210)の場合:
- 開いているロングポジションをすべてクローズ。
- 設定されたボリュームでショートポジションに入るか追加。
- 逆のロング条件が発動するか、保護注文がトレードをクローズするまでショートを保持。
トレード管理
- ストップロスとテイクプロフィットの距離はpipsで定義されます。戦略はそれを検出されたpipサイズ(価格ステップ、3桁と5桁のFXシンボルでは10倍)で乗じて絶対価格オフセットを取得し、StockSharpの組み込み
StartProtectionを有効にします。
- 保護は開始時に一度だけ適用されるため、新しいポジションはすべてその約定価格に対する同じストップとターゲット値を即座に引き継ぎます。
- ポジションの転換は
設定されたボリューム + |現在のポジション|にサイジングされた成行注文で実行され、1回のトランザクションでポジションの反転と新しいポジションの開始が同時に行われます。
パラメーター
| 名前 |
説明 |
| Candle Type |
計算とシグナル生成に使用する時間軸。 |
| Trade Volume |
新しいポジションのロットサイズ。反転トレードのサイジングに現在のポジション値と共に使用。 |
| CCI Period |
Commodity Channel Indexの平均化の長さ。 |
| CCI Upper Threshold |
ショートエントリーをトリガーするCCIレベル。 |
| CCI Lower Threshold |
ロングエントリーをトリガーするCCIレベル。 |
| Stop Loss (pips) |
pipsでの保護ストップまでの距離。無効にするには0に設定。 |
| Take Profit (pips) |
pipsでの利益目標までの距離。無効にするには0に設定。 |
すべてのパラメーターはStockSharpのパラメーターマネージャーで最適化をサポートします。
推奨される使用方法
- 30分から4時間のローソク足が顕著なCCIの極値を生成する流動性の高いFXペアと指数で最も効果を発揮します。
- ±210の閾値はFT_CCIのデフォルトを再現します。値を下げるとシステムはより反応的になり、値を上げると最も極端な反転のみに集中します。
- 証券のメタデータが有効な
PriceStepを公開していることを確認してください。pipコンバーターはpipsを価格オフセットに変換するためにこの値に依存します。
- 戦略はネッティング口座モデル(単一ネットポジション)を前提としています。ヘッジング口座の場合、反転が以前のトレードを完全にフラット化するように取引ボリュームを適切に設定してください。
注意事項
- 取引シグナルが考慮される前に指標が完全に形成されている必要があります。CCIが有効な値を出力するのに十分なデータが集まるまで、初期のローソク足は無視されます。
- ストップロスとテイクプロフィットの注文はオプションです。それらをゼロに設定したままにすると、出口に逆シグナルのみを使用した元のエキスパートアドバイザーの動作が再現されます。
- StockSharpのチャートに戦略を追加すると、ローソク足、CCI指標、および実行されたトレードを視覚化できます。これらの視覚的補助はC#実装で自動的に有効化されます。
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>
/// CCI breakout strategy. Opens long when CCI drops below lower band, shorts when above upper band.
/// </summary>
public class FtCciStrategy : Strategy
{
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _upperThreshold;
private readonly StrategyParam<decimal> _lowerThreshold;
private readonly StrategyParam<DataType> _candleType;
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal UpperThreshold { get => _upperThreshold.Value; set => _upperThreshold.Value = value; }
public decimal LowerThreshold { get => _lowerThreshold.Value; set => _lowerThreshold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FtCciStrategy()
{
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "Averaging period for CCI", "Indicator");
_upperThreshold = Param(nameof(UpperThreshold), 210m)
.SetDisplay("CCI Upper", "CCI level for short entries", "Indicator");
_lowerThreshold = Param(nameof(LowerThreshold), -210m)
.SetDisplay("CCI Lower", "CCI level for long entries", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle Type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, cci);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
if (cciValue <= LowerThreshold && Position <= 0)
BuyMarket();
else if (cciValue >= UpperThreshold && Position >= 0)
SellMarket();
// Exit when CCI returns to zero
if (Position > 0 && cciValue >= 0)
SellMarket();
else if (Position < 0 && cciValue <= 0)
BuyMarket();
}
}
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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class ft_cci_strategy(Strategy):
def __init__(self):
super(ft_cci_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "Averaging period for CCI", "Indicator")
self._upper_threshold = self.Param("UpperThreshold", 210.0) \
.SetDisplay("CCI Upper", "CCI level for short entries", "Indicator")
self._lower_threshold = self.Param("LowerThreshold", -210.0) \
.SetDisplay("CCI Lower", "CCI level for long entries", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle Type", "General")
@property
def cci_period(self):
return self._cci_period.Value
@property
def upper_threshold(self):
return self._upper_threshold.Value
@property
def lower_threshold(self):
return self._lower_threshold.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(ft_cci_strategy, self).OnStarted2(time)
cci = CommodityChannelIndex()
cci.Length = self.cci_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(cci, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, cci)
self.DrawOwnTrades(area)
def on_process(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if cci_value <= self.lower_threshold and self.Position <= 0:
self.BuyMarket()
elif cci_value >= self.upper_threshold and self.Position >= 0:
self.SellMarket()
# Exit when CCI returns to zero
if self.Position > 0 and cci_value >= 0:
self.SellMarket()
elif self.Position < 0 and cci_value <= 0:
self.BuyMarket()
def CreateClone(self):
return ft_cci_strategy()