IU Open Equal to High Low Strategy
Enters long on the first candle of the day when its open equals its low and enters short when the open equals the high. Stop loss uses the prior candle and take profit is based on the RiskReward ratio.
Details
- Entry Criteria:
- Long: first candle's open equals its low.
- Short: first candle's open equals its high.
- Long/Short: Both sides.
- Exit Criteria:
- Stop loss at the previous candle low for long, previous candle high for short.
- Take profit calculated from entry price using
RiskReward.
- Stops: Yes.
- Default Values:
RiskReward= 2.CandleType= TimeSpan.FromMinutes(1).TimeFrame().
- Filters:
- Category: Pattern
- Direction: Both
- Indicators: Price action
- Stops: Yes
- Complexity: Basic
- Timeframe: Intraday
- Seasonality: No
- Neural networks: No
- Divergence: No
- Risk level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Enters when the first candle's open equals its high or low.
/// </summary>
public class IuOpenEqualToHighLowStrategy : Strategy
{
private readonly StrategyParam<decimal> _riskReward;
private readonly StrategyParam<int> _cooldownDays;
private readonly StrategyParam<DataType> _candleType;
private DateTime _currentDay;
private DateTime _nextEntryDate;
private decimal _stopPrice;
private decimal _takePrice;
private ICandleMessage _prevCandle;
/// <summary>
/// Risk/reward ratio.
/// </summary>
public decimal RiskReward
{
get => _riskReward.Value;
set => _riskReward.Value = value;
}
/// <summary>
/// Minimum days between entries.
/// </summary>
public int CooldownDays
{
get => _cooldownDays.Value;
set => _cooldownDays.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="IuOpenEqualToHighLowStrategy"/> class.
/// </summary>
public IuOpenEqualToHighLowStrategy()
{
_riskReward = Param(nameof(RiskReward), 2m)
.SetGreaterThanZero()
.SetDisplay("Risk/Reward", "Take profit to stop ratio", "Risk")
.SetOptimize(1m, 5m, 1m);
_cooldownDays = Param(nameof(CooldownDays), 1)
.SetDisplay("Cooldown Days", "Minimum number of days between new entries", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_currentDay = default;
_nextEntryDate = DateTime.MinValue;
_stopPrice = 0m;
_takePrice = 0m;
_prevCandle = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var dummyEma1 = new StockSharp.Algo.Indicators.ExponentialMovingAverage { Length = 10 };
var dummyEma2 = new StockSharp.Algo.Indicators.ExponentialMovingAverage { Length = 20 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(dummyEma1, dummyEma2, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal d1, decimal d2)
{
if (candle.State != CandleStates.Finished)
return;
var day = candle.OpenTime.Date;
if (_currentDay != day)
{
_currentDay = day;
if (Position == 0 && _prevCandle != null && day >= _nextEntryDate)
{
var entryPrice = candle.OpenPrice;
var tolerance = candle.OpenPrice * 0.005m;
var isOpenNearLow = candle.OpenPrice - candle.LowPrice <= tolerance;
var isOpenNearHigh = candle.HighPrice - candle.OpenPrice <= tolerance;
if (isOpenNearLow)
{
_stopPrice = _prevCandle.LowPrice;
_takePrice = entryPrice + (entryPrice - _stopPrice) * RiskReward;
BuyMarket();
_nextEntryDate = day.AddDays(CooldownDays);
}
else if (isOpenNearHigh)
{
_stopPrice = _prevCandle.HighPrice;
_takePrice = entryPrice - (_stopPrice - entryPrice) * RiskReward;
SellMarket();
_nextEntryDate = day.AddDays(CooldownDays);
}
}
}
if (Position > 0)
{
if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
{
SellMarket();
_stopPrice = 0m;
_takePrice = 0m;
}
}
else if (Position < 0)
{
if (candle.HighPrice >= _stopPrice || candle.LowPrice <= _takePrice)
{
BuyMarket();
_stopPrice = 0m;
_takePrice = 0m;
}
}
_prevCandle = candle;
}
}
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 iu_open_equal_to_high_low_strategy(Strategy):
"""
Enters when candle open equals its high or low at day boundary.
Uses risk/reward management with SL/TP based on previous candle.
"""
def __init__(self):
super(iu_open_equal_to_high_low_strategy, self).__init__()
self._risk_reward = self.Param("RiskReward", 2.0) \
.SetDisplay("Risk/Reward", "Take profit to stop ratio", "Risk")
self._cooldown_days = self.Param("CooldownDays", 1) \
.SetDisplay("Cooldown Days", "Min days between entries", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._current_day = None
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(iu_open_equal_to_high_low_strategy, self).OnReseted()
self._current_day = None
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(iu_open_equal_to_high_low_strategy, self).OnStarted2(time)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
high = float(candle.HighPrice)
low = float(candle.LowPrice)
open_price = float(candle.OpenPrice)
close = float(candle.ClosePrice)
day = candle.OpenTime.Date
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_high = high
self._prev_low = low
self._has_prev = True
self._current_day = day
return
if self._current_day is None or self._current_day != day:
self._current_day = day
if self.Position == 0 and self._has_prev:
tolerance = open_price * 0.005
is_open_near_low = open_price - low <= tolerance
is_open_near_high = high - open_price <= tolerance
if is_open_near_low:
self._stop_price = self._prev_low
self._take_price = open_price + (open_price - self._stop_price) * self._risk_reward.Value
self.BuyMarket()
elif is_open_near_high:
self._stop_price = self._prev_high
self._take_price = open_price - (self._stop_price - open_price) * self._risk_reward.Value
self.SellMarket()
if self.Position > 0:
if low <= self._stop_price or high >= self._take_price:
self.SellMarket()
self._stop_price = 0.0
self._take_price = 0.0
elif self.Position < 0:
if high >= self._stop_price or low <= self._take_price:
self.BuyMarket()
self._stop_price = 0.0
self._take_price = 0.0
self._prev_high = high
self._prev_low = low
self._has_prev = True
def CreateClone(self):
return iu_open_equal_to_high_low_strategy()