Triple MA
Strategie basierend auf dem Triple Moving Average-Crossover.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 55%. Die Strategie funktioniert am besten im Aktienmarkt.
Triple MA richtet drei gleitende Durchschnitte aus, um die Richtung zu definieren. Wenn der kürzeste Durchschnitt über dem mittleren und langen Durchschnitt liegt, erfolgt ein Long-Einstieg. Die umgekehrte Ausrichtung öffnet Shorts, und ein Kreuzung der kurzen und mittleren Linien schließt den Trade.
Die Verwendung von drei Durchschnitten hilft, Rauschen zu filtern, das in Einzel-MA-Systemen vorhanden ist. Dieser geschichtete Ansatz versucht, Momentum zu bestätigen, bevor man sich zu einem Trade verpflichtet.
Details
- Einstiegskriterien: Signale basierend auf MA.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Gegensätzliches Signal oder Stop.
- Stops: Ja.
- Standardwerte:
ShortMaPeriod= 5MiddleMaPeriod= 20LongMaPeriod= 50StopLossPercent= 2mCandleType= TimeSpan.FromMinutes(5)
- Filter:
- Kategorie: Trend
- Richtung: Beide
- Indikatoren: MA
- Stops: Ja
- Komplexität: Grundlegend
- Zeitrahmen: Intraday (5m)
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// Strategy based on Triple Moving Average crossover.
/// It enters long position when short MA > middle MA > long MA and short position when short MA < middle MA < long MA.
/// </summary>
public class TripleMAStrategy : Strategy
{
private readonly StrategyParam<int> _shortMaPeriod;
private readonly StrategyParam<int> _middleMaPeriod;
private readonly StrategyParam<int> _longMaPeriod;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
// Current state
private bool _prevIsShortAboveMiddle;
private bool _prevIsBullish;
private bool _prevIsBearish;
/// <summary>
/// Period for short moving average.
/// </summary>
public int ShortMaPeriod
{
get => _shortMaPeriod.Value;
set => _shortMaPeriod.Value = value;
}
/// <summary>
/// Period for middle moving average.
/// </summary>
public int MiddleMaPeriod
{
get => _middleMaPeriod.Value;
set => _middleMaPeriod.Value = value;
}
/// <summary>
/// Period for long moving average.
/// </summary>
public int LongMaPeriod
{
get => _longMaPeriod.Value;
set => _longMaPeriod.Value = value;
}
/// <summary>
/// Stop-loss percentage.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize the Triple MA strategy.
/// </summary>
public TripleMAStrategy()
{
_shortMaPeriod = Param(nameof(ShortMaPeriod), 100)
.SetDisplay("Short MA Period", "Period for short moving average", "Indicators")
.SetOptimize(3, 10, 1);
_middleMaPeriod = Param(nameof(MiddleMaPeriod), 250)
.SetDisplay("Middle MA Period", "Period for middle moving average", "Indicators")
.SetOptimize(15, 30, 5);
_longMaPeriod = Param(nameof(LongMaPeriod), 500)
.SetDisplay("Long MA Period", "Period for long moving average", "Indicators")
.SetOptimize(40, 100, 10);
_stopLossPercent = Param(nameof(StopLossPercent), 2m)
.SetDisplay("Stop Loss (%)", "Stop loss as a percentage of entry price", "Risk parameters")
.SetOptimize(1, 3, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevIsShortAboveMiddle = default;
_prevIsBullish = default;
_prevIsBearish = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
var shortMa = new ExponentialMovingAverage { Length = ShortMaPeriod };
var middleMa = new ExponentialMovingAverage { Length = MiddleMaPeriod };
var longMa = new ExponentialMovingAverage { Length = LongMaPeriod };
// Create subscription and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(shortMa, middleMa, longMa, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, shortMa);
DrawIndicator(area, middleMa);
DrawIndicator(area, longMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal shortMaValue, decimal middleMaValue, decimal longMaValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Check if strategy is ready to trade
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Check the MA alignments
var isShortAboveMiddle = shortMaValue > middleMaValue;
var isMiddleAboveLong = middleMaValue > longMaValue;
// Check for MA crossover
var isShortCrossedMiddle = isShortAboveMiddle != _prevIsShortAboveMiddle;
// Check for alignment conditions
var isBullishAlignment = isShortAboveMiddle && isMiddleAboveLong;
var isBearishAlignment = !isShortAboveMiddle && !isMiddleAboveLong;
// Entry logic based on three MA alignment change
if (isBullishAlignment && !_prevIsBullish && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
}
else if (isBearishAlignment && !_prevIsBearish && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
}
// Update previous state
_prevIsShortAboveMiddle = isShortAboveMiddle;
_prevIsBullish = isBullishAlignment;
_prevIsBearish = isBearishAlignment;
}
}
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 triple_ma_strategy(Strategy):
"""
Strategy based on Triple Moving Average crossover.
Enters long when short MA > middle MA > long MA.
Enters short when short MA < middle MA < long MA.
"""
def __init__(self):
super(triple_ma_strategy, self).__init__()
self._short_ma_period = self.Param("ShortMaPeriod", 100).SetDisplay("Short MA Period", "Period for short moving average", "Indicators")
self._middle_ma_period = self.Param("MiddleMaPeriod", 250).SetDisplay("Middle MA Period", "Period for middle moving average", "Indicators")
self._long_ma_period = self.Param("LongMaPeriod", 500).SetDisplay("Long MA Period", "Period for long moving average", "Indicators")
self._stop_loss_percent = self.Param("StopLossPercent", 2.0).SetDisplay("Stop Loss (%)", "Stop loss as a percentage of entry price", "Risk parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_is_short_above_middle = False
self._prev_is_bullish = False
self._prev_is_bearish = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(triple_ma_strategy, self).OnReseted()
self._prev_is_short_above_middle = False
self._prev_is_bullish = False
self._prev_is_bearish = False
def OnStarted2(self, time):
super(triple_ma_strategy, self).OnStarted2(time)
short_ma = ExponentialMovingAverage()
short_ma.Length = self._short_ma_period.Value
middle_ma = ExponentialMovingAverage()
middle_ma.Length = self._middle_ma_period.Value
long_ma = ExponentialMovingAverage()
long_ma.Length = self._long_ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(short_ma, middle_ma, long_ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, short_ma)
self.DrawIndicator(area, middle_ma)
self.DrawIndicator(area, long_ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, short_val, middle_val, long_val):
if candle.State != CandleStates.Finished:
return
s = float(short_val)
m = float(middle_val)
l = float(long_val)
is_short_above_middle = s > m
is_middle_above_long = m > l
is_bullish = is_short_above_middle and is_middle_above_long
is_bearish = not is_short_above_middle and not is_middle_above_long
if is_bullish and not self._prev_is_bullish and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif is_bearish and not self._prev_is_bearish and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._prev_is_short_above_middle = is_short_above_middle
self._prev_is_bullish = is_bullish
self._prev_is_bearish = is_bearish
def CreateClone(self):
return triple_ma_strategy()