Liquidity Retest Strategy (Apicode) - TP/SL Lines Fixed by Apicode
By Apicode
Performance Metrics
- Author: Apicode
- Symbol: BITGET:HBARUSDT
- Timeframe: 15 minutes
- Net P&L: +152.78 USDT (+1.53%)
- Win Rate: 44.7%
- Profit Factor: 1.368
- Max Drawdown: 76.91 USDT (0.75%)
- Total Trades: 76
Description
Technical Documentation:1. Purpose and underlying conceptThis strategy targets a common behavior in liquid markets: liquidity sweeps around meaningful support/resistance levels, followed by a retest and rejection (reversal) with confirmation.The core thesis is that many initial “breaks” are not continuation moves, but rather stop-runs and order harvesting. After the sweep, price reclaims the level and closes back on the opposite side, offering a structured entry with defined risk.The strategy includes:Support/Resistance detection via pivotsDynamic selection of the “working” level using an ATR-based proximity windowRejection validation via candle structure (wick + close)Optional filters: volume, VWAP-like bias, and EMA trendRisk management with static TP/SL (ATR-based or %), plus trailing stop (ATR-based or %), with per-trade lines plotted2. Main components2.1. Volatility metric: ATRatr = ta.atr(atrLength) is used in two essential places:Level selection (proximity to S/R): prevents trading levels that are too far from current price.Sweep validation (minimum wick size): requires the wick to extend beyond the level by a volatility-relative amount.Optionally, ATR can also be used for:Static TP/SL (when usePercent = false)Trailing stop (when useTrailPercent = false)2.2. Building S/R levels with pivotsPivots are detected using:pivotHigh = ta.pivothigh(pivotLookback, rightBars)pivotLow = ta.pivotlow(pivotLookback, rightBars)Each confirmed pivot is stored in arrays:resistanceLevels for resistancesupportLevels for supportThe array size is capped by maxLevels, which reduces noise and manages chart resource usage (lines).2.3. Selecting the “best” level each barOn each bar, a single support S and/or resistance R candidate is chosen:Support: nearest level below price (L price)Only levels within atr * maxDistATR are consideredThis produces dynamic “working levels” that adapt to price location and volatility.2.4. Rejection pattern (retest + sweep)After selecting the working level:Support rejection (long setup)Conditions:Low touches/crosses support: low SBullish candle: close > openSufficient wick below the level (liquidity sweep): (S - low) >= atr * minWickATRThis aims to capture a stop sweep below support followed by immediate recovery.Resistance rejection (short setup)Symmetric conditions:High touches/crosses resistance: high >= RClose rejects back below: close = atr * minWickATR2.5. Optional filtersFinal signals are the rejection pattern AND enabled filters: 1.- Volume filterHigh volume is defined as: volume > SMA(volume, 20) * volMultWhen useVolFilter = true, setups require relatively elevated participation 2.- VWAP-like bias filter A VWAP-like series is computed over vwapLength (typical price weighted by volume) When useVWAPFilter = true: - Longs only if close > vwap - Shorts only if close EMA(slow) When useTrendFilter = true: - Longs only in uptrend - Shorts only in downtrend2.6. Backtest time window (time filter)To keep testing focused and reduce long-history noise:useMaxLookbackDays enables the filtermaxLookbackDays defines how many days back from timenow entries are allowedEntries are permitted only when time >= startTime.3. Entry rules and position control3.1. Entriesstrategy.entry('Long', strategy.long) when longSetup and no long position is openstrategy.entry('Short', strategy.short) when shortSetup and no short position is openNo pyramiding is allowed (pyramiding = 0). Position gating is handled by:Long allowed if strategy.position_size = 04. Risk management: TP/SL and trailing (with plotted lines)4.1. Detecting entry/exit eventsEvents are identified via changes in strategy.position_size:LongEntry: transition into a longshortEntry: transition into a shortflatExit: transition back to flatThis drives per-trade line creation, updates, and cleanup of state variables.4.2. Static TP/SLOn entry, entryPrice := strategy.position_avg_price is stored.Percent mode (usePercent = true)Long:staticSL = entryPrice*(1 - slPerc/100)staticTP = entryPrice*(1 + tpPerc/100)Short:staticSL = entryPrice*(1 + slPerc/100)staticTP = entryPrice*(1 - tpPerc/100)ATR mode (usePercent = false)Long:staticSL = entryPrice - atrAtEntry*slATRstaticTP = entryPrice + atrAtEntry*tpATRShort:staticSL = entryPrice + atrAtEntry*slATRstaticTP = entryPrice - atrAtEntry*tpATR4.3. Trailing stop (custom)While a position is open, the script tracks the most favorable excursion:Long: hhSinceEntry = highest high since entryShort: llSinceEntry = lowest low since entryA trailing candidate is computed:Percent trailing (useTrailPercent = true)Long: trailCandidate = hhSinceEntry*(1 - trailPerc/100)Short: trailCandidate = llSinceEntry*(1 + trailPerc/100)ATR trailing (useTrailPercent = false)Long: trailCandidate = hhSinceEntry - atr*trailATRShort: trailCandidate = llSinceEntry + atr*trailATRThen the effective stop is selected:Long: slUsed = max(staticSL, trailCandidate) when useTrail is enabledShort: slUsed = min(staticSL, trailCandidate) when useTrail is enabledIf useTrail is disabled, slUsed remains the static stop.Take profit remains static:tpUsed = staticTPExit orders are issued via:strategy.exit(..., stop=slUsed, limit=tpUsed)4.4. Per-trade TP/SL linesOn each entry, two lines are created (SL and TP) via f_createLines().During the trade, the SL line updates when trailing moves the stop; TP remains fixed.On exit (flatExit), both lines are finalized on the exit bar and left on the chart as historical references.This makes it straightforward to visually audit each trade: entry context, intended TP, and trailing evolution until exit.5. Visualization and debuggingBUY/SELL labels with configurable size (xsize)Debug mode (showDebug) plots the chosen working support/resistance level each barStored pivot levels are drawn using reusable line slots, projected a fixed 20 bars to the right to keep the chart readable and efficient6. Parameter guidance and practical notespivotLookback / rightBars: controls pivot significance vs responsiveness. Lower rightBars confirms pivots earlier but can increase noise.maxDistATR: too low may reject valid levels; too high may select distant, less relevant levels.minWickATR: key quality gate for “real” sweeps. Higher values reduce frequency but often improve signal quality.Filters:Volume filter tends to help in ranges and active sessions.VWAP bias is useful intraday to align trades with session positioning.EMA trend filter is helpful in directional markets but may remove good mean-reversion setups.Percent TP/SL: provides consistent behavior across assets with variable volatility, but is less adaptive to sudden regime shifts.Percent trailing: can capture extensions well; calibrate trailPerc per asset/timeframe (too tight = premature exits).7. Known limitationsPivot-derived levels are a heuristic; in strong trends, valid retests may be limited.The time filter uses timenow; behavior may vary depending on historical context and how the platform evaluates “current time.”TP/SL and trailing are computed from bar OHLC; in live trading, intrabar sequencing and fills may differ from bar-close simulation.