GitHub で見る
Color JJRSX トレンド戦略
概要
この戦略はStockSharpの高レベルフレームワーク内でMetaTraderエキスパートアドバイザーExp_ColorJJRSXを再構想します。元のシステムはトレンドの変化を検出するためにJurik平滑化技術を組み合わせたプロプライエタリなColorJJRSXオシレーターに依存しています。このポートでは、オシレーターはJurik移動平均(JMA)でさらに平滑化された標準的な相対力指数(RSI)で近似されています。平滑化されたオシレーターの傾きは、エントリーとエグジットをトリガーするために複数の履歴バーにわたって評価されます。
取引は設定可能なローソク足の時間軸(デフォルトは4時間足)で行われ、ロングとショート操作のための独立したトグルをサポートします。追加パラメーターにより、ソースエキスパートアドバイザーと同一の終了ロジックを保持しながら、ポイントベースのストップロスやテイクプロフィットなどのStockSharpネイティブのリスク管理を導入できます。
インジケーター構築
- RSI近似 –
JurxPeriodで定義された期間のRelativeStrengthIndexは元のJurX平滑化ステージを置き換えます。これにより、相対的なモメンタムをキャプチャしながらオシレーターが0から100の間に留まります。
- Jurik平滑化 – RSI出力は
JurikMovingAverage(長さJmaPeriod)を通過します。結果の系列は過度なラグなしにモメンタムの変化に迅速に反応する滑らかな曲線です。
- 履歴ウィンドウ – 戦略はMQLからの
CopyBufferの使用を複製するために最新のSignalBar + 3個のJMA値を保存します。SignalBar、SignalBar + 1、およびSignalBar + 2でインデックスされた値は、シグナル評価のためにソースエキスパートで使用されるバーに対応します。
トレードロジック
- 強気セットアップ
JMA[SignalBar + 1] < JMA[SignalBar + 2]は、前のバーでオシレーターが上向きに転換したことを確認します。
JMA[SignalBar] > JMA[SignalBar + 1]は、最後の閉じたバーで上昇モメンタムが続いていることを示します。
- ロングエントリーが有効でアクティブなロングポジションがない場合、戦略は
OrderVolumeユニットを買います。既存のショートエクスポージャーは自動的に反転されます。
- 弱気セットアップ
JMA[SignalBar + 1] > JMA[SignalBar + 2]は下向きの転換を確認します。
JMA[SignalBar] < JMA[SignalBar + 1]は継続的な下降モメンタムを検証します。
- ショートエントリーが有効な場合、戦略は
OrderVolumeユニットを売り、既存のロングエクスポージャーを反転させます。
- エグジットルール
- 平滑化されたオシレーターの傾きがポジションに反して転換した時(
AllowBuyClose / AllowSellClose)、オープントレードがマーケットでクローズされます。
- 保護的なストップロスとテイクプロフィットのレベル(価格ポイントで表現)は新しいポジションごとに再計算されます。ローソク足の範囲がレベルに触れると、ポジションが即座にクローズされます。
リスク管理
StopLossPointsはインストゥルメントの価格ステップで価格距離に変換され、不利な動きから保護します。
TakeProfitPointsは対称的なターゲット距離を定義します。
- ストップとターゲットはゼロに設定されると自動的に無効になります。
- ボリュームは
OrderVolumeを通じてベース戦略ボリュームとは独立して調整できます。
パラメーター
| 名前 |
説明 |
JurxPeriod |
Jurik平滑化前に使用されるRSI近似の期間。MQLエキスパートのJurX期間を反映。 |
JmaPeriod |
RSI出力に適用されるJurik移動平均の長さ。 |
SignalBar |
評価に使用される履歴バーのインデックス(1 = 前の閉じたバー)。値が大きいほどシグナル確認が遅れます。 |
EnableBuy / EnableSell |
ロングまたはショートエントリーを独立してトグル。 |
AllowBuyClose / AllowSellClose |
ロングおよびショートポジションそれぞれの傾きベースのエグジットシグナルを有効化。 |
OrderVolume |
各新規エントリーで取引されるボリューム。完全な反転を実行するために既存の反対エクスポージャーが新しい注文に追加されます。 |
TakeProfitPoints / StopLossPoints |
インストゥルメントポイントでの利益目標とストップ距離。無効にするにはゼロに設定。 |
CandleType |
インジケーター計算に使用するローソク足の時間軸(デフォルト4時間足)。 |
元のエキスパートアドバイザーとの違い
- プロプライエタリなJurXアルゴリズムはStockSharpで利用できないため、JurX平滑化は古典的なRSIで近似されます。パラメーター名は移行を簡単にするために一貫して保たれています。
- MetaTraderのスリッページ(
Deviation_)とマネーマネジメントの列挙は再現されません。代わりに固定のOrderVolumeパラメーターが提供されます;必要に応じてStockSharpのポジションサイジングモジュールと組み合わせることができます。
- 注文は
BuyMarket/SellMarketで実行され、ストップロスとテイクプロフィットは完成したローソク足の価格チェックを通じてエミュレートされます。
使用上のヒント
- 戦略を希望のインストゥルメントに添付し、複製したい時間軸に合わせて
CandleTypeを設定します。
- 市場の反応性に合わせて
JurxPeriodとJmaPeriodを調整します。値が高いほど滑らかな振動と少ないシグナルが生成されます。
- デフォルトの1バー遅延と比較して追加の確認ラグが必要な場合は
SignalBarを調整します。
- リスク許容度に応じて
OrderVolume、StopLossPoints、TakeProfitPointsを設定します。自動エグジットを無効にするにはゼロを使用します。
- オシレーターの動作をリアルタイムで監視するために、StockSharpの組み込みログや(ローソク足+インジケータープロット用にすでに配線されている)チャートヘルパーと組み合わせます。
戦略は元のColorJJRSXシステムの意図に忠実を保ちながら、StockSharp環境内での裁量的な実験と自動バックテストの両方の準備が整っています。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class ColorJjrsxTrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private decimal? _prevRsi;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public ColorJjrsxTrendStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14).SetGreaterThanZero().SetDisplay("RSI Period", "RSI lookback", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevRsi = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevRsi = null;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevRsi = rsiVal; return; }
if (_prevRsi == null) { _prevRsi = rsiVal; return; }
if (_prevRsi.Value < 45m && rsiVal >= 55m && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevRsi.Value > 55m && rsiVal <= 45m && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
_prevRsi = rsiVal;
}
}
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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class color_jjrsx_trend_strategy(Strategy):
def __init__(self):
super(color_jjrsx_trend_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI lookback", "Indicators")
self._prev_rsi = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
def OnReseted(self):
super(color_jjrsx_trend_strategy, self).OnReseted()
self._prev_rsi = None
def OnStarted2(self, time):
super(color_jjrsx_trend_strategy, self).OnStarted2(time)
self._prev_rsi = None
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if self._prev_rsi is None:
self._prev_rsi = rv
return
if self._prev_rsi < 45.0 and rv >= 55.0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_rsi > 55.0 and rv <= 45.0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_rsi = rv
def CreateClone(self):
return color_jjrsx_trend_strategy()