Strategie basierend auf prozentualem Preismomentum
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 97%. Am besten funktioniert sie auf dem Kryptomarkt.
Momentum Percentage verfolgt die prozentuale Preisveränderung. Trades werden ausgelöst, wenn das Momentum positive oder negative Niveaus überschreitet, und enden bei einem Gegensignal oder einem Volatilitätsstopp.
Durch die Messung von Renditen über einen festgelegten Rückblickzeitraum passt sich das System verschiedenen Märkten an. Der Volatilitätsstopp sorgt dafür, dass große negative Bewegungen schnell beendet werden.
Details
Einstiegskriterien: Signale basierend auf MA, Momentum.
Long/Short: Beide Richtungen.
Ausstiegskriterien: Entgegengesetztes Signal oder Stop.
Stops: Ja.
Standardwerte:
MomentumPeriod = 10
ThresholdPercent = 5m
StopLossPercent = 2m
CandleType = TimeSpan.FromMinutes(5)
Filter:
Kategorie: Trend
Richtung: Beide
Indikatoren: MA, Momentum
Stops: Ja
Komplexität: Grundlegend
Zeitrahmen: Intraday (5m)
Saisonalität: Nein
Neural Networks: Nein
Divergenz: Nein
Risikolevel: Mittel
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 price momentum percentage change.
/// Uses Momentum indicator with SMA trend filter.
/// Buys when momentum crosses above zero and price is above SMA.
/// Sells when momentum crosses below zero and price is below SMA.
/// </summary>
public class MomentumPercentageStrategy : Strategy
{
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevMom;
private bool _hasPrevValues;
private int _cooldown;
/// <summary>
/// Momentum period.
/// </summary>
public int MomentumPeriod
{
get => _momentumPeriod.Value;
set => _momentumPeriod.Value = value;
}
/// <summary>
/// SMA period.
/// </summary>
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="MomentumPercentageStrategy"/>.
/// </summary>
public MomentumPercentageStrategy()
{
_momentumPeriod = Param(nameof(MomentumPeriod), 10)
.SetDisplay("Momentum Period", "Period for momentum calculation", "Indicators")
.SetOptimize(8, 20, 4);
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetDisplay("SMA Period", "Period for SMA trend filter", "Indicators")
.SetOptimize(15, 30, 5);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();
_prevMom = default;
_hasPrevValues = default;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var momentum = new Momentum { Length = MomentumPeriod };
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(momentum, sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, momentum);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal momValue, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (smaValue == 0)
return;
if (!_hasPrevValues)
{
_hasPrevValues = true;
_prevMom = momValue;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevMom = momValue;
return;
}
var price = candle.ClosePrice;
// Momentum crosses above zero + price above SMA = buy
if (_prevMom <= 0 && momValue > 0 && price > smaValue && Position <= 0)
{
var volume = Volume + Math.Abs(Position);
BuyMarket(volume);
_cooldown = 30;
}
// Momentum crosses below zero + price below SMA = sell
else if (_prevMom >= 0 && momValue < 0 && price < smaValue && Position >= 0)
{
var volume = Volume + Math.Abs(Position);
SellMarket(volume);
_cooldown = 30;
}
_prevMom = momValue;
}
}
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 Momentum, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class momentum_percentage_strategy(Strategy):
"""
Momentum Percentage: buys when momentum crosses above zero with price above SMA.
"""
def __init__(self):
super(momentum_percentage_strategy, self).__init__()
self._momentum_period = self.Param("MomentumPeriod", 10).SetDisplay("Momentum Period", "Momentum period", "Indicators")
self._sma_period = self.Param("SmaPeriod", 20).SetDisplay("SMA Period", "SMA trend filter period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._prev_mom = 0.0
self._has_prev = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(momentum_percentage_strategy, self).OnReseted()
self._prev_mom = 0.0
self._has_prev = False
self._cooldown = 0
def OnStarted2(self, time):
super(momentum_percentage_strategy, self).OnStarted2(time)
mom = Momentum()
mom.Length = self._momentum_period.Value
sma = SimpleMovingAverage()
sma.Length = self._sma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(mom, sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, mom)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, mom_val, sma_val):
if candle.State != CandleStates.Finished:
return
mom = float(mom_val)
sma = float(sma_val)
if sma == 0:
return
if not self._has_prev:
self._has_prev = True
self._prev_mom = mom
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_mom = mom
return
price = float(candle.ClosePrice)
if self._prev_mom <= 0 and mom > 0 and price > sma and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._cooldown = 30
elif self._prev_mom >= 0 and mom < 0 and price < sma and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._cooldown = 30
self._prev_mom = mom
def CreateClone(self):
return momentum_percentage_strategy()