Candels High Open Strategy
Strategy that trades when a candle opens exactly at its high or low. A long position is opened if the candle's open equals its low, anticipating upward movement. A short position is opened if the candle's open equals its high, expecting a decline. The position is closed when price crosses the Parabolic SAR value, acting as a trailing exit.
Details
- Entry Criteria:
- Long:
Open == Low - Short:
Open == High
- Long:
- Long/Short: Both
- Exit Criteria: Price crosses Parabolic SAR or opposite signal
- Stops: Uses fixed stop loss and take profit levels
- Default Values:
StopLevel= 50mTakeLevel= 50mSarStep= 0.02mSarMax= 0.2mCandleType= TimeSpan.FromMinutes(5).TimeFrame()ReverseSignals= false
- Filters:
- Category: Price action
- Direction: Both
- Indicators: Parabolic SAR
- Stops: Yes
- Complexity: Basic
- Timeframe: Intraday
- Seasonality: No
- Neural Networks: No
- Divergence: No
- Risk Level: Medium
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that enters when a candle opens at its high or low and exits on Parabolic SAR reversal.
/// </summary>
public class CandelsHighOpenStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<bool> _reverseSignals;
private readonly StrategyParam<decimal> _stopLevel;
private readonly StrategyParam<decimal> _takeLevel;
private readonly StrategyParam<decimal> _sarStep;
private readonly StrategyParam<decimal> _sarMax;
/// <summary>
/// Candle type for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Reverse entry signals.
/// </summary>
public bool ReverseSignals
{
get => _reverseSignals.Value;
set => _reverseSignals.Value = value;
}
/// <summary>
/// Stop loss level in absolute price.
/// </summary>
public decimal StopLevel
{
get => _stopLevel.Value;
set => _stopLevel.Value = value;
}
/// <summary>
/// Take profit level in absolute price.
/// </summary>
public decimal TakeLevel
{
get => _takeLevel.Value;
set => _takeLevel.Value = value;
}
/// <summary>
/// Parabolic SAR acceleration step.
/// </summary>
public decimal SarStep
{
get => _sarStep.Value;
set => _sarStep.Value = value;
}
/// <summary>
/// Parabolic SAR maximum acceleration.
/// </summary>
public decimal SarMax
{
get => _sarMax.Value;
set => _sarMax.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public CandelsHighOpenStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles used for processing", "General")
;
_reverseSignals = Param(nameof(ReverseSignals), false)
.SetDisplay("Reverse Signals", "Invert long and short signals", "General")
;
_stopLevel = Param(nameof(StopLevel), 50m)
.SetGreaterThanZero()
.SetDisplay("Stop Level", "Absolute stop loss distance", "Protection")
;
_takeLevel = Param(nameof(TakeLevel), 50m)
.SetGreaterThanZero()
.SetDisplay("Take Level", "Absolute take profit distance", "Protection")
;
_sarStep = Param(nameof(SarStep), 0.02m)
.SetGreaterThanZero()
.SetDisplay("SAR Step", "Acceleration factor step for Parabolic SAR", "Indicators")
;
_sarMax = Param(nameof(SarMax), 0.2m)
.SetGreaterThanZero()
.SetDisplay("SAR Max", "Maximum acceleration factor for Parabolic SAR", "Indicators")
;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var psar = new ParabolicSar
{
Acceleration = SarStep,
AccelerationMax = SarMax,
AccelerationStep = SarStep
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(psar, ProcessCandle)
.Start();
StartProtection(
stopLoss: new Unit(StopLevel, UnitTypes.Absolute),
takeProfit: new Unit(TakeLevel, UnitTypes.Absolute));
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, psar);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal psarValue)
{
if (candle.State != CandleStates.Finished)
return;
// Exit conditions based on Parabolic SAR reversal
if (Position > 0 && candle.ClosePrice < psarValue)
{
SellMarket();
return;
}
if (Position < 0 && candle.ClosePrice > psarValue)
{
BuyMarket();
return;
}
var openAtHigh = candle.OpenPrice == candle.HighPrice;
var openAtLow = candle.OpenPrice == candle.LowPrice;
if (ReverseSignals)
{
var tmp = openAtHigh;
openAtHigh = openAtLow;
openAtLow = tmp;
}
if (openAtLow && Position <= 0)
{
BuyMarket();
}
else if (openAtHigh && Position >= 0)
{
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class candels_high_open_strategy(Strategy):
def __init__(self):
super(candels_high_open_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._reverse_signals = self.Param("ReverseSignals", False)
self._stop_level = self.Param("StopLevel", 50.0)
self._take_level = self.Param("TakeLevel", 50.0)
self._sar_step = self.Param("SarStep", 0.02)
self._sar_max = self.Param("SarMax", 0.2)
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def ReverseSignals(self):
return self._reverse_signals.Value
@ReverseSignals.setter
def ReverseSignals(self, value):
self._reverse_signals.Value = value
@property
def StopLevel(self):
return self._stop_level.Value
@StopLevel.setter
def StopLevel(self, value):
self._stop_level.Value = value
@property
def TakeLevel(self):
return self._take_level.Value
@TakeLevel.setter
def TakeLevel(self, value):
self._take_level.Value = value
@property
def SarStep(self):
return self._sar_step.Value
@SarStep.setter
def SarStep(self, value):
self._sar_step.Value = value
@property
def SarMax(self):
return self._sar_max.Value
@SarMax.setter
def SarMax(self, value):
self._sar_max.Value = value
def OnStarted2(self, time):
super(candels_high_open_strategy, self).OnStarted2(time)
psar = ParabolicSar()
psar.Acceleration = self.SarStep
psar.AccelerationMax = self.SarMax
psar.AccelerationStep = self.SarStep
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(psar, self.ProcessCandle).Start()
self.StartProtection(
Unit(self.TakeLevel, UnitTypes.Absolute),
Unit(self.StopLevel, UnitTypes.Absolute))
def ProcessCandle(self, candle, psar_value):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
psar_val = float(psar_value)
if self.Position > 0 and price < psar_val:
self.SellMarket()
return
if self.Position < 0 and price > psar_val:
self.BuyMarket()
return
open_at_high = float(candle.OpenPrice) == float(candle.HighPrice)
open_at_low = float(candle.OpenPrice) == float(candle.LowPrice)
if self.ReverseSignals:
tmp = open_at_high
open_at_high = open_at_low
open_at_low = tmp
if open_at_low and self.Position <= 0:
self.BuyMarket()
elif open_at_high and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return candels_high_open_strategy()