0bps

Strategy vault / Mean reversion

Open High Low Stop Loss Tracking Strategy

This strategy is designed based on the open, high and low data of candlestick charts to identify trend reversal points for entries. After entries, stop loss lines will be set based on the ATR indicator and tracked…

Author
ChaoZhang
Complexity
Starter · 78 lines
Parameters
6
Backtest bar
1h · intraday
Tested on
BTC/USDT · futures

IMG

Overview

This strategy is designed based on the open, high and low data of candlestick charts to identify trend reversal points for entries. After entries, stop loss lines will be set based on the ATR indicator and tracked. Targets will also be calculated based on the risk-reward ratio. When price hits either the stop loss or profit target, orders will be sent to close positions.

Strategy Logic

The entry signals of this strategy come from the open, high and low prices. A buy signal is generated when the opening price equals the low of the candlestick, and a sell signal is generated when the opening price equals the high, indicating potential trend reversal opportunities.

After entry, dynamic trailing stop loss is calculated based on the ATR indicator. The long stop loss is set at the lowest low of recent N bars minus 1 ATR; the short stop loss is set at the highest high of recent N bars plus 1 ATR. The stop loss line will update dynamically to trail price moves.

Profit targets are calculated based on the risk-reward ratio setting. The long target is set at the entry price plus (the risk difference between entry price and stop loss multiplied by the risk-reward ratio); the short target is set at the entry price minus (the risk difference between stop loss and entry price multiplied by the risk-reward ratio).

When price hits either the stop loss or profit target, orders will be sent to flatten positions.

Advantage Analysis

The advantages of this strategy include:

  1. Simple and clear entry signals, avoiding multiple whipsaws.

  2. Dynamic ATR trailing stop locks in profits and prevents chasing highs and lows.

  3. Risk-reward ratio control avoids leaving profits on table and over-trading.

  4. Applicable to different products, easy to optimize.

Risk Analysis

There are also some risks of this strategy:

  1. Entry signals may lag to some extent, missing best market entry.

  2. Stop loss too tight or too loose, causing unnecessary stop loss or missing profits.

  3. No trend determination, prone to being trapped in ranging markets.

  4. Unable to handle overnight positions.

The optimization directions are:

  1. Incorporate other indicators for trend bias to avoid whipsaws.

  2. Fine tune ATR parameters or add volatility control for better stop loss.

  3. Add trend filtering to reduce signal noise.

  4. Add overnight position handling for certain products.

Conclusion

In conclusion, this is a simple and straightforward strategy with clear entry logic, reasonable stop loss methodology and good risk control. But there are some limitations like insufficient trend bias, signal lagging etc. These flaws also point out directions for future optimization. By incorporating more indicators filters and risk management modules, this strategy can be further enhanced and made more robust.

Parameters

NameDefaultWhat it controls
v_input_int_114(?StopLoss settings)ATR Period for placing SL
v_input_bool_1false(?Stolploss settings)Show SL lines in chart
v_input_float_12(?Trade settings)Risk:Reward
v_input_int_21500Close all trades, default is 3:00 PM, 1500 hours (integer)
v_input_bool_2trueMarkets that never closed (Crypto, Forex, Commodity)
v_input_int_3trueLot Size

Source Pine Script

/*backtest
start: 2024-01-01 00:00:00
end: 2024-01-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// Open-High-Low strategy

strategy('Strategy: OLH', shorttitle="OLH", overlay=true )

// Inputs
slAtrLen = input.int(defval=14, title="ATR Period for placing SL", group="StopLoss settings")
showSLLines = input.bool(defval=false, title="Show SL lines in chart", tooltip="Show SL lines also as dotted lines in chart. Note: chart may look untidy.", group="Stolploss settings")
// Trade related
rrRatio = input.float(title='Risk:Reward', step=0.1, defval=2.0, group="Trade settings")
endOfDay = input.int(defval=1500, title="Close all trades, default is 3:00 PM, 1500 hours (integer)", group="Trade settings")
mktAlwaysOn = input.bool(defval=true, title="Markets that never closed (Crypto, Forex, Commodity)", tooltip="Some markers never closes. For those cases, make this checked.", group="Trade settings")
lotSize = input.int(title='Lot Size', step=1, defval=1, group="Trade settings")


// Utils
green(open, close) => close > open ? true : false
red(open, close) => close < open ? true : false
body(open, close) => math.abs(open - close)
lowerwick = green(open, close) ? open - low : close - low
upperwick = green(open, close) ? high - close : high - open
crange = high - low
crangep = high[1] - low[1] // previous candle's candle-range
bullish = close > open ? true : false
bearish = close < open ? true : false


// Trade signals
longCond = barstate.isconfirmed and (open == low)
shortCond = barstate.isconfirmed and (open == high)

// For SL calculation
atr = ta.atr(slAtrLen)
highestHigh = ta.highest(high, 7)
lowestLow = ta.lowest(low, 7)
longStop = showSLLines ? lowestLow - (atr * 1) : na
shortStop = showSLLines ? highestHigh + (atr * 1) : na
plot(longStop, title="Buy SL", color=color.green, style=plot.style_cross)
plot(shortStop, title="Sell SL", color=color.red, style=plot.style_cross)

// Trade execute
h = hour(time('1'), syminfo.timezone)
m = minute(time('1'), syminfo.timezone)
hourVal = h * 100 + m
totalTrades = strategy.opentrades + strategy.closedtrades
if (mktAlwaysOn or (hourVal < endOfDay))
    // Entry
    var float sl = na
    var float target = na
    if (longCond)
        strategy.entry("enter long", strategy.long, lotSize, limit=na, stop=na, comment="Enter Long")
        sl := longStop
        target := close + ((close - longStop) * rrRatio)
        alert('Buy:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)
    if (shortCond)
        strategy.entry("enter short", strategy.short, lotSize, limit=na, stop=na, comment="Enter Short")
        sl := shortStop
        target := close - ((shortStop - close) * rrRatio)
        alert('Sell:' + syminfo.ticker + ' ,SL:' + str.tostring(math.floor(sl)) + ', Target:' + str.tostring(target), alert.freq_once_per_bar)

    // Exit: target or SL
    if ((close >= target) or (close <= sl))
        strategy.close("enter long", comment=close < sl ? "Long SL hit" : "Long target hit")
    if ((close <= target) or (close >= sl))
        strategy.close("enter short", comment=close > sl ? "Short SL hit" : "Short target hit")
else if (not mktAlwaysOn)
    // Close all open position at the end if Day
    strategy.close_all(comment = "Close all entries at end of day.")

Published by ChaoZhang on the FMZ strategy square · last modified 2024-02-18. Collected in the Quant Trading Vault. Unvalidated research: re-test with your own data and costs before trusting it.

Build this with AgenKit

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build a production-grade trading bot with a backtest engine, risk controls and paper trading by default from strategies/Open-High-Low-Stop-Loss-Tracking-Strategy.md
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch

Understand it first

Before you run this, read the lesson behind the idea and how to backtest it honestly. Specs like this one are the survivors of an unknown number of trials; deflate their results accordingly.

Related specs

esc

Try , , or .

↑↓ move↵ open