Psi Proc EMA MACD戦略
この戦略はオリジナルのMQLエキスパートe-PSI@PROC.mq4のT4システムを再現します。複数の指数移動平均線の並びとMACDフィルターに基づいて取引します。
戦略ロジック
- 各受信ローソク足でEMA(200)、EMA(50)、EMA(10)を計算する。
- パラメーター12、26、9でMACDを計算する。
- 以下の条件でロングに入る:
- EMA200が上昇中でEMA50 > EMA200。
- EMA50が上昇中でEMA10 > EMA50。
- MACDが上昇中で
LimitMACDを上回る。
- 以下の条件でショートに入る:
- EMA200が下降中でEMA50 < EMA200。
- EMA50が下降中でEMA10 < EMA50。
- MACDが下降中で
-LimitMACDを下回る。
- 価格がEMA50を下回って引けるとロングを決済する。
- 価格がEMA50を上回って引けるとショートを決済する。
オプションのテイクプロフィットとトレーリングストップの保護がサポートされています。
パラメーター
| 名前 | 説明 |
|---|---|
LimitMACD |
エントリーを許可する最小絶対MACDレベル。 |
TakeProfitPoints |
価格ポイント単位のテイクプロフィットレベル。 |
TrailStopPoints |
価格ポイント単位のトレーリングストップレベル。 |
CandleType |
戦略が使用するローソク足の時間軸。 |
注意事項
- 取引は成行注文で建てられます。
- 完了したローソク足のみが処理されます。
- 戦略は単一の銘柄で動作します。
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>
/// Strategy based on multiple EMA alignment with MACD confirmation.
/// Buys when EMA10 > EMA50 > EMA200 and MACD positive.
/// Sells on opposite alignment.
/// </summary>
public class PsiProcEmaMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private decimal _prevEma200;
private decimal _prevEma50;
private decimal _prevEma10;
private bool _initialized;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PsiProcEmaMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevEma200 = 0;
_prevEma50 = 0;
_prevEma10 = 0;
_initialized = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema200 = new ExponentialMovingAverage { Length = 50 };
var ema50 = new ExponentialMovingAverage { Length = 20 };
var ema10 = new ExponentialMovingAverage { Length = 10 };
var macd = new MovingAverageConvergenceDivergence();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema200, ema50, ema10, macd, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema200, decimal ema50, decimal ema10, decimal macdVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!_initialized)
{
_prevEma200 = ema200;
_prevEma50 = ema50;
_prevEma10 = ema10;
_initialized = true;
return;
}
// Entry/reversal conditions - EMA alignment
if (ema10 > ema50 && Position <= 0)
BuyMarket();
else if (ema10 < ema50 && Position >= 0)
SellMarket();
_prevEma200 = ema200;
_prevEma50 = ema50;
_prevEma10 = ema10;
}
}
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, MovingAverageConvergenceDivergence
from StockSharp.Algo.Strategies import Strategy
class psi_proc_ema_macd_strategy(Strategy):
def __init__(self):
super(psi_proc_ema_macd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._prev_ema200 = 0.0
self._prev_ema50 = 0.0
self._prev_ema10 = 0.0
self._initialized = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(psi_proc_ema_macd_strategy, self).OnReseted()
self._prev_ema200 = 0.0
self._prev_ema50 = 0.0
self._prev_ema10 = 0.0
self._initialized = False
def OnStarted2(self, time):
super(psi_proc_ema_macd_strategy, self).OnStarted2(time)
ema200 = ExponentialMovingAverage()
ema200.Length = 50
ema50 = ExponentialMovingAverage()
ema50.Length = 20
ema10 = ExponentialMovingAverage()
ema10.Length = 10
macd = MovingAverageConvergenceDivergence()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema200, ema50, ema10, macd, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ema200, ema50, ema10, macd_val):
if candle.State != CandleStates.Finished:
return
if not self._initialized:
self._prev_ema200 = ema200
self._prev_ema50 = ema50
self._prev_ema10 = ema10
self._initialized = True
return
# Entry/reversal conditions - EMA alignment
if ema10 > ema50 and self.Position <= 0:
self.BuyMarket()
elif ema10 < ema50 and self.Position >= 0:
self.SellMarket()
self._prev_ema200 = ema200
self._prev_ema50 = ema50
self._prev_ema10 = ema10
def CreateClone(self):
return psi_proc_ema_macd_strategy()