MA mit logistischer Funktion
MA mit logistischer Funktion ist eine Strategie auf Basis gleitender Durchschnitte, die einen schnellen und einen langsamen gleitenden Durchschnitt für Einstiege verwendet und prozentuale oder logistikbasierte Ausstiege unterstützt.
Details
- Daten: Preiskerzen.
- Einstiegskriterien:
- Long: Schlusskurs > schnelle MA und schnelle MA > langsame MA.
- Short: Schlusskurs < schnelle MA und schnelle MA < langsame MA.
- Ausstiegskriterien: Prozentziele oder logistische Wahrscheinlichkeitsschwellen.
- Stops: Prozentuale oder logistik-wahrscheinlichkeitsbasierte Ausstiege.
- Standardwerte:
FastLength= 9SlowLength= 21MaType= MaTypeEnum.EMAExitType= ExitTypeEnum.PercentTakeProfitPercent= 20StopLossPercent= 5LogisticSlope= 10LogisticMidpoint= 0TakeProfitProbability= 0.8StopLossProbability= 0.2
- Filter:
- Kategorie: Trendfolge
- Richtung: Long & Short
- Indikatoren: MA
- Komplexität: Niedrig
- 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>
/// MA crossover strategy with percent-based exits.
/// </summary>
public class MaWithLogisticStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<decimal> _takeProfitPercent;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _fastMa;
private ExponentialMovingAverage _slowMa;
private decimal _entryPrice;
private decimal _prevFast;
private decimal _prevSlow;
private bool _initialized;
private int _cooldown;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public decimal TakeProfitPercent { get => _takeProfitPercent.Value; set => _takeProfitPercent.Value = value; }
public decimal StopLossPercent { get => _stopLossPercent.Value; set => _stopLossPercent.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MaWithLogisticStrategy()
{
_fastLength = Param(nameof(FastLength), 12).SetGreaterThanZero()
.SetDisplay("Fast MA", "Fast MA period", "Indicators");
_slowLength = Param(nameof(SlowLength), 25).SetGreaterThanZero()
.SetDisplay("Slow MA", "Slow MA period", "Indicators");
_takeProfitPercent = Param(nameof(TakeProfitPercent), 8m).SetGreaterThanZero()
.SetDisplay("TP %", "Take profit percent", "Risk");
_stopLossPercent = Param(nameof(StopLossPercent), 5m).SetGreaterThanZero()
.SetDisplay("SL %", "Stop loss percent", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(20).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = default;
_prevFast = default;
_prevSlow = default;
_initialized = false;
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fastMa = new ExponentialMovingAverage { Length = FastLength };
_slowMa = new ExponentialMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(_fastMa, _slowMa, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _fastMa);
DrawIndicator(area, _slowMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_fastMa.IsFormed || !_slowMa.IsFormed)
return;
if (!_initialized)
{
_prevFast = fast;
_prevSlow = slow;
_initialized = true;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevFast = fast;
_prevSlow = slow;
return;
}
var close = candle.ClosePrice;
// MA crossover entry
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
if (crossUp && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_entryPrice = close;
_cooldown = 5;
}
else if (crossDown && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_entryPrice = close;
_cooldown = 5;
}
_prevFast = fast;
_prevSlow = slow;
}
}
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 ma_with_logistic_strategy(Strategy):
"""
MA crossover strategy with percent-based exits.
"""
def __init__(self):
super(ma_with_logistic_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 12).SetDisplay("Fast MA", "Fast MA period", "Indicators")
self._slow_length = self.Param("SlowLength", 25).SetDisplay("Slow MA", "Slow MA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(20))).SetDisplay("Candle Type", "Candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_init = False
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ma_with_logistic_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._is_init = False
self._cooldown = 0
def OnStarted2(self, time):
super(ma_with_logistic_strategy, self).OnStarted2(time)
self._fast_ma = ExponentialMovingAverage()
self._fast_ma.Length = self._fast_length.Value
self._slow_ma = ExponentialMovingAverage()
self._slow_ma.Length = self._slow_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast_ma, self._slow_ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._fast_ma)
self.DrawIndicator(area, self._slow_ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
if not self._fast_ma.IsFormed or not self._slow_ma.IsFormed:
return
fast = float(fast_val)
slow = float(slow_val)
if not self._is_init:
self._prev_fast = fast
self._prev_slow = slow
self._is_init = True
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast
self._prev_slow = slow
return
cross_up = self._prev_fast <= self._prev_slow and fast > slow
cross_down = self._prev_fast >= self._prev_slow and fast < slow
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown = 5
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown = 5
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return ma_with_logistic_strategy()