GitHub で見る
T3MA(MTC)戦略
MetaTrader 4 Expert Advisor T3MA(MTC).mq4 (ディレクトリ MQL/7904) から変換されました。オリジナルのロボットは、「T3MA-ALARM」インジケーターからのシグナルを取引します。二重平滑化指数移動平均を構築し、その曲線の傾きが下降から上昇、またはその逆に反転するたびに注文を出します。 StockSharp ポートは、慣用的な高レベル API と同じロジックをミラーリングします。
取引アイデア
- 選択したローソクの種類と期間を使用して最初の EMA を構築します。
- 同じ期間の 2 番目の EMA でそのシリーズを平滑化します。
- 平滑化された値を前の値と比較します (オプションで
MaShift だけシフト)。
- 傾斜の方向が変わると、戦略は信号を記録します。注文は設定された
CalculationBarOffset 遅延の後に実行され、EA の CalculationBarIndex パラメータが再現されます。
- 各シグナルは、MetaTrader の
LastOrder 変数と同様に、バーの安値 (ロング エントリーの場合) または高値 (ショート エントリーの場合) を一意のマーカーとして使用し、重複取引を回避します。
移植の詳細
- 2 つの
ExponentialMovingAverage インスタンスを使用して、T3MA-ALARM スムージング チェーンをエミュレートします。
MaShift ルックバックをサポートするために、最近平滑化された値の小さなキューを維持します。
- シグナルは FIFO キューに保存され、要求された数のキャンドルが完成した後に実行されます。
- 保護注文は、MetaTrader ポイントに一致する価格ステップで表現された距離を持つ
StartProtection を通じて管理されます。
AllowMultiplePositions フラグは MultiPositions 入力を再現します。無効にすると、ストラテジーは新しい信号に作用する前にネット ポジションがフラットになるまで待機します。
パラメーター
MaPeriod – 両方のスムージング パスに使用される EMA の長さ (デフォルト: 4)。
MaShift – 傾きを比較する前に平滑化シリーズをシフトするバーの数 (デフォルト: 0)。
CalculationBarOffset – シグナルの検出と注文の送信の間の遅延(終了キャンドル単位)(デフォルト: 1)。
TradeVolume – ロット単位の基本注文量 (デフォルト: 1)。
UseStopLoss / StopLossPoints – 価格ステップでのストップロスの有効化と距離 (デフォルト: 有効、40 ステップ)。
UseTakeProfit / TakeProfitPoints – 価格ステップでの利食いの有効化と距離 (デフォルト: 有効、11 ステップ)。
AllowMultiplePositions – 反対側のポジションが開いている場合でも、スタックポジションを許可します (デフォルト: 有効)。
CandleType – インジケーターチェーンにフィードするために使用される時間枠またはデータタイプ (デフォルト: 5 分足ローソク足)。
取引ワークフロー
- 選択したローソク足シリーズを購読し、ダブル EMA チェーンを通じて終値をフィードします。
- 現在の傾斜方向を追跡し、反転したときに信号を生成します。
- MQL4 スクリプトが古いインジケーター バッファを読み取るのと同じように、
CalculationBarOffset のローソク足が完了した直後に実行が行われるように、各シグナル (またはシグナルの欠落) を遅延キューにプッシュします。
- 成熟したシグナルが実行されると、次のようになります。
- 取引が無効になっている場合、プラットフォームの準備ができていない場合、またはネットポジションがすでにオープンしているときに
AllowMultiplePositions がオフになっている場合は、スキップしてください。
- 重複を防ぐために、信号マーカーが以前のものと異なることを確認してください。
- 設定された数量で成行注文 (
BuyMarket/SellMarket) を送信します。有効にすると、保護ストップが自動的に接続されます。
注意事項
- 価格比較では、
LastOrder の類似品をチェックする際の浮動小数点アーチファクトを避けるために、小さな小数許容誤差を使用します。
- この戦略は、
AllowMultiplePositions が無効になっている場合に反対のポジションを自動決済せず、保護的出口に依存した元の EA を模倣します。
- チャート作成サブシステムが存在する場合、ローソク足と自身の取引の視覚化が可能です。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class T3MaMtc9Strategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevEma;
private decimal _prevMom;
private bool _hasPrev;
private int _cooldownRemaining;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public T3MaMtc9Strategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 50).SetDisplay("EMA Period", "EMA lookback", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 14).SetDisplay("Momentum", "Momentum period", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 150).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevEma = default;
_prevMom = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevEma = 0;
_prevMom = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var mom = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, mom, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema, decimal mom)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev) { _prevEma = ema; _prevMom = mom; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevEma = ema;
_prevMom = mom;
return;
}
if (close > ema && _prevMom <= 0 && mom > 0 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (close < ema && _prevMom >= 0 && mom < 0 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevEma = ema;
_prevMom = mom;
}
}
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, Momentum
from StockSharp.Algo.Strategies import Strategy
class t3_ma_mtc9_strategy(Strategy):
def __init__(self):
super(t3_ma_mtc9_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 50) \
.SetDisplay("EMA Period", "EMA lookback", "Indicators")
self._momentum_period = self.Param("MomentumPeriod", 14) \
.SetDisplay("Momentum", "Momentum period", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 150) \
.SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_ema = 0.0
self._prev_mom = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def ema_period(self):
return self._ema_period.Value
@property
def momentum_period(self):
return self._momentum_period.Value
@property
def cooldown_candles(self):
return self._cooldown_candles.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(t3_ma_mtc9_strategy, self).OnReseted()
self._prev_ema = 0.0
self._prev_mom = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(t3_ma_mtc9_strategy, self).OnStarted2(time)
self._prev_ema = 0.0
self._prev_mom = 0.0
self._has_prev = False
self._cooldown_remaining = 0
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
mom = Momentum()
mom.Length = self.momentum_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, mom, self.process_candle).Start()
def process_candle(self, candle, ema, mom):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ema_val = float(ema)
mom_val = float(mom)
if not self._has_prev:
self._prev_ema = ema_val
self._prev_mom = mom_val
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_ema = ema_val
self._prev_mom = mom_val
return
if close > ema_val and self._prev_mom <= 0 and mom_val > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif close < ema_val and self._prev_mom >= 0 and mom_val < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_ema = ema_val
self._prev_mom = mom_val
def CreateClone(self):
return t3_ma_mtc9_strategy()