GitHub で見る
ColorJFatl Digit NN3 MMRec 戦略(StockSharp変換)
この戦略はMetaTrader 5エキスパートExp_ColorJFatl_Digit_NN3_MMRecのStockSharp高レベルポートです。元のロボットはカスタムColorJFatl_Digitインジケーターとマネーマネジメントリカバリールールを使用していました。StockSharpバージョンはコアシグナルエンジンに焦点を当て、異なる時間軸で動作する3つの独立したモジュールを通じて表現しています。
各モジュールは選択した価格ソースにJurik移動平均(JMA)を適用し、その平均の傾斜を監視します。傾斜が正になると、モジュールはそれを強気レジームとして扱い、ショートエクスポージャーを閉じてオプションで新しいロングポジションを開きます。傾斜が負になると、モジュールはショートトレードの鏡像ロジックを実行します。すべてのモジュールは同じポートフォリオを共有し、常に戦略のネットポジションで動作します。
取引ロジック
- 3つの時間軸(デフォルト:1日、8時間、3時間)でローソク足を購読します。
- 完成した各ローソク足に対して:
- ローソク足を設定された適用価格(終値、始値、典型的な価格、DeMark価格など)に変換します。
- Jurik移動平均を通じて値を処理して滑らかな系列を得ます。
- 現在のJMA値と前の値を比較して傾斜方向を決定します。正の傾斜は「上」の状態、負の傾斜は「下」の状態、平坦な傾斜は前の状態を維持します。
- SignalBarの遅延に従って状態をバッファリングし、必要に応じて戦略が歴史的なバーで動作できるようにします(元のエキスパートは遅延シグナルをサポートしていました)。
- モジュールが遷移を検出するたびに:
- 上向き遷移:オプションでショートポジションを閉じ、モジュールボリュームでロングポジションを開きます。
- 下向き遷移:オプションでロングポジションを閉じ、モジュールボリュームでショートポジションを開きます。
- 別のモジュールからの反対シグナルは、有効化フラグに応じてポジションをフラット化または反転させることができます。
ストップと利益はハードコードされていません;代わりに戦略は反対シグナルと安全のためのStockSharpの組み込み保護(StartProtection())に依存しています。
パラメーター
パラメーターはMT5テンプレートを反映するためにモジュールごと(A、B、C)にグループ化されています。各グループは以下の値を公開します:
- CandleType – 受信ローソク足の時間軸。
- JmaLength – Jurik移動平均の期間。
- JmaPhase – ドキュメント用に保存;StockSharpのJMAはフェーズ調整を公開しません。
- SignalBar – シグナルに基づいて行動する前に待つ完成したバーの数(0 = 即時)。
- AppliedPrices – JMAの入力として使用される価格変換(終値、始値、中央値、典型的、加重、単純、四分の一、トレンドフォロー、DeMark)。
- AllowBuyOpen / AllowSellOpen – 対応する方向でポジションを開く権限。
- AllowBuyClose / AllowSellClose – モジュールが反対シグナルを発したときに既存のポジションを閉じる権限。
- Volume – 新しいトレードを開く際にモジュールが使用する注文サイズ。
モジュールは単一のアカウントポジションを共有するため、同時に存在できるのはネットロングまたはネットショートポジションのみです。ポートフォリオがすでに同じ方向のエクスポージャーを持っている間にモジュールがトレードを開こうとすると、注文はスキップされます;反対方向が開いている場合、新しいトレードが配置される前に閉じられます(許可フラグに従います)。
使用上の注意
- 戦略は
GetWorkingSecurities()を通じて設定されたすべての時間軸を購読し、シミュレーションまたはライブ環境が必要なローソク足シリーズを読み込むことを保証します。
- シグナルはバー内の再描画を防ぐために完成したローソク足でのみ動作します。
- AppliedPricesenumは、2つのトレンドフォロー価格バリアントとDeMark価格を含む元のインジケーターのオプションを再現します。
- MQLバージョンのマネーマネジメントリカバリーロジックは再現されていません。代わりに、リスクはStockSharpの保護やモジュールボリュームの調整を通じて管理できます。
- コード内の英語コメントは、メンテナンスと将来のPythonポーティングを容易にするために変換の各ステップを説明しています。
戦略の拡張
- ストップロスまたはテイクプロフィットルールを追加するには、デフォルトの
StartProtection()呼び出しを希望の設定に置き換えます。
SignalModule設定パターンをクローンすることで追加のモジュールを作成できます。
- 高度なポジション管理(例:モジュールごとのエクスポージャーの追跡)には、この基盤の上にStockSharpの子戦略または仮想ポートフォリオを追加できます。
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>
/// Multi-timeframe JMA slope strategy.
/// Three modules monitor different timeframes and react to slope changes of a Jurik MA.
/// </summary>
public class ColorJFatlDigitNn3MmRecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _jmaLength;
private JurikMovingAverage _jma;
private decimal? _prevJma;
private int _prevSignal; // -1 down, 0 neutral, 1 up
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int JmaLength
{
get => _jmaLength.Value;
set => _jmaLength.Value = value;
}
public ColorJFatlDigitNn3MmRecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_jmaLength = Param(nameof(JmaLength), 5)
.SetGreaterThanZero()
.SetDisplay("JMA Length", "Jurik MA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_jma = null;
_prevJma = null;
_prevSignal = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_jma = new JurikMovingAverage { Length = JmaLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_jma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _jma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal jmaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevJma = jmaValue;
return;
}
if (_prevJma == null)
{
_prevJma = jmaValue;
return;
}
var diff = jmaValue - _prevJma.Value;
var signal = diff > 0 ? 1 : diff < 0 ? -1 : _prevSignal;
_prevJma = jmaValue;
if (signal == _prevSignal)
return;
var oldSignal = _prevSignal;
_prevSignal = signal;
if (signal == 1 && oldSignal == -1)
{
// Slope turned up -- close short, open long
if (Position < 0)
BuyMarket();
if (Position <= 0)
BuyMarket();
}
else if (signal == -1 && oldSignal == 1)
{
// Slope turned down -- close long, open short
if (Position > 0)
SellMarket();
if (Position >= 0)
SellMarket();
}
}
}
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 JurikMovingAverage
from StockSharp.Algo.Strategies import Strategy
class color_j_fatl_digit_nn3_mm_rec_strategy(Strategy):
def __init__(self):
super(color_j_fatl_digit_nn3_mm_rec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._jma_length = self.Param("JmaLength", 5) \
.SetDisplay("JMA Length", "Jurik MA period", "Indicators")
self._prev_jma = None
self._prev_signal = 0
@property
def CandleType(self):
return self._candle_type.Value
@property
def JmaLength(self):
return self._jma_length.Value
def OnReseted(self):
super(color_j_fatl_digit_nn3_mm_rec_strategy, self).OnReseted()
self._prev_jma = None
self._prev_signal = 0
def OnStarted2(self, time):
super(color_j_fatl_digit_nn3_mm_rec_strategy, self).OnStarted2(time)
self._prev_jma = None
self._prev_signal = 0
jma = JurikMovingAverage()
jma.Length = self.JmaLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(jma, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, jma)
self.DrawOwnTrades(area)
def _on_process(self, candle, jma_value):
if candle.State != CandleStates.Finished:
return
jv = float(jma_value)
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_jma = jv
return
if self._prev_jma is None:
self._prev_jma = jv
return
diff = jv - self._prev_jma
if diff > 0:
signal = 1
elif diff < 0:
signal = -1
else:
signal = self._prev_signal
self._prev_jma = jv
if signal == self._prev_signal:
return
old_signal = self._prev_signal
self._prev_signal = signal
if signal == 1 and old_signal == -1:
if self.Position < 0:
self.BuyMarket()
if self.Position <= 0:
self.BuyMarket()
elif signal == -1 and old_signal == 1:
if self.Position > 0:
self.SellMarket()
if self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return color_j_fatl_digit_nn3_mm_rec_strategy()