Strategie der Falschen Ausbruch-Falle
Die Falsche Ausbruch-Falle zielt darauf ab, von Ausbrüchen zu profitieren, die über wichtige Unterstützungs- oder Widerstandsniveaus hinaus nicht standhalten. Trader springen oft in einen Ausbruch, nur um zu sehen, wie der Preis schnell umkehrt und sie in der Falle sitzen lässt.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 52%. Die Strategie funktioniert am besten am Kryptomarkt.
Diese Strategie wartet auf dieses Scheitern und tritt in die entgegengesetzte Richtung ein, sobald der Preis wieder innerhalb der Range schließt.
Die Stop-Platzierung ist eng, knapp jenseits des gescheiterten Ausbruchniveaus, um sicherzustellen, dass Verluste gering bleiben, wenn die Umkehr ausbleibt.
Details
- Einstiegskriterien: Indikatorsignal
- Long/Short: Beide
- Ausstiegskriterien: Stop-Loss oder entgegengesetztes Signal
- Stops: Ja, prozentbasiert
- Standardwerte:
CandleType= 15 minuteStopLoss= 2%
- Filter:
- Kategorie: Umkehr
- 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>
/// False Breakout Trap strategy.
/// Detects when price breaks a recent high/low range then reverses back.
/// Trades against the failed breakout direction.
/// Uses SMA for exit confirmation.
/// Uses cooldown to control trade frequency.
/// </summary>
public class FalseBreakoutTrapStrategy : Strategy
{
private readonly StrategyParam<int> _lookbackPeriod;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private readonly List<decimal> _highs = new();
private readonly List<decimal> _lows = new();
private int _cooldown;
/// <summary>
/// Lookback period for range.
/// </summary>
public int LookbackPeriod
{
get => _lookbackPeriod.Value;
set => _lookbackPeriod.Value = value;
}
/// <summary>
/// MA period for exit.
/// </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>
/// Cooldown bars.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public FalseBreakoutTrapStrategy()
{
_lookbackPeriod = Param(nameof(LookbackPeriod), 20)
.SetRange(5, 50)
.SetDisplay("Lookback", "Period for high/low range", "Range");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetRange(5, 50)
.SetDisplay("MA Period", "Period for SMA exit", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_cooldownBars = Param(nameof(CooldownBars), 500)
.SetRange(1, 1000)
.SetDisplay("Cooldown Bars", "Bars to wait between trades", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_highs.Clear();
_lows.Clear();
_cooldown = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_highs.Clear();
_lows.Clear();
_cooldown = 0;
var sma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Maintain rolling high/low window
_highs.Add(candle.HighPrice);
_lows.Add(candle.LowPrice);
if (_highs.Count > LookbackPeriod + 1)
{
_highs.RemoveAt(0);
_lows.RemoveAt(0);
}
if (_highs.Count < LookbackPeriod + 1)
return;
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Find highest high and lowest low of the previous N bars (excluding current)
decimal rangeHigh = decimal.MinValue;
decimal rangeLow = decimal.MaxValue;
for (int i = 0; i < _highs.Count - 1; i++)
{
if (_highs[i] > rangeHigh) rangeHigh = _highs[i];
if (_lows[i] < rangeLow) rangeLow = _lows[i];
}
// False upside breakout: candle broke above range high but closed below it
var falseBreakUp = candle.HighPrice > rangeHigh && candle.ClosePrice < rangeHigh;
// False downside breakout: candle broke below range low but closed above it
var falseBreakDown = candle.LowPrice < rangeLow && candle.ClosePrice > rangeLow;
if (Position == 0 && falseBreakDown)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (Position == 0 && falseBreakUp)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position > 0 && candle.ClosePrice < smaValue)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && candle.ClosePrice > smaValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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
from StockSharp.Algo.Strategies import Strategy
class false_breakout_trap_strategy(Strategy):
"""
False Breakout Trap strategy.
Detects when price breaks a recent high/low range then reverses back.
Trades against the failed breakout direction.
Uses SMA for exit confirmation.
"""
def __init__(self):
super(false_breakout_trap_strategy, self).__init__()
self._lookback_period = self.Param("LookbackPeriod", 20).SetDisplay("Lookback", "Period for high/low range", "Range")
self._ma_period = self.Param("MaPeriod", 20).SetDisplay("MA Period", "Period for SMA exit", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._cooldown_bars = self.Param("CooldownBars", 500).SetDisplay("Cooldown Bars", "Bars to wait between trades", "General")
self._highs = []
self._lows = []
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(false_breakout_trap_strategy, self).OnReseted()
self._highs = []
self._lows = []
self._cooldown = 0
def OnStarted2(self, time):
super(false_breakout_trap_strategy, self).OnStarted2(time)
self._highs = []
self._lows = []
self._cooldown = 0
sma = SimpleMovingAverage()
sma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, 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):
if candle.State != CandleStates.Finished:
return
lookback = self._lookback_period.Value
# Maintain rolling high/low window
self._highs.append(float(candle.HighPrice))
self._lows.append(float(candle.LowPrice))
if len(self._highs) > lookback + 1:
self._highs.pop(0)
self._lows.pop(0)
if len(self._highs) < lookback + 1:
return
if self._cooldown > 0:
self._cooldown -= 1
return
cd = self._cooldown_bars.Value
sv = float(sma_val)
# Find highest high and lowest low of the previous N bars (excluding current)
range_high = max(self._highs[:-1])
range_low = min(self._lows[:-1])
# False upside breakout: candle broke above range high but closed below it
false_break_up = float(candle.HighPrice) > range_high and float(candle.ClosePrice) < range_high
# False downside breakout: candle broke below range low but closed above it
false_break_down = float(candle.LowPrice) < range_low and float(candle.ClosePrice) > range_low
if self.Position == 0 and false_break_down:
self.BuyMarket()
self._cooldown = cd
elif self.Position == 0 and false_break_up:
self.SellMarket()
self._cooldown = cd
elif self.Position > 0 and float(candle.ClosePrice) < sv:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and float(candle.ClosePrice) > sv:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return false_breakout_trap_strategy()