Mittagspausen-Fade-Strategie
Die Mittagspausen-Fade-Strategie zielt auf Umkehrungen ab, die sich während der ruhigen Mittagszeit entwickeln. Nach der Morgensitzung pausieren oder korrigieren Trends häufig, wenn das Volumen zur Mittagszeit abnimmt.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 127%. Sie funktioniert am besten am Aktienmarkt.
Die Strategie handelt gegen die Morgenbewegung gegen Mittag, tritt entgegen der vorherrschenden Richtung ein und schließt die Position, bevor das Volumen zurückkehrt.
Ein prozentualer Stop steuert das Risiko, falls der Trend wieder aufgenommen wird statt abzuflauen.
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>
/// Strategy that trades on the price movement fade during the lunch break.
/// Fades the prior trend around midday, with MA confirmation and cooldown.
/// </summary>
public class LunchBreakFadeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _cooldownBars;
private SimpleMovingAverage _ma;
private decimal _prevClose;
private decimal _prevPrevClose;
private int _cooldown;
/// <summary>
/// Data type for candles.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Moving average period.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.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="LunchBreakFadeStrategy"/>.
/// </summary>
public LunchBreakFadeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_maPeriod = Param(nameof(MaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("MA Period", "Moving average period", "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();
_ma = default;
_prevClose = 0;
_prevPrevClose = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_ma = new SimpleMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_ma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _ma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal maValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var hour = candle.OpenTime.Hour;
if (_prevClose == 0)
{
_prevClose = close;
return;
}
if (_prevPrevClose == 0)
{
_prevPrevClose = _prevClose;
_prevClose = close;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevPrevClose = _prevClose;
_prevClose = close;
return;
}
// Lunch zone: hours 11-14
var isLunchTime = hour >= 11 && hour <= 14;
if (isLunchTime)
{
var priorUptrend = _prevClose > _prevPrevClose;
var priorDowntrend = _prevClose < _prevPrevClose;
var currentBearish = close < candle.OpenPrice;
var currentBullish = close > candle.OpenPrice;
// Fade uptrend at lunch: short
if (priorUptrend && currentBearish && Position == 0)
{
SellMarket();
_cooldown = CooldownBars;
}
// Fade downtrend at lunch: long
else if (priorDowntrend && currentBullish && Position == 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
// Exit on MA cross
if (Position > 0 && close < maValue)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && close > maValue)
{
BuyMarket();
_cooldown = CooldownBars;
}
_prevPrevClose = _prevClose;
_prevClose = 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
from StockSharp.Algo.Strategies import Strategy
class lunch_break_fade_strategy(Strategy):
"""
Fades the prior trend during lunch break (11-14h), exits on MA cross.
"""
def __init__(self):
super(lunch_break_fade_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 20).SetDisplay("MA Period", "SMA period", "Strategy")
self._cooldown_bars = self.Param("CooldownBars", 30).SetDisplay("Cooldown", "Bars between trades", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._prev_close = 0.0
self._prev_prev_close = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(lunch_break_fade_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_prev_close = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(lunch_break_fade_strategy, self).OnStarted2(time)
ma = SimpleMovingAverage()
ma.Length = self._ma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
hour = candle.OpenTime.Hour
ma = float(ma_val)
if self._prev_close == 0:
self._prev_close = close
return
if self._prev_prev_close == 0:
self._prev_prev_close = self._prev_close
self._prev_close = close
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_prev_close = self._prev_close
self._prev_close = close
return
is_lunch = hour >= 11 and hour <= 14
if is_lunch:
prior_up = self._prev_close > self._prev_prev_close
prior_down = self._prev_close < self._prev_prev_close
bearish = close < open_p
bullish = close > open_p
if prior_up and bearish and self.Position == 0:
self.SellMarket()
self._cooldown = self._cooldown_bars.Value
elif prior_down and bullish and self.Position == 0:
self.BuyMarket()
self._cooldown = self._cooldown_bars.Value
if self.Position > 0 and close < ma:
self.SellMarket()
self._cooldown = self._cooldown_bars.Value
elif self.Position < 0 and close > ma:
self.BuyMarket()
self._cooldown = self._cooldown_bars.Value
self._prev_prev_close = self._prev_close
self._prev_close = close
def CreateClone(self):
return lunch_break_fade_strategy()