GitHub で見る
Exp Iin MA Signal MMRec 戦略
MetaTrader エキスパート「Exp_Iin_MA_Signal_MMRec」のStockSharpポート。戦略は設定可能な移動平均のペア(元のIin_MA_Signalインジケーター)が生成するクロスオーバーシグナルをリッスンし、損失ベースの削減を伴う適応的なポジションサイジングスキームを適用します。
概要
- シグナル生成: 高速と低速の移動平均が選択したキャンドルタイプと適用価格で評価されます。高速平均が低速を上回ったときに買いシグナルが生成され、反対のクロスオーバーで売りシグナルが生成されます。
SignalBarパラメーターは指定された数の完全にクローズされたバー分だけ実行を延期し、MQLバージョンで使用されるインジケーターバッファーのラグを再現します。
- ポジション管理:
BuyPosOpenとSellPosOpenはロングとショートエントリーを有効または無効にします。反対のシグナルが現れ、対応するBuyPosCloseまたはSellPosCloseフラグが有効な場合、戦略は現在のエクスポージャーをクローズするか、直接新しい方向に反転します。
- リスク制御:
StopLossPointsとTakeProfitPointsはSecurity.PriceStepを使用して価格距離に変換され、新しいシグナルを処理する前にキャンドルの極値と照合されます。
- 資金管理: 最後の取引はロングとショートで別々に追跡されます。
BuyTotalTrigger/SellTotalTriggerウィンドウ内の損失取引数がそれぞれの損失しきい値に達すると、戦略はNormalVolumeからReducedVolumeに切り替わります。MoneyModeパラメーターはボリューム値の解釈方法を定義します(固定ロット、残高パーセンテージ、またはstopベースのリスクパーセンテージ)。
パラメーター
FastPeriod, SlowPeriod – 高速と低速移動平均の長さ。
FastType, SlowType – 移動平均のタイプ(Simple、Exponential、Smoothed、Weighted、VolumeWeighted)。
FastPrice, SlowPrice – 各平均の適用価格(Close、Open、High、Low、Median、Typical、Weighted)。
SignalBar – 検出されたシグナルと注文提出の間のクローズバーの数。
BuyPosOpen, SellPosOpen – ロング/ショートポジションを開くためのトグル。
BuyPosClose, SellPosClose – 反対シグナルで既存ポジションをクローズまたは反転するためのトグル。
BuyTotalTrigger, SellTotalTrigger – 損失カウンターのために検査される最近の取引数。
BuyLossTrigger, SellLossTrigger – 削減ボリュームを有効にする検査ウィンドウ内の最小損失数。
NormalVolume, ReducedVolume – プライマリとフォールバックボリューム(またはMoneyModeに応じたリスクファクター)。
StopLossPoints, TakeProfitPoints – インストゥルメントポイントでのストップロスとテイクプロフィット距離。
MoneyMode – ボリューム値の解釈(Lot、Balance、FreeMargin、BalanceRisk、FreeMarginRisk)。残高ベースのモードはPortfolio.CurrentValueを使用し、リスクベースのモードはリスク金額をstop距離で割ります。
CandleType – インジケーター計算に使用されるキャンドルシリーズ。
シグナルロジック
- すべての完了したキャンドルが選択した適用価格で移動平均に供給されます。
- 移動平均の現在値と前の値の差がクロスオーバーイベントを定義します。
- シグナルはキューに入れられ、キューサイズが
SignalBarを超えると最も古いエントリーが実行されます。
- 買いシグナルが実行されると:
- ショートポジションが存在し
SellPosCloseが有効な場合、戦略はそのショートトレードの実現PnLを計算します。次に(BuyPosOpenが有効な場合)ロングに反転するか、単にエクスポージャーをクローズします。
- ポジションが開いておらず
BuyPosOpenが有効な場合、計算されたボリュームで新しいロングが開かれます。
- 売りシグナルは買いのワークフローを反映します。
資金管理の詳細
- 取引履歴は
BuyTotalTrigger / SellTotalTriggerによって制限されるローリングFIFOキューとして保存されます。
- 損失取引(負のPnL)は損失カウンターを増加させます。カウンターが
BuyLossTriggerまたはSellLossTriggerに達すると、次のポジションはReducedVolumeを使用します。
MoneyMode = Lotはボリューム値を生の量として扱います。
MoneyMode = BalanceとFreeMarginは設定値にPortfolio.CurrentValueを掛けて現在のクローズ価格で割り、数量を取得します。
MoneyMode = BalanceRiskとFreeMarginRiskは設定値にPortfolio.CurrentValueを掛けてストップロス距離で割ります。stop距離がゼロの場合、フォールバックは残高パーセンテージ計算と同一です。
- ポートフォリオ情報が利用できない場合、計算されたボリュームはデフォルトでゼロになり、偶発的な注文を避けます。
リスク処理
- ストップロスとテイクプロフィットレベルはエントリー価格とポイント値を使用してすべてのキャンドルで再計算されます。レベルがキャンドル範囲内に触れた場合、新しいシグナルが処理される前にポジションがクローズされます。
- クローズアクションは常に取引結果を記録し、資金管理キューが実際のエグジットと同期したままであることを保証します。
注意事項
StopLossPointsとTakeProfitPointsがインストゥルメントのティックサイズと互換性があることを確認してください;戦略はSecurity.PriceStepでそれらを乗算します。
MoneyModeがポートフォリオデータに依存する場合、戦略はPortfolioオブジェクトがCurrentValueを公開することを期待します。
- アルゴリズムはネットポジション基準で動作します:同時のロングとショートの保有はサポートされていません。
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>
/// Exp Iin MA Signal MMRec strategy. Uses SMA crossover.
/// </summary>
public class ExpIinMaSignalMmrecStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public ExpIinMaSignalMmrecStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8).SetGreaterThanZero().SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21).SetGreaterThanZero().SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal f, decimal s)
{
if (candle.State != CandleStates.Finished) return;
if (_prevFast == null || _prevSlow == null) { _prevFast = f; _prevSlow = s; return; }
var pa = _prevFast.Value > _prevSlow.Value; var ca = f > s;
_prevFast = f; _prevSlow = s;
if (!pa && ca && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (pa && !ca && Position >= 0) { if (Position > 0) SellMarket(); 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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class exp_iin_ma_signal_mmrec_strategy(Strategy):
def __init__(self):
super(exp_iin_ma_signal_mmrec_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 8) \
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(exp_iin_ma_signal_mmrec_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(exp_iin_ma_signal_mmrec_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return exp_iin_ma_signal_mmrec_strategy()