Liquidity Engulfment Strategy
This strategy detects bullish and bearish engulfing patterns that occur after price touches recent liquidity highs or lows. Trades are filtered by mode and include fixed stop loss and optional take profit defined in pips.
Details
- Entry Conditions:
- Long: Bullish engulfing after lower liquidity touch.
- Short: Bearish engulfing after upper liquidity touch.
- Exit Conditions: Opposite signal, stop loss or take profit.
- Long/Short: Configurable (both by default).
- Indicators: Highest, Lowest.
- Stops:
StopLossPipsand optionalTakeProfitPips. - Default Values:
CandleType= 1 minuteUpperLookback= 10LowerLookback= 10StopLossPips= 10TakeProfitPips= 20Mode= Both
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>
/// Liquidity and Engulfment combination strategy.
/// </summary>
public class LiquidityEngulfmentStrategy : Strategy
{
private readonly StrategyParam<int> _upperLookback;
private readonly StrategyParam<int> _lowerLookback;
private readonly StrategyParam<DataType> _candleType;
public int UpperLookback { get => _upperLookback.Value; set => _upperLookback.Value = value; }
public int LowerLookback { get => _lowerLookback.Value; set => _lowerLookback.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public LiquidityEngulfmentStrategy()
{
_upperLookback = Param(nameof(UpperLookback), 14).SetGreaterThanZero().SetDisplay("Upper Lookback", "Upper liquidity", "Indicators");
_lowerLookback = Param(nameof(LowerLookback), 14).SetGreaterThanZero().SetDisplay("Lower Lookback", "Lower liquidity", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = UpperLookback };
var lowest = new Lowest { Length = LowerLookback };
var sub = SubscribeCandles(CandleType);
sub.Bind(highest, lowest, Process).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, sub);
DrawOwnTrades(area);
}
}
private void Process(ICandleMessage candle, decimal highestVal, decimal lowestVal)
{
if (candle.State != CandleStates.Finished)
return;
if (highestVal == 0m || lowestVal == 0m)
return;
var bull = candle.ClosePrice > candle.OpenPrice;
var bear = candle.ClosePrice < candle.OpenPrice;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
// Engulfing candle: body is large relative to range
var engulfing = range > 0 && body / range > 0.6m;
// Bullish: price touched lower liquidity zone and engulfing bullish candle
var bullSignal = bull && engulfing && candle.LowPrice <= lowestVal;
// Bearish: price touched upper liquidity zone and engulfing bearish candle
var bearSignal = bear && engulfing && candle.HighPrice >= highestVal;
if (bearSignal && Position >= 0)
SellMarket();
else if (bullSignal && Position <= 0)
BuyMarket();
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class liquidity_engulfment_strategy(Strategy):
def __init__(self):
super(liquidity_engulfment_strategy, self).__init__()
self._upper_lookback = self.Param("UpperLookback", 14) \
.SetGreaterThanZero() \
.SetDisplay("Upper Lookback", "Upper liquidity", "Indicators")
self._lower_lookback = self.Param("LowerLookback", 14) \
.SetGreaterThanZero() \
.SetDisplay("Lower Lookback", "Lower liquidity", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(liquidity_engulfment_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self._upper_lookback.Value
lowest = Lowest()
lowest.Length = self._lower_lookback.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def OnProcess(self, candle, highest_val, lowest_val):
if candle.State != CandleStates.Finished:
return
hv = float(highest_val)
lv = float(lowest_val)
if hv == 0.0 or lv == 0.0:
return
close = float(candle.ClosePrice)
opn = float(candle.OpenPrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
bull = close > opn
bear = close < opn
body = abs(close - opn)
rng = high - low
engulfing = rng > 0 and body / rng > 0.6
bull_signal = bull and engulfing and low <= lv
bear_signal = bear and engulfing and high >= hv
if bear_signal and self.Position >= 0:
self.SellMarket()
elif bull_signal and self.Position <= 0:
self.BuyMarket()
def CreateClone(self):
return liquidity_engulfment_strategy()