Exp Moving Average FN-Strategie
Diese Strategie handelt auf Basis von Richtungsumkehrungen der Steigung eines exponentiellen gleitenden Durchschnitts (EMA). Sie geht Long, wenn die EMA nach einem Rückgang nach oben dreht, und Short, wenn die EMA nach einem Anstieg nach unten dreht. Optionale Stop-Loss- und Take-Profit-Level werden in absoluten Preiseinheiten definiert.
Details
- Einstiegskriterien:
- Long: Die EMA-Steigung wechselt von fallend zu steigend.
- Short: Die EMA-Steigung wechselt von steigend zu fallend.
- Long/Short: Beide.
- Ausstiegskriterien:
- Entgegengesetzte Steigungsumkehr.
- Stop-Loss oder Take-Profit erreicht.
- Stops: Ja, mit absoluten Preisabständen.
- Standardwerte:
EMA Length= 12Stop Loss= 1000Take Profit= 2000Candle Type= 4-Stunden-Zeitrahmen
- Filter:
- Kategorie: Trendfolge
- Richtung: Beide
- Indikatoren: Einzeln (EMA)
- Stops: Ja
- Komplexität: Moderat
- Zeitrahmen: Mittelfristig
- Saisonalität: Nein
- Neuronale Netze: 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>
/// EMA slope reversal with absolute stop loss and take profit protection.
/// </summary>
public class ExpMovingAverageFnStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private decimal _prevEma;
private decimal _prevPrevEma;
private int _count;
public int Length { get => _length.Value; set => _length.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public ExpMovingAverageFnStrategy()
{
_length = Param(nameof(Length), 12)
.SetGreaterThanZero()
.SetDisplay("EMA Length", "EMA period", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_stopLoss = Param(nameof(StopLoss), 1000m)
.SetDisplay("Stop Loss", "Absolute price distance from entry", "Risk");
_takeProfit = Param(nameof(TakeProfit), 2000m)
.SetDisplay("Take Profit", "Absolute price distance from entry", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevEma = 0;
_prevPrevEma = 0;
_count = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = Length };
SubscribeCandles(CandleType)
.Bind(ema, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(TakeProfit, UnitTypes.Absolute),
stopLoss: new Unit(StopLoss, UnitTypes.Absolute));
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
_count++;
if (_count < 3)
{
_prevPrevEma = _prevEma;
_prevEma = emaValue;
return;
}
var turnUp = _prevEma < _prevPrevEma && emaValue > _prevEma;
var turnDown = _prevEma > _prevPrevEma && emaValue < _prevEma;
if (turnUp && Position <= 0)
{
if (Position < 0)
BuyMarket(-Position);
BuyMarket(Volume);
}
else if (turnDown && Position >= 0)
{
if (Position > 0)
SellMarket(Position);
SellMarket(Volume);
}
_prevPrevEma = _prevEma;
_prevEma = emaValue;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class exp_moving_average_fn_strategy(Strategy):
def __init__(self):
super(exp_moving_average_fn_strategy, self).__init__()
self._length = self.Param("Length", 12) \
.SetDisplay("EMA Length", "EMA period", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._stop_loss = self.Param("StopLoss", 1000.0) \
.SetDisplay("Stop Loss", "Absolute price distance from entry", "Risk")
self._take_profit = self.Param("TakeProfit", 2000.0) \
.SetDisplay("Take Profit", "Absolute price distance from entry", "Risk")
self._prev_ema = 0.0
self._prev_prev_ema = 0.0
self._count = 0
@property
def Length(self):
return self._length.Value
@Length.setter
def Length(self, value):
self._length.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
def OnStarted2(self, time):
super(exp_moving_average_fn_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.Length
self.SubscribeCandles(self.CandleType) \
.Bind(ema, self.ProcessCandle) \
.Start()
self.StartProtection(
takeProfit=Unit(self.TakeProfit, UnitTypes.Absolute),
stopLoss=Unit(self.StopLoss, UnitTypes.Absolute))
def ProcessCandle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
ema_val = float(ema_value)
self._count += 1
if self._count < 3:
self._prev_prev_ema = self._prev_ema
self._prev_ema = ema_val
return
turn_up = self._prev_ema < self._prev_prev_ema and ema_val > self._prev_ema
turn_down = self._prev_ema > self._prev_prev_ema and ema_val < self._prev_ema
if turn_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket(-self.Position)
self.BuyMarket(self.Volume)
elif turn_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket(self.Position)
self.SellMarket(self.Volume)
self._prev_prev_ema = self._prev_ema
self._prev_ema = ema_val
def OnReseted(self):
super(exp_moving_average_fn_strategy, self).OnReseted()
self._prev_ema = 0.0
self._prev_prev_ema = 0.0
self._count = 0
def CreateClone(self):
return exp_moving_average_fn_strategy()