Open Drive Strategie
Open Drive bezeichnet eine starke gerichtete Bewegung direkt nach der Markteröffnung, oft nach einem Nachrichtenkatalysator über Nacht. Trader suchen nach hohem Volumen und nachhaltigem Momentum in den ersten Minuten.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 118%. Sie funktioniert am besten am Aktienmarkt.
Die Strategie schließt sich diesem Momentum an, tritt long oder short innerhalb der Eröffnungsspanne ein und zieht den Stop nach, während der Kurs sich ausdehnt.
Positionen werden schnell geschlossen, wenn der Antrieb nachlässt, um Verluste bei unruhigen Eröffnungen klein zu halten.
Details
- Einstiegskriterien: Indikatorsignal
- Long/Short: Beide
- Ausstiegskriterien: Stop-Loss oder entgegengesetztes Signal
- Stops: Ja, prozentbasiert
- Standardwerte:
CandleType= 15 minuteStopLoss= 2%
- Filter:
- Kategorie: Intraday
- Richtung: Beide
- Indikatoren: Price Action
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Intraday
- 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>
/// Implementation of Open Drive trading strategy.
/// Trades on strong gap openings relative to previous close using ATR filter and MA trend.
/// </summary>
public class OpenDriveStrategy : Strategy
{
private readonly StrategyParam<decimal> _atrMultiplier;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private decimal _prevClosePrice;
private decimal _atrValue;
private int _cooldown;
/// <summary>
/// ATR multiplier for gap size.
/// </summary>
public decimal AtrMultiplier
{
get => _atrMultiplier.Value;
set => _atrMultiplier.Value = value;
}
/// <summary>
/// ATR period.
/// </summary>
public int AtrPeriod
{
get => _atrPeriod.Value;
set => _atrPeriod.Value = value;
}
/// <summary>
/// Moving average period.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <summary>
/// Candle type for strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="OpenDriveStrategy"/>.
/// </summary>
public OpenDriveStrategy()
{
_atrMultiplier = Param(nameof(AtrMultiplier), 0.3m)
.SetGreaterThanZero()
.SetDisplay("ATR Multiplier", "Multiplier for ATR to define gap size", "Strategy");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "Period for ATR calculation", "Strategy");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period for trend confirmation", "Strategy");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for strategy", "Strategy");
_cooldownBars = Param(nameof(CooldownBars), 30)
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
.SetRange(5, 500);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClosePrice = 0;
_atrValue = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = MaPeriod };
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, atr, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(3, UnitTypes.Percent),
stopLoss: new Unit(2, UnitTypes.Percent));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
// indicators checked via Bind
_atrValue = atrValue;
var close = candle.ClosePrice;
var open = candle.OpenPrice;
if (_cooldown > 0)
{
_cooldown--;
_prevClosePrice = close;
return;
}
// Detect strong momentum candle (body exceeds ATR * multiplier)
if (_prevClosePrice > 0 && atrValue > 0)
{
var body = close - open;
var bodySize = Math.Abs(body);
if (bodySize > atrValue * AtrMultiplier && Position == 0)
{
// Bullish momentum + above MA = Buy
if (body > 0 && close > smaValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
// Bearish momentum + below MA = Sell short
else if (body < 0 && close < smaValue)
{
SellMarket();
_cooldown = CooldownBars;
}
}
}
_prevClosePrice = close;
}
}
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 SimpleMovingAverage, AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class open_drive_strategy(Strategy):
"""
Open Drive trading strategy.
Trades on strong momentum candles (body exceeds ATR * multiplier).
Bullish momentum + above MA = Buy, Bearish momentum + below MA = Sell.
"""
def __init__(self):
super(open_drive_strategy, self).__init__()
self._atr_multiplier = self.Param("AtrMultiplier", 0.3).SetDisplay("ATR Multiplier", "Multiplier for ATR to define gap size", "Strategy")
self._atr_period = self.Param("AtrPeriod", 14).SetDisplay("ATR Period", "Period for ATR calculation", "Strategy")
self._ma_period = self.Param("MaPeriod", 20).SetDisplay("MA Period", "Moving average period for trend confirmation", "Strategy")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles for strategy", "Strategy")
self._cooldown_bars = self.Param("CooldownBars", 30).SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._prev_close_price = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(open_drive_strategy, self).OnReseted()
self._prev_close_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(open_drive_strategy, self).OnStarted2(time)
self._prev_close_price = 0.0
self._cooldown = 0
sma = SimpleMovingAverage()
sma.Length = self._ma_period.Value
atr = AverageTrueRange()
atr.Length = self._atr_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, atr, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val, atr_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
sma = float(sma_val)
atr = float(atr_val)
cd = self._cooldown_bars.Value
mult = float(self._atr_multiplier.Value)
if self._cooldown > 0:
self._cooldown -= 1
self._prev_close_price = close
return
# Detect strong momentum candle (body exceeds ATR * multiplier)
if self._prev_close_price > 0 and atr > 0:
body = close - open_price
body_size = abs(body)
if body_size > atr * mult and self.Position == 0:
# Bullish momentum + above MA = Buy
if body > 0 and close > sma:
self.BuyMarket()
self._cooldown = cd
# Bearish momentum + below MA = Sell short
elif body < 0 and close < sma:
self.SellMarket()
self._cooldown = cd
self._prev_close_price = close
def CreateClone(self):
return open_drive_strategy()