Bleris Strategy
Overview
The Bleris strategy analyzes the trend of recent price extremes to open trades in the direction of the prevailing trend.
The price series is split into three segments of length SignalBarSample and the highest highs and lowest lows of these segments are compared.
- Indicators: Highest, Lowest
- Parameters:
SignalBarSample– number of candles per segment.CounterTrend– reverse the trading direction.Lots– order volume.CandleType– timeframe of the candles.AnotherOrderPips– minimum distance in pips before another order of the same type is opened.
How it Works
- Highest and Lowest indicators calculate extreme prices over the recent
SignalBarSamplecandles. - Decreasing highs signal a downtrend, increasing lows signal an uptrend.
- The strategy buys on an uptrend and sells on a downtrend. With
CounterTrendenabled the logic is inverted. - New orders of the same direction are ignored if the last order price is within
AnotherOrderPips.
This example uses the high-level StockSharp API and is intended for educational purposes.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Bleris strategy based on comparisons of consecutive highest highs and lowest lows.
/// </summary>
public class BlerisStrategy : Strategy
{
private readonly StrategyParam<int> _signalBarSample;
private readonly StrategyParam<bool> _counterTrend;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _highs = new();
private readonly List<decimal> _lows = new();
private decimal _prevHigh1;
private decimal _prevHigh2;
private decimal _prevLow1;
private decimal _prevLow2;
/// <summary>
/// Number of candles for each segment of trend detection.
/// </summary>
public int SignalBarSample { get => _signalBarSample.Value; set => _signalBarSample.Value = value; }
/// <summary>
/// Reverse trading direction when true.
/// </summary>
public bool CounterTrend { get => _counterTrend.Value; set => _counterTrend.Value = value; }
/// <summary>
/// Candle type used for analysis.
/// </summary>
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BlerisStrategy()
{
_signalBarSample = Param(nameof(SignalBarSample), 24)
.SetDisplay("Signal bar sample", "Signal bar sample", "General");
_counterTrend = Param(nameof(CounterTrend), false)
.SetDisplay("Counter trend", "Counter trend", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle type", "Candle type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_highs.Clear();
_lows.Clear();
_prevHigh1 = 0;
_prevHigh2 = 0;
_prevLow1 = 0;
_prevLow2 = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartProtection(null, null);
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;
_highs.Add(candle.HighPrice);
_lows.Add(candle.LowPrice);
if (_highs.Count > SignalBarSample)
_highs.RemoveAt(0);
if (_lows.Count > SignalBarSample)
_lows.RemoveAt(0);
if (_highs.Count < SignalBarSample)
return;
var highest = decimal.MinValue;
var lowest = decimal.MaxValue;
for (var i = 0; i < _highs.Count; i++)
{
if (_highs[i] > highest) highest = _highs[i];
if (_lows[i] < lowest) lowest = _lows[i];
}
var uptrend = _prevLow2 > 0 && _prevLow2 < _prevLow1 && _prevLow1 < lowest;
var downtrend = _prevHigh2 > 0 && _prevHigh2 > _prevHigh1 && _prevHigh1 > highest;
_prevHigh2 = _prevHigh1;
_prevHigh1 = highest;
_prevLow2 = _prevLow1;
_prevLow1 = lowest;
if (uptrend && !downtrend)
{
if (CounterTrend)
{
if (Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
else
{
if (Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
}
}
else if (downtrend && !uptrend)
{
if (CounterTrend)
{
if (Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
}
else
{
if (Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
}
}
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 bleris_strategy(Strategy):
def __init__(self):
super(bleris_strategy, self).__init__()
self._signal_bar_sample = self.Param("SignalBarSample", 24) \
.SetDisplay("Signal bar sample", "Signal bar sample", "General")
self._counter_trend = self.Param("CounterTrend", False) \
.SetDisplay("Counter trend", "Counter trend", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle type", "Candle type", "General")
self._highs = []
self._lows = []
self._prev_high1 = 0.0
self._prev_high2 = 0.0
self._prev_low1 = 0.0
self._prev_low2 = 0.0
@property
def signal_bar_sample(self):
return self._signal_bar_sample.Value
@property
def counter_trend(self):
return self._counter_trend.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(bleris_strategy, self).OnReseted()
self._highs = []
self._lows = []
self._prev_high1 = 0.0
self._prev_high2 = 0.0
self._prev_low1 = 0.0
self._prev_low2 = 0.0
def OnStarted2(self, time):
super(bleris_strategy, self).OnStarted2(time)
self.StartProtection(None, None)
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
self._highs.append(float(candle.HighPrice))
self._lows.append(float(candle.LowPrice))
sbs = self.signal_bar_sample
if len(self._highs) > sbs:
self._highs.pop(0)
if len(self._lows) > sbs:
self._lows.pop(0)
if len(self._highs) < sbs:
return
highest = max(self._highs)
lowest = min(self._lows)
uptrend = self._prev_low2 > 0 and self._prev_low2 < self._prev_low1 and self._prev_low1 < lowest
downtrend = self._prev_high2 > 0 and self._prev_high2 > self._prev_high1 and self._prev_high1 > highest
self._prev_high2 = self._prev_high1
self._prev_high1 = highest
self._prev_low2 = self._prev_low1
self._prev_low1 = lowest
if uptrend and not downtrend:
if self.counter_trend:
if self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
else:
if self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif downtrend and not uptrend:
if self.counter_trend:
if self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
else:
if self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return bleris_strategy()