Trend Alexcud
Trend Alexcud 策略通过在三个时间框架上对齐多条简单移动平均线和 Accelerator Oscillator 来寻找强劲的趋势。它由原始的 MQL5 专家 "TREND_alexcud v_2" 转换而来。
系统监控三个时间框架(默认 15 分钟、1 小时、4 小时)。在每个时间框架上计算五条简单移动平均线(周期 5、8、13、21、34)以及 Accelerator Oscillator。当收盘价高于所有均线且 Accelerator 为正时,该时间框架被视为多头;当收盘价低于所有均线且 Accelerator 为负时,该时间框架被视为空头。
只有当三个时间框架意见一致时才会开仓。若全为多头则买入,全为空头则卖出。一旦出现相反信号,策略立即反向。保护性订单由 StockSharp 的内置风险系统管理。
详情
- 入场条件
- 做多:每个时间框架上价格高于所有均线且 Accelerator > 0。
- 做空:每个时间框架上价格低于所有均线且 Accelerator < 0。
- 多空方向:双向。
- 出场条件:出现反向信号时反向开仓。
- 止损:使用内置保护(无默认值)。
- 默认值:
- Timeframe1 = 15m,Timeframe2 = 1h,Timeframe3 = 4h
- 均线周期 = 5、8、13、21、34
- 过滤器:
- 类别:趋势跟随
- 方向:双向
- 指标:多个
- 止损:是
- 复杂度:中等
- 时间框架:多时间框架
- 季节性:无
- 神经网络:无
- 背离:无
- 风险等级:中等
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trend strategy based on multiple EMA alignment.
/// Enters long when price is above all 5 EMAs and short when below all 5 EMAs.
/// </summary>
public class TrendAlexcudStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _ma1;
private readonly StrategyParam<int> _ma2;
private readonly StrategyParam<int> _ma3;
private readonly StrategyParam<int> _ma4;
private readonly StrategyParam<int> _ma5;
private int _previousBias;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
/// <summary>Period of the shortest moving average.</summary>
public int MaPeriod1 { get => _ma1.Value; set => _ma1.Value = value; }
/// <summary>Period of the second moving average.</summary>
public int MaPeriod2 { get => _ma2.Value; set => _ma2.Value = value; }
/// <summary>Period of the third moving average.</summary>
public int MaPeriod3 { get => _ma3.Value; set => _ma3.Value = value; }
/// <summary>Period of the fourth moving average.</summary>
public int MaPeriod4 { get => _ma4.Value; set => _ma4.Value = value; }
/// <summary>Period of the longest moving average.</summary>
public int MaPeriod5 { get => _ma5.Value; set => _ma5.Value = value; }
/// <summary>
/// Constructor.
/// </summary>
public TrendAlexcudStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe", "General");
_ma1 = Param(nameof(MaPeriod1), 5)
.SetGreaterThanZero()
.SetDisplay("MA 1", "Shortest MA period", "Indicators");
_ma2 = Param(nameof(MaPeriod2), 8)
.SetGreaterThanZero()
.SetDisplay("MA 2", "Second MA period", "Indicators");
_ma3 = Param(nameof(MaPeriod3), 13)
.SetGreaterThanZero()
.SetDisplay("MA 3", "Third MA period", "Indicators");
_ma4 = Param(nameof(MaPeriod4), 21)
.SetGreaterThanZero()
.SetDisplay("MA 4", "Fourth MA period", "Indicators");
_ma5 = Param(nameof(MaPeriod5), 34)
.SetGreaterThanZero()
.SetDisplay("MA 5", "Longest MA period", "Indicators");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousBias = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema1 = new ExponentialMovingAverage { Length = MaPeriod1 };
var ema2 = new ExponentialMovingAverage { Length = MaPeriod2 };
var ema3 = new ExponentialMovingAverage { Length = MaPeriod3 };
var ema4 = new ExponentialMovingAverage { Length = MaPeriod4 };
var ema5 = new ExponentialMovingAverage { Length = MaPeriod5 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema1, ema2, ema3, ema4, ema5, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema1);
DrawIndicator(area, ema2);
DrawIndicator(area, ema3);
DrawIndicator(area, ema4);
DrawIndicator(area, ema5);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal v1, decimal v2, decimal v3, decimal v4, decimal v5)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var price = candle.ClosePrice;
var isBull = price > v1 && price > v2 && price > v3 && price > v4 && price > v5;
var isBear = price < v1 && price < v2 && price < v3 && price < v4 && price < v5;
var bias = isBull ? 1 : isBear ? -1 : 0;
if (isBull && _previousBias != 1 && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
else if (isBear && _previousBias != -1 && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
}
_previousBias = bias;
}
}
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
from indicator_extensions import *
class trend_alexcud_strategy(Strategy):
"""Multiple EMA alignment: long when price above all 5 EMAs, short when below all."""
def __init__(self):
super(trend_alexcud_strategy, self).__init__()
self._ma1 = self.Param("MaPeriod1", 5).SetGreaterThanZero().SetDisplay("MA 1", "Shortest MA period", "Indicators")
self._ma2 = self.Param("MaPeriod2", 8).SetGreaterThanZero().SetDisplay("MA 2", "Second MA period", "Indicators")
self._ma3 = self.Param("MaPeriod3", 13).SetGreaterThanZero().SetDisplay("MA 3", "Third MA period", "Indicators")
self._ma4 = self.Param("MaPeriod4", 21).SetGreaterThanZero().SetDisplay("MA 4", "Fourth MA period", "Indicators")
self._ma5 = self.Param("MaPeriod5", 34).SetGreaterThanZero().SetDisplay("MA 5", "Longest MA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Primary timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(trend_alexcud_strategy, self).OnReseted()
self._prev_bias = 0
def OnStarted2(self, time):
super(trend_alexcud_strategy, self).OnStarted2(time)
self._prev_bias = 0
ema1 = ExponentialMovingAverage()
ema1.Length = self._ma1.Value
ema2 = ExponentialMovingAverage()
ema2.Length = self._ma2.Value
ema3 = ExponentialMovingAverage()
ema3.Length = self._ma3.Value
ema4 = ExponentialMovingAverage()
ema4.Length = self._ma4.Value
ema5 = ExponentialMovingAverage()
ema5.Length = self._ma5.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(ema1, ema2, ema3, ema4, ema5, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, ema1)
self.DrawIndicator(area, ema5)
self.DrawOwnTrades(area)
def OnProcess(self, candle, v1, v2, v3, v4, v5):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
is_bull = price > v1 and price > v2 and price > v3 and price > v4 and price > v5
is_bear = price < v1 and price < v2 and price < v3 and price < v4 and price < v5
if is_bull and self._prev_bias != 1 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif is_bear and self._prev_bias != -1 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
if is_bull:
self._prev_bias = 1
elif is_bear:
self._prev_bias = -1
else:
self._prev_bias = 0
def CreateClone(self):
return trend_alexcud_strategy()