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 |
策略使用的K线周期。 |
说明
- 使用市价单开仓。
- 仅处理已完成的K线。
- 策略仅针对一个标的运行。
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()