Simple Bars-Strategie
Die Simple Bars-Strategie repliziert das Verhalten des ursprünglichen MQL5-Experten Exp_SimpleBars. Sie verwendet den SimpleBars-Indikator, um den aktuellen Trend zu bestimmen, indem die letzte Kerze mit den letzten Hochs und Tiefs verglichen wird. Wenn der Indikator eine Trendänderung erkennt, führt die Strategie einen Trade am Eröffnungskurs der nächsten Bar aus.
Details
- Einstiegskriterien
- Long: Das Indikatorsignal der vorherigen Bar ist buy.
- Short: Das Indikatorsignal der vorherigen Bar ist sell.
- Long/Short: Beide Richtungen werden gehandelt.
- Ausstiegskriterien
- Die Position wird umgekehrt, wenn ein entgegengesetztes Signal erscheint.
- Stops: Keine.
- Standardwerte
Period= 6 Bars.UseClose=true(Schlusskurs wird für den Vergleich verwendet).CandleType= 6-Stunden-Kerzen.
- Filter
- Kategorie: Trendfolge.
- Richtung: Beide.
- Indikatoren: Benutzerdefiniert.
- Stops: Nein.
- Komplexität: Moderat.
- Zeitrahmen: Mittelfristig.
- Saisonalität: Nein.
- Neuronale Netze: Nein.
- Divergenz: Nein.
- Risikolevel: Mittel.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on simple bar trend reversals.
/// </summary>
public class SimpleBarsStrategy : Strategy
{
private readonly StrategyParam<int> _period;
private readonly StrategyParam<bool> _useClose;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cooldownBars;
private readonly Queue<decimal> _lows = new();
private readonly Queue<decimal> _highs = new();
private decimal _prevMinLow;
private decimal _prevMaxHigh;
private int _prevTrend;
private int? _pendingSignal;
private bool _isInitialized;
private int _cooldownRemaining;
public int Period
{
get => _period.Value;
set => _period.Value = value;
}
public bool UseClose
{
get => _useClose.Value;
set => _useClose.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
public SimpleBarsStrategy()
{
_period = Param(nameof(Period), 6)
.SetDisplay("Period", "Number of bars for trend check", "General")
.SetGreaterThanZero();
_useClose = Param(nameof(UseClose), true)
.SetDisplay("Use Close", "Use close price instead of extremes", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
_cooldownBars = Param(nameof(CooldownBars), 4)
.SetDisplay("Cooldown Bars", "Completed candles to wait after a position change", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_lows.Clear();
_highs.Clear();
_prevMinLow = 0m;
_prevMaxHigh = 0m;
_prevTrend = 0;
_pendingSignal = null;
_isInitialized = false;
_cooldownRemaining = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_cooldownRemaining > 0)
_cooldownRemaining--;
if (_pendingSignal is int pending && _cooldownRemaining == 0)
{
if (pending == 1 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownBars;
}
else if (pending == -1 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_cooldownRemaining = CooldownBars;
}
}
_pendingSignal = null;
_highs.Enqueue(candle.HighPrice);
_lows.Enqueue(candle.LowPrice);
while (_highs.Count > Period)
_highs.Dequeue();
while (_lows.Count > Period)
_lows.Dequeue();
if (_highs.Count < Period || _lows.Count < Period)
return;
var minLow = GetLowest();
var maxHigh = GetHighest();
var buyPrice = UseClose ? candle.ClosePrice : candle.LowPrice;
var sellPrice = UseClose ? candle.ClosePrice : candle.HighPrice;
var trend = 0;
if (!_isInitialized)
{
trend = candle.ClosePrice > candle.OpenPrice ? 1 : -1;
_isInitialized = true;
}
else if (_prevTrend >= 0)
{
trend = buyPrice > _prevMinLow ? 1 : -1;
}
else
{
trend = sellPrice < _prevMaxHigh ? -1 : 1;
}
_pendingSignal = trend;
_prevTrend = trend;
_prevMinLow = minLow;
_prevMaxHigh = maxHigh;
}
private decimal GetLowest()
{
var lowest = decimal.MaxValue;
foreach (var low in _lows)
{
if (low < lowest)
lowest = low;
}
return lowest;
}
private decimal GetHighest()
{
var highest = decimal.MinValue;
foreach (var high in _highs)
{
if (high > highest)
highest = high;
}
return highest;
}
}
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.Strategies import Strategy
class simple_bars_strategy(Strategy):
def __init__(self):
super(simple_bars_strategy, self).__init__()
self._period = self.Param("Period", 6) \
.SetDisplay("Period", "Number of bars for trend check", "General")
self._use_close = self.Param("UseClose", True) \
.SetDisplay("Use Close", "Use close price instead of extremes", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._cooldown_bars = self.Param("CooldownBars", 4) \
.SetDisplay("Cooldown Bars", "Completed candles to wait after a position change", "Trading")
self._lows = []
self._highs = []
self._prev_min_low = 0.0
self._prev_max_high = 0.0
self._prev_trend = 0
self._pending_signal = None
self._is_initialized = False
self._cooldown_remaining = 0
@property
def period(self):
return self._period.Value
@property
def use_close(self):
return self._use_close.Value
@property
def candle_type(self):
return self._candle_type.Value
@property
def cooldown_bars(self):
return self._cooldown_bars.Value
def OnReseted(self):
super(simple_bars_strategy, self).OnReseted()
self._lows = []
self._highs = []
self._prev_min_low = 0.0
self._prev_max_high = 0.0
self._prev_trend = 0
self._pending_signal = None
self._is_initialized = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(simple_bars_strategy, self).OnStarted2(time)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
if self._pending_signal is not None and self._cooldown_remaining == 0:
if self._pending_signal == 1 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_bars
elif self._pending_signal == -1 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_bars
self._pending_signal = None
self._highs.append(float(candle.HighPrice))
self._lows.append(float(candle.LowPrice))
p = self.period
while len(self._highs) > p:
self._highs.pop(0)
while len(self._lows) > p:
self._lows.pop(0)
if len(self._highs) < p or len(self._lows) < p:
return
min_low = min(self._lows)
max_high = max(self._highs)
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
buy_price = close if self.use_close else float(candle.LowPrice)
sell_price = close if self.use_close else float(candle.HighPrice)
trend = 0
if not self._is_initialized:
trend = 1 if close > open_p else -1
self._is_initialized = True
elif self._prev_trend >= 0:
trend = 1 if buy_price > self._prev_min_low else -1
else:
trend = -1 if sell_price < self._prev_max_high else 1
self._pending_signal = trend
self._prev_trend = trend
self._prev_min_low = min_low
self._prev_max_high = max_high
def CreateClone(self):
return simple_bars_strategy()