Preisrücksetzer-Strategie
Diese Strategie handelt tägliche Preisgaps. Zu Beginn eines ausgewählten Wochentags vergleicht sie den letzten Schlusskurs mit dem Eröffnungspreis 24 Stunden zuvor. Wenn der Gap größer als der Parameter Corridor ist, wird eine Position in Richtung des Rücksetzers eröffnet:
- Gap nach oben → verkaufen.
- Gap nach unten → kaufen.
Trades verwenden feste Stop-Loss- und Take-Profit-Abstände in Preiseinheiten. Ein Trailing-Stop mit Schritt wird angewendet, nachdem die Position in den Gewinn läuft. Alle Positionen werden gegen Ende des Tages (22:45) geschlossen.
Parameter
Corridor– Gap-Schwellenwert.StopLoss– fester Verlustabstand.TakeProfit– festes Gewinnziel.TrailingStop– Trailing-Abstand.TrailingStep– Bewegung zum Aktualisieren des Trailing.TradingDay– Wochentag für das Eröffnen von Trades (0=Sonntag).CandleType– Zeitrahmen für Berechnungen.
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>
/// Price rollback strategy that detects price gaps (large moves) and trades the pullback.
/// When price gaps up beyond a corridor, it sells expecting rollback.
/// When price gaps down beyond a corridor, it buys expecting rollback.
/// Uses trailing stop and take profit for exits.
/// </summary>
public class PriceRollbackStrategy : Strategy
{
private readonly StrategyParam<decimal> _corridor;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _trailingStop;
private readonly StrategyParam<DataType> _type;
private decimal _prevClose;
private bool _hasPrev;
public decimal Corridor { get => _corridor.Value; set => _corridor.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public decimal TrailingStop { get => _trailingStop.Value; set => _trailingStop.Value = value; }
public DataType CandleType { get => _type.Value; set => _type.Value = value; }
public PriceRollbackStrategy()
{
_corridor = Param(nameof(Corridor), 5000m)
.SetDisplay("Corridor", "Minimum gap size for entry", "General");
_stopLoss = Param(nameof(StopLoss), 500m)
.SetDisplay("Stop Loss", "Stop loss distance", "Risk");
_takeProfit = Param(nameof(TakeProfit), 400m)
.SetDisplay("Take Profit", "Take profit distance", "Risk");
_trailingStop = Param(nameof(TrailingStop), 300m)
.SetDisplay("Trailing Stop", "Trailing stop distance", "Risk");
_type = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0m;
_hasPrev = false;
}
public override IEnumerable<(Security, DataType)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var atr = new AverageTrueRange { Length = 14 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, atr);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (_hasPrev && Position == 0)
{
// Detect strong candle move (body > corridor) - trade rollback
var body = close - candle.OpenPrice;
var bodySize = Math.Abs(body);
if (bodySize > atrValue * 1.5m)
{
// Strong move up - sell expecting rollback
if (body > 0)
{
SellMarket();
}
// Strong move down - buy expecting rollback
else if (body < 0)
{
BuyMarket();
}
}
}
_prevClose = close;
_hasPrev = true;
}
}
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 AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class price_rollback_strategy(Strategy):
def __init__(self):
super(price_rollback_strategy, self).__init__()
self._corridor = self.Param("Corridor", 5000.0)
self._stop_loss = self.Param("StopLoss", 500.0)
self._take_profit = self.Param("TakeProfit", 400.0)
self._trailing_stop = self.Param("TrailingStop", 300.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_close = 0.0
self._entry_price = 0.0
self._trail_price = 0.0
self._has_prev = False
@property
def Corridor(self):
return self._corridor.Value
@Corridor.setter
def Corridor(self, value):
self._corridor.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
@property
def TrailingStop(self):
return self._trailing_stop.Value
@TrailingStop.setter
def TrailingStop(self, value):
self._trailing_stop.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(price_rollback_strategy, self).OnStarted2(time)
self._has_prev = False
self._entry_price = 0.0
self._trail_price = 0.0
self._prev_close = 0.0
atr = AverageTrueRange()
atr.Length = 14
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, self.ProcessCandle).Start()
self.StartProtection(
Unit(2.0, UnitTypes.Percent),
Unit(1.0, UnitTypes.Percent))
def ProcessCandle(self, candle, atr_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
atr_val = float(atr_value)
if self._has_prev and self.Position == 0:
body = close - open_price
body_size = abs(body)
if body_size > atr_val * 1.5:
if body > 0.0:
self.SellMarket()
elif body < 0.0:
self.BuyMarket()
self._prev_close = close
self._has_prev = True
def OnReseted(self):
super(price_rollback_strategy, self).OnReseted()
self._prev_close = 0.0
self._entry_price = 0.0
self._trail_price = 0.0
self._has_prev = False
def CreateClone(self):
return price_rollback_strategy()