GitHub で見る
マルチタイムフレームEmaアライメント戦略
概要
MultiTimeframeEmaAlignmentStrategy は、フォルダ MQL/7713 の MetaTrader 4 Expert Advisor 1h-4h-1d.mq4 の StockSharp ポートです。オリジナルのロボットは、3 つの時間枠にわたって高速および低速の指数移動平均を調整し、固定ストップロス、テイクプロフィット、およびトレーリングストップレベルによる保護マネー管理を適用します。この C# バージョンは、StockSharp のインジケーター バインディングと高レベルの順序ヘルパーを活用しながら、同じ高レベルのアイデアに従います。
取引ロジック
- この戦略は、M1 (シグナル タイムフレーム)、M5 (中間フィルター)、および M30 (より高いタイムフレームのトレンド確認) の 3 つのローソク足シリーズを同時に購読します。
- 各シリーズは、構成可能な長さ (デフォルトは 8 と 64) を持つ指数移動平均のペア (EMA) をフィードします。
- 強気のセットアップでは、3 つの時間枠すべてで速い EMA が遅い EMA を上回っている必要があります。さらに、速い EMA は勢いを失ってはなりません (現在の値が前の値以上で、かつ
ShiftDepth バー前の値を超えている)。
- 弱気の設定では、3 つの時間枠すべてで高速の EMA が低速の EMA を下回って推移し、高速の EMA の勢いが低下する必要があります。
- アライメントとモメンタムのチェックが満たされた場合、注文は M1 ローソク足の終値でトリガーされます。ロングシグナルは、オープンポジションがない(または既存のショートが最初にクローズされている)場合にのみ許可され、その逆も同様です。
この解釈は、StockSharp の高レベルの API を使用して MT4 条件の意図を再作成します。 MQL の「MA シフト」比較は、EMA の値を数キャンドル分遡って追跡し、勢いがエントリー方向と一致していることを確認する ShiftDepth バッファーを通じてエミュレートされます。
リスク管理
- ポジションサイズは、
TradeVolume パラメータによって制御されます (デフォルトは元の EA と同様に 3 ロット)。
- オプションのストップロスとテイクプロフィットの距離はピップ単位で提供されます。これらは商品の
PriceStep を通じて価格に変換されます (見つからない場合は 0.0001 に戻ります)。
- トレーリング ストップは、取引が十分に進むたびにストップ価格を市場に近づけることで、EA の動作を再現します。
- リスク パラメータは、MQL スクリプトの
StopLossMode、TakeProfitMode、および TrailingStopMode フラグに合わせて個別に切り替えることができます。
パラメーター
| パラメータ |
説明 |
デフォルト |
TradeVolume |
BuyMarket / SellMarket が使用した注文量。 Lots 入力をミラーリングします。 |
3 |
FastLength |
高速回線の場合は EMA 期間。 |
8 |
SlowLength |
低速回線の場合は EMA 期間。 |
64 |
ShiftDepth |
MQL 移動平均シフト比較をエミュレートするために使用される過去のローソク足の数。 |
3 |
UseStopLoss |
固定ストップロスを有効にします。 |
true |
StopLossPips |
ピップ単位で表されるストップロス距離。 |
75 |
UseTakeProfit |
利益確定を可能にします。 |
true |
TakeProfitPips |
利益確定距離をピップスで表します。 |
150 |
UseTrailingStop |
トレーリングストップ管理を有効にします。 |
true |
TrailingStopPips |
ピップ単位のトレーリング距離。 |
30 |
M1CandleType |
シグナル時間枠のローソク足タイプ (デフォルトは 1 分)。 |
1m |
M5CandleType |
中間フィルターのキャンドル タイプ (デフォルトは 5 分)。 |
5m |
M30CandleType |
長い時間枠のローソク式 (デフォルトは 30 分)。 |
30m |
使用上の注意
- ストラテジーを商品にアタッチし、履歴データが 3 つの時間枠すべてで利用可能であることを確認して、EMA バッファーにデータを入力できるようにします。
- 戦略が短期的な勢いを検証できるように、
ShiftDepth パラメーターは少なくとも 2 のままにする必要があります。
UseStopLoss なしで UseTrailingStop がアクティブな場合でも、取引が有利に進むと、トレーリング ロジックはストップ値を初期化します。
- StockSharp はローソク足の終値で実行されるため、特に不安定な市場では、結果が MT4 バージョンのティックごとの実行とは若干異なる場合があります。核となるトレンド調整動作はそのまま残ります。
変換メモ
- インジケーターの計算は、StockSharp の
Bind メカニズムのみに依存します。手動のインジケーター履歴収集は使用されません。
- 注文管理は、直接の
OrderSend 呼び出しではなく、高レベルのヘルパー (BuyMarket、SellMarket) と内部価格追跡を使用して実装されています。
- MQL スクリプトからのメール通知とスリッページ制御は、StockSharp の範囲外であるため省略されます。
ファイル
CS/MultiTimeframeEmaAlignmentStrategy.cs – 主要な C# 戦略の実装。
README_ru.md – ロシア語のドキュメント。
README_zh.md – 中国語のドキュメント。
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>
/// Multi-Timeframe EMA Alignment strategy - fast/slow EMA crossover with trend EMA filter.
/// Buys when fast EMA crosses above slow EMA while close is above trend EMA.
/// Sells when fast EMA crosses below slow EMA while close is below trend EMA.
/// </summary>
public class MultiTimeframeEmaAlignmentStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _trendPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int TrendPeriod { get => _trendPeriod.Value; set => _trendPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MultiTimeframeEmaAlignmentStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_trendPeriod = Param(nameof(TrendPeriod), 100)
.SetDisplay("Trend EMA", "Trend EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var trend = new ExponentialMovingAverage { Length = TrendPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, trend, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal trend)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
if (_prevFast <= _prevSlow && fast > slow && close > trend && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && close < trend && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 multi_timeframe_ema_alignment_strategy(Strategy):
def __init__(self):
super(multi_timeframe_ema_alignment_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._trend_period = self.Param("TrendPeriod", 100).SetDisplay("Trend EMA", "Trend EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def trend_period(self): return self._trend_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(multi_timeframe_ema_alignment_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(multi_timeframe_ema_alignment_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
trend = ExponentialMovingAverage()
trend.Length = self.trend_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, trend, self.process_candle).Start()
def process_candle(self, candle, fast, slow, trend):
if candle.State != CandleStates.Finished: return
close = float(candle.ClosePrice)
f = float(fast); s = float(slow); t = float(trend)
if not self._has_prev:
self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and close > t and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and close < t and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return multi_timeframe_ema_alignment_strategy()