ホーム
/
戦略のサンプル
GitHub で見る
iCHO トレンド CCIDualOnMA フィルター戦略
この戦略は、MetaTrader エキスパート アドバイザ 「iCHO Trend CCIDualOnMA Filter」 の上位レベルの StockSharp 移植です。これは、チャイキン オシレーターのゼロライン レジーム フィルターと、平滑化された価格系列に基づいて計算されるデュアル コモディティ チャネル インデックス (CCI) 確認を組み合わせています。その結果、モメンタムの変化に反応するトレンド追跡アプローチが得られますが、それでも取引に入る前に CCI ペアからのモメンタムの確認が必要です。
取引ロジック
チャイキン オシレーター コア – 累積/分配ラインは、構成可能な 2 つの移動平均によって平滑化されます。それらの違いはチャイキン発振器を再現します。ゼロを上回る/下のクロスは、支配的な資本フローの変化を示します。
デュアル CCI フィルター – 両方の CCI インスタンスは同じ移動平均平滑化価格入力を使用しますが、異なるルックバック期間を使用します。長いセットアップでは、チャイキン オシレーターがゼロ以上に留まる間に、高速の CCI がマイナス領域から回復し、低速の CCI を超える必要があります。短いセットアップはこれらの条件を反映します。
オプションのリバーサル – オリジナルの EA は、ロング信号とショート信号を交換する「リバース」フラグを提供します。ポートではこの動作が維持されるため、同じルールを逆トレンド テストに使用できます。
ポジション管理 – オプションのフラグは、新しいポジションをオープンする前に反対側のエクスポージャーをクローズし、戦略を 1 つのオープン ポジションに制限します。 MetaTrader の実装を模倣するために、バーごとに 1 つの取引ルールが適用されます。
セッションフィルター – 取引は、真夜中を過ぎるラップアラウンドセッションを含む、ユーザー定義の日中ウィンドウに制限できます。
パラメーター
パラメータ
説明
FastChaikinLength
Chaikin オシレーター内で使用される高速移動平均期間。
SlowChaikinLength
チャイキン オシレーター内で使用される低速移動平均期間。
ChaikinMethod
移動平均法(単純、指数関数、平滑化、線形重み付け)を累積/分配線に適用します。
FastCciLength
高速コモディティ・チャネル指数の振り返り。
SlowCciLength
低調な商品チャネル指数の振り返り。
MaLength
CCI をフィードする前処理移動平均の長さ。
MaMethod
CCI に到達する前に価格を前処理するために使用される移動平均法。
MaPrice
CCI の前に平滑化される価格タイプ (終値、始値、高値、安値、中央値、標準、加重)。
UseClosedBar
完全に完成したキャンドルのみを処理します(デフォルトは true、EA の SignalsBarCurrent=bar_1 と同じ)。
ReverseSignals
ロングロジックとショートロジックを交換します。
CloseOpposite
新しいポジションに入る前に、オープンポジションを反対方向に閉じてください。
OnlyOnePosition
常に 1 つのオープンポジションのみを許可します。
TradeMode
約定をロング、ショート、またはその両方に制限します (BuyOnly、SellOnly、BuyAndSell)。
UseTimeFilter
取引セッションフィルターを有効にします。
StartHour, StartMinute, EndHour, EndMinute
交換時間で表されるセッション境界 (開始を含み、終了は除く)。ラップアラウンドセッションがサポートされています。
CandleType
インジケーターをフィードするローソク足サブスクリプションの時間枠。
注意事項
この戦略では、高レベルの SubscribeCandles バインディングと組み込みインジケーターのみが使用されます。カスタム バッファーや履歴リクエストは必要ありません。
すべての価格ベースの計算では、平滑化された価格系列を CCI に供給することにより、MetaTrader CCIDualOnMA インジケーターと同じ移動平均前処理が採用されます。
デフォルトのパラメータは、元の EA のデフォルトを再現します。Chaikin 3/10 EMA、CCI 期間 14 と 50、12 期間の SMA 前処理、および 10:01 から 15:02 までの取引ウィンドウです。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Combines a Chaikin oscillator zero-line filter with CCI confirmation.
/// Buys when Chaikin crosses above zero and CCI is rising, sells on opposite.
/// </summary>
public class iCHO_Trend_CCIDualOnMA_FilterStrategy : Strategy
{
private readonly StrategyParam<int> _cciLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private decimal? _prevCci;
private decimal? _prevPrevCci;
private int _candlesSinceTrade;
public int CciLength
{
get => _cciLength.Value;
set => _cciLength.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public decimal CciLevel
{
get => _cciLevel.Value;
set => _cciLevel.Value = value;
}
public int SignalCooldownCandles
{
get => _signalCooldownCandles.Value;
set => _signalCooldownCandles.Value = value;
}
public iCHO_Trend_CCIDualOnMA_FilterStrategy()
{
_cciLength = Param(nameof(CciLength), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Length", "CCI period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Primary candle series", "Data");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold for entry", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 4)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between entries", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevCci = null;
_prevPrevCci = null;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCci = null;
_prevPrevCci = null;
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciLength };
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 (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (_prevCci.HasValue && _prevPrevCci.HasValue)
{
if (_prevPrevCci.Value < -CciLevel && _prevCci.Value < -CciLevel && cciValue > -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (_prevPrevCci.Value > CciLevel && _prevCci.Value > CciLevel && cciValue < CciLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
_prevPrevCci = _prevCci;
_prevCci = cciValue;
}
}
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 i_cho__trend_cci_dual_on_ma__filter_strategy(Strategy):
def __init__(self):
super(i_cho__trend_cci_dual_on_ma__filter_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._cci_length = self.Param("CciLength", 14)
self._cci_level = self.Param("CciLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 4)
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = 4
self._has_two = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciLength(self):
return self._cci_length.Value
@CciLength.setter
def CciLength(self, value):
self._cci_length.Value = value
@property
def CciLevel(self):
return self._cci_level.Value
@CciLevel.setter
def CciLevel(self, value):
self._cci_level.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(i_cho__trend_cci_dual_on_ma__filter_strategy, self).OnReseted()
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_two = False
def OnStarted2(self, time):
super(i_cho__trend_cci_dual_on_ma__filter_strategy, self).OnStarted2(time)
self._prev_cci = 0.0
self._prev_prev_cci = 0.0
self._candles_since_trade = self.SignalCooldownCandles
self._has_two = False
cci = CommodityChannelIndex()
cci.Length = self.CciLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
cci_val = float(cci_value)
level = float(self.CciLevel)
if self._has_two:
# Both prev_prev and prev were below -level, now crossing above -level
if self._prev_prev_cci < -level and self._prev_cci < -level and cci_val > -level and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
# Both prev_prev and prev were above +level, now crossing below +level
elif self._prev_prev_cci > level and self._prev_cci > level and cci_val < level and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
self._prev_prev_cci = self._prev_cci
self._prev_cci = cci_val
if not self._has_two:
if self._prev_prev_cci != 0.0 or self._prev_cci != 0.0:
self._has_two = True
def CreateClone(self):
return i_cho__trend_cci_dual_on_ma__filter_strategy()