Parabolic SAR Frühkauf-Strategie mit MA-Ausstieg
Diese Strategie handelt Parabolic SAR-Umkehrungen und schließt Long-Positionen frühzeitig, wenn der SAR über den Kurs kippt und der Schlusskurs unter einem gleitenden Durchschnitt mit N Perioden liegt.
Details
- Einstiegskriterien:
- Kreuzung des Kurses mit dem Parabolic SAR.
- Long/Short: Beide.
- Ausstiegskriterien:
- Bei Long-Positionen: SAR über dem Kurs und Schlusskurs unter dem MA (
MaPeriod). - Bei Short-Positionen: gegenläufige SAR-Kreuzung (durch die Einstiegslogik gesteuert).
- Bei Long-Positionen: SAR über dem Kurs und Schlusskurs unter dem MA (
- Stops: Keine.
- Standardwerte:
SarStart= 0.02SarIncrement= 0.02SarMax= 0.2MaPeriod= 11
- Filter:
- Kategorie: Trendfolge
- Richtung: Long & Short
- Indikatoren: Parabolic SAR, SMA
- Stops: Nein
- Komplexität: Niedrig
- Zeitrahmen: Beliebig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Niedrig
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>
/// Parabolic SAR early buy with moving average exit.
/// A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
/// A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
/// </summary>
public class ParabolicSarEarlyBuyMaExitStrategy : Strategy
{
private readonly StrategyParam<decimal> _sarStart;
private readonly StrategyParam<decimal> _sarIncrement;
private readonly StrategyParam<decimal> _sarMax;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevClose;
private decimal? _prevSar;
/// <summary>
/// Initial SAR acceleration factor.
/// </summary>
public decimal SarStart
{
get => _sarStart.Value;
set => _sarStart.Value = value;
}
/// <summary>
/// SAR acceleration factor increment.
/// </summary>
public decimal SarIncrement
{
get => _sarIncrement.Value;
set => _sarIncrement.Value = value;
}
/// <summary>
/// Maximum SAR acceleration factor.
/// </summary>
public decimal SarMax
{
get => _sarMax.Value;
set => _sarMax.Value = value;
}
/// <summary>
/// Period of the exit moving average.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ParabolicSarEarlyBuyMaExitStrategy()
{
_sarStart = Param(nameof(SarStart), 0.02m)
.SetGreaterThanZero()
.SetDisplay("SAR Start", "Initial SAR acceleration factor", "Indicators");
_sarIncrement = Param(nameof(SarIncrement), 0.02m)
.SetGreaterThanZero()
.SetDisplay("SAR Increment", "SAR acceleration factor increment", "Indicators");
_sarMax = Param(nameof(SarMax), 0.2m)
.SetGreaterThanZero()
.SetDisplay("SAR Max", "Maximum SAR acceleration factor", "Indicators");
_maPeriod = Param(nameof(MaPeriod), 11)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Period of the exit moving average", "Indicators");
_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();
_prevClose = null;
_prevSar = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
_prevSar = null;
var sar = new ParabolicSar
{
Acceleration = SarStart,
AccelerationStep = SarIncrement,
AccelerationMax = SarMax
};
var ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sar, ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sar);
DrawIndicator(area, ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal sar, decimal ma)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var prevClose = _prevClose;
var prevSar = _prevSar;
_prevClose = close;
_prevSar = sar;
if (prevClose is not decimal pc || prevSar is not decimal ps)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var crossUp = pc <= ps && close > sar;
var crossDown = pc >= ps && close < sar;
if (crossUp && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (crossDown && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && sar > close && close < ma)
SellMarket(Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ParabolicSar, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class parabolic_sar_early_buy_ma_exit_strategy(Strategy):
"""
Parabolic SAR early buy with moving average exit.
A close crossing above the Parabolic SAR goes long and a close crossing below it goes short, reversing an opposite position.
A long is also closed early when the SAR is above the close and the close is below the MaPeriod simple moving average.
"""
def __init__(self):
super(parabolic_sar_early_buy_ma_exit_strategy, self).__init__()
self._sar_start = self.Param("SarStart", 0.02).SetGreaterThanZero().SetDisplay("SAR Start", "Initial SAR acceleration factor", "Indicators")
self._sar_increment = self.Param("SarIncrement", 0.02).SetGreaterThanZero().SetDisplay("SAR Increment", "SAR acceleration factor increment", "Indicators")
self._sar_max = self.Param("SarMax", 0.2).SetGreaterThanZero().SetDisplay("SAR Max", "Maximum SAR acceleration factor", "Indicators")
self._ma_period = self.Param("MaPeriod", 11).SetGreaterThanZero().SetDisplay("MA Period", "Period of the exit moving average", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_close = None
self._prev_sar = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(parabolic_sar_early_buy_ma_exit_strategy, self).OnReseted()
self._prev_close = None
self._prev_sar = None
def OnStarted2(self, time):
super(parabolic_sar_early_buy_ma_exit_strategy, self).OnStarted2(time)
self._prev_close = None
self._prev_sar = None
sar = ParabolicSar()
sar.Acceleration = Decimal(self._sar_start.Value)
sar.AccelerationStep = Decimal(self._sar_increment.Value)
sar.AccelerationMax = Decimal(self._sar_max.Value)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sar, ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sar)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sar, ma):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
prev_close = self._prev_close
prev_sar = self._prev_sar
self._prev_close = close
self._prev_sar = sar
if prev_close is None or prev_sar is None:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
cross_up = prev_close <= prev_sar and close > sar
cross_down = prev_close >= prev_sar and close < sar
if cross_up and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif cross_down and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and sar > close and close < ma:
self.SellMarket(self.Position)
def CreateClone(self):
return parabolic_sar_early_buy_ma_exit_strategy()