Volumetric Sweep Gravity Engine [PhenLabs]📊 Volumetric Sweep Gravity Engine
Version: PineScript™ v6
📌 Description
The Volumetric Sweep Gravity Engine detects true liquidity stop-hunts and only keeps the ones backed by real volume absorption. Instead of marking every wick beyond a swing, VSGE scores each sweep with volume expansion, wick geometry, and a candle delta proxy — then projects a Fibonacci golden-zone magnet where price is most likely to get pulled next.
Traders get a clean, high-contrast chart: absorption boxes that intensify with score strength, gold-tinted gravity zones, dotted magnet lines, dual glow signal markers, and a live PhenLabs command dashboard. Built for fast visual reads on crypto, indices, FX, and metals without clutter.
🚀 Points of Innovation
Triple-factor absorption score (volume × wick ratio × delta proxy) filters weak fake sweeps
Liquidity pool tracking from confirmed swing highs/lows with ATR-buffered sweep rules
Automatic Fibonacci golden-zone gravity targets (0.618–0.786) after valid sweeps
Score-reactive zone transparency — stronger absorption draws hotter, more opaque boxes
Dotted magnet projection lines from signal price into the golden-zone midpoint
Live VSGE dashboard with bias, last event, ABS score, GZ magnet, BSL/SSL pools, and vol pulse
🔧 Core Components
Liquidity Pool Engine: Confirms swing highs (BSL) and swing lows (SSL), then watches for wick violations with optional close-back-inside stop-hunt logic
Absorption Scorer: Composites volume-vs-SMA, wick-to-body geometry, and signed volume delta into a 0–100 score with configurable weights
Gravity Projector: Measures the impulse leg and maps the 61.8–78.6 golden zone as the expected rebalance magnet
Visual Command Layer: Absorption boxes, golden zones, magnet lines, glow markers, pool rails, and a gold-framed dashboard
🔥 Key Features
Bullish and bearish volumetric sweep signals with min score gate
Optional EMA trend filter and ATR volatility floor to skip dead markets
Toggleable pool lines, absorption boxes, labels, bar coloring, and magnet lines
Max active zone cap to keep charts clean on lower timeframes
Alert conditions for bull sweeps, bear sweeps, and any sweep
Fully open-source Pine v6 with organized input groups and tooltips
🎨 Visualization
Neon triangle + soft glow circle markers tagged “VSGE” for screenshot-ready signals
Absorption boxes labeled with live ABS % and opacity scaled to conviction
Dashed golden-zone rectangles with centered GOLDEN ZONE text
Dotted gold magnet lines pulling toward the zone midpoint
BSL/SSL pool rails in bear/bull tints for structural context
Top-right dark dashboard with gold border, bias coloring, and vol pulse readout
📖 Usage Guidelines
Swing Lookback — Default: 5 — Range: 2-30 — Higher = fewer, more structural pools
Sweep Buffer (ATR mult) — Default: 0.05 — Range: 0-1 — Extra wick extension required beyond the pool
Require Close Back Inside — Default: true — Enforces classic stop-hunt reclaim closes
Min Sweep Wick (ATR) — Default: 0.15 — Range: 0.05-2 — Rejects tiny liquidity nicks
Volume SMA Length — Default: 20 — Range: 5-100 — Baseline for absorption volume
Absorption Volume Mult — Default: 1.4 — Range: 1-5 — Minimum volume expansion vs SMA
Min Wick/Body Ratio — Default: 1.5 — Range: 0.5-10 — Ensures rejection-style geometry
Min Absorption Score — Default: 55 — Range: 0-100 — Composite gate for signals
Golden Zone Low/High (Fib) — Default: 0.618 / 0.786 — Retracement band for gravity targets
Impulse Lookback Bars — Default: 8 — Range: 3-40 — Bars used to size the impulse leg
Max Active Zones — Default: 6 — Range: 1-20 — Limits drawn boxes/lines/labels
EMA Trend Filter — Default: off — Optional 200 EMA directional gate
Min ATR Volatility Filter — Default: on — Skips low-volatility chop vs ATR SMA
✅ Best Use Cases
Intraday liquidity-grab reversals on crypto, Nasdaq, Gold, and major FX pairs
Confirming stop-hunts before entering toward the golden-zone magnet
Filtering pure wick noise by requiring volumetric absorption
Screenshot-friendly SMC setups for education, social posts, and journal reviews
⚠️ Limitations
Delta is a candle-geometry proxy, not true bid/ask order-flow data
Pivot pools confirm with lag equal to the swing lookback
Golden zones are probabilistic magnets, not guaranteed fill targets
Dense lower-timeframe charts may need higher min score or lower max zones
💡 What Makes This Unique
Fuses liquidity sweeps + volumetric absorption scoring + Fibonacci gravity in one engine — a combination missing from pure sweep or pure Fib tools
Score-reactive visuals make conviction readable at a glance for SEO screenshots and live trading
PhenLabs-style command dashboard turns structure, score, and magnet price into a single decision panel
🔬 How It Works
Map liquidity pools from confirmed swing highs (BSL) and swing lows (SSL)
Detect sweeps when price wicks beyond a pool by ATR buffer and optionally closes back inside
Score absorption using volume expansion, wick/body geometry, and signed delta proxy
If score clears the minimum gate, draw the absorption box and project the 0.618–0.786 golden gravity zone with a magnet line
Update the live dashboard (bias, last event, ABS score, GZ magnet, pools, vol pulse) and fire alerts
💡 Note:
Use VSGE as a confluence layer with your own risk rules, higher-timeframe bias, and position sizing. This is an analytical aid for studying liquidity and absorption behavior — not financial advice. Indicator

Execution Window Planner [AGPro Series]Execution Window Planner
🧠 Core Idea
Where is the cleanest active price window for evaluating execution context?
📌 Overview / What it does
Execution Window Planner is a chart-first execution-readiness tool built to answer one practical question: is price currently sitting inside a clean review window, or is the context too early, too late, too stretched, or already invalidated?
The script maps an active execution window box, a risk edge, a target edge, compact state labels, and a premium AGPro panel. It converts window width, structure alignment, volatility fit, trend support, candle confirmation, and room-to-risk context into a transparent 0-100 Quality Score.
It does not predict price movement, automate orders, or issue buy/sell commands. The output is designed as an analytical planning layer for traders who want cleaner context before making their own execution decisions.
🎯 Purpose & Design Philosophy
This script was built for traders who already have a directional thesis but need a disciplined way to judge whether the current price area is actually usable for execution review.
Many tools show trend, signals, support/resistance, or zones. The missing piece is often the active decision window: the price area where risk is still definable, target room still exists, volatility is not distorted, and confirmation is not too weak.
The design philosophy is simple: execution quality should be evaluated through a defined window, not through excitement around a single candle.
⚡ Why This Script Is Different
Most tools focus on printing a signal, marking a generic support/resistance area, or showing a large multi-feature trading dashboard.
This script does NOT act as a full trading suite, signal service, position sizing tool, ICT/FVG map, order block map, or generic zone scanner.
Instead, it keeps one narrow purpose: identify and score the current execution window using risk edge, target edge, structure, volatility, trend support, and candle confirmation. The result is a focused decision layer rather than another broad indicator.
⚙️ Methodology
1. Context Detection
The script detects the active planning side automatically from trend structure, or lets the user force a long-bias or short-bias view.
2. Reference Mapping
It builds a risk edge from recent structure and a target edge from broader structure or ATR-adjusted room.
3. Window Construction
It creates an active execution window around the current trend reference, then limits that window between the risk edge and target edge.
4. Reaction Evaluation
It scores window width, structure alignment, volatility fit, trend support, and candle confirmation into a 0-100 Quality Score.
5. Visual Output
The chart displays the execution window box, risk/target edges, state labels, alerts, and a premium AGPro panel with the key decision fields.
🗺️ How to Read the Chart
Execution Window = the current price area where the script is evaluating execution context.
Risk Edge = the structure-based invalidation edge for the active window.
Target Edge = the nearest meaningful target-side reference or ATR-adjusted room marker.
Labels = the current window state, score tier, risk distance, and room-to-risk context.
Colors = teal for stronger bullish execution windows, pink for bearish or invalidation contexts, amber for forming/waiting states, and indigo for target-edge or transition states.
Panel = the fastest summary of window state, quality score, risk edge, target edge, and next action.
🚦 Signals & States
• ACTIVE → the execution window meets the quality threshold and confirmation filter.
• FORMING → the window is improving but still needs cleaner confirmation.
• WAIT → the context exists, but structure, volatility, room, or confirmation is not strong enough yet.
• BLOCKED → there is no clean execution window in the current context.
• TARGET EDGE → price has reached the mapped target-side reference and reaction quality should be evaluated.
• INVALIDATED → price closed beyond the active risk edge.
🔔 Alerts Logic
ACTIVE Window alerts trigger when the state upgrades into ACTIVE.
Downgrade alerts trigger when the active window weakens from a stronger previous state.
Risk Edge alerts trigger when price closes beyond the current risk edge.
Target Edge alerts trigger when price reaches the current target edge.
Alerts are attention markers only. They are not trading instructions.
🧩 Confluence Logic
The strongest execution-window context appears when several conditions align:
• Price remains inside the mapped execution window
• The risk edge is still structurally valid
• The target edge leaves enough room relative to risk
• Trend support agrees with the active side
• Candle structure confirms the same direction
• Volatility is close to its recent baseline
When these elements align, the Quality Score improves and the panel state becomes easier to interpret.
📊 When to Use
• When you already have a directional thesis and want to evaluate execution context
• During trend continuation setups where risk and target references remain clear
• Around pullback or reset areas where timing and risk quality matter
• Before reacting to a potential continuation candle
• When you want a cleaner planning layer instead of another simple signal indicator
⚠️ When NOT to Use
• During very low-liquidity conditions where candles print irregularly
• During high-noise chop where risk and target edges change too quickly
• During extreme volatility spikes where ATR context becomes distorted
• On symbols with poor price continuity or unreliable session behavior
• As a standalone reason to enter or exit a trade
🎛️ Key Inputs
• Setup Direction → Auto detects the active planning side, or the user can force Long Bias / Short Bias.
• Sensitivity → controls how selective the model is.
• Structure Lookback → controls how risk edge, target edge, and structure context are mapped.
• Minimum ACTIVE Score → defines the score threshold required for ACTIVE state.
• Confirmation Mode → controls how much trend and candle confirmation must align.
• Label Cooldown Bars → controls historical label density.
• Max Visible Labels → limits older state labels to keep the chart readable.
• Label Detail → Compact is the default clean publication view; Balanced and Full can show more risk/room context.
• Label Offset Strength / Lane Strength → smart placement controls that keep labels near price without burying them inside candles or pushing them too far away on higher timeframes.
• Panel Location / Theme / Font Size → controls the AGPro panel presentation.
• Label Font Size → controls all on-chart labels.
🖥️ Interface & Visual Design
The panel is designed as a compact decision dashboard, not a large command center. The first row uses the standard AGPro merged blue header row, and the remaining rows focus only on the information needed to evaluate the current execution window.
The chart visuals stay restrained: one active execution window, one risk edge, one target edge, a current quality tag, and moderate historical state labels. The goal is a premium, readable chart that does not feel empty but also avoids clutter.
🧪 Practical Usage Workflow
1. Read the panel state first.
2. Check whether price is inside or near the execution window.
3. Compare the risk edge and target edge.
4. Review the Quality Score and confirmation state.
5. Interpret labels as context markers, not as trade commands.
6. Confirm the broader market context with your own process.
🔍 Interpretation Guidelines
ACTIVE does not mean guaranteed continuation. It means the current window has passed the script's rule-based quality model.
FORMING means the setup may be developing, but the script does not yet see enough confirmation.
WAIT means the context may exist, but the window quality is not clean enough.
BLOCKED means the current chart does not offer a useful execution window under the selected settings.
TARGET EDGE means the chart has reached the mapped target-side reference, so reaction quality becomes more important than chasing the move.
INVALIDATED means the risk edge has been broken and the active window should be reset.
🚫 What This Script Is NOT
• Not a prediction engine
• Not financial advice
• Not an auto-trading system
• Not a guaranteed signal tool
• Not a full trading suite
• Not an ICT/FVG or order block map
• Not a generic support/resistance zone scanner
⚠️ Limitations & Transparency
Execution-window quality is rule-based and depends on the selected inputs, timeframe, symbol behavior, and available chart data.
Different timeframes can produce different risk and target edges because market structure changes with resolution.
Fast volatility expansion can make the current edge distances less stable.
Low-volume markets may produce weaker confirmation quality.
The script should be interpreted inside broader market context, not in isolation.
🧠 Market Context Notes
Execution quality is usually strongest when structure, volatility, and trend behavior are aligned.
If volatility expands too quickly, the window can become stretched even if direction looks strong.
If the target edge is too close, the setup may have limited room even when the trend looks clean.
If the risk edge is too far away, the setup may require too much tolerance relative to the available room.
🧾 Use Case Examples
When price pulls back toward the active trend reference, remains inside the execution window, and the risk edge is still structurally protected, the Quality Score may improve.
When price reaches the target edge after an ACTIVE window, the script can shift into TARGET EDGE state so the user can evaluate reaction behavior instead of treating the move as fresh.
When price closes beyond the risk edge, the window becomes INVALIDATED and the panel shifts to a reset-oriented state.
🧱 System Philosophy
Execution Window Planner follows the AGPro Series approach: build scripts that help traders make a decision, not just see another signal.
The script is intentionally narrow. It focuses on one practical question and keeps the chart output centered around that question.
🔐 Non-Promise Statement
No script can provide certainty.
No score guarantees future movement.
No alert should be treated as an instruction to trade.
📉 Risk Disclosure
Trading involves risk.
Users are responsible for their own analysis, execution choices, risk management, and trading outcomes.
This script is for educational and analytical use only and does not provide financial advice.
📚 Educational Note
The best use of this script is to study how execution context changes as price moves between risk edge, execution window, and target edge.
Use it as a structured planning aid, not as a replacement for your own market analysis.
Indicator

Automate on Hyperliquid - Strategy Webhook Template [HYPR-run]DESCRIPTION
You define the entry signal. The system manages everything after the fill. This is a production-grade trade system for automating strategies on Hyperliquid using PulseWire webhooks. Five-level priority chain trade system. Four ATR trailing architectures including volume-weighted ATR with Efficiency Ratio scaling and ratchet floor. Smart stops that exit when a trade is invalidated. Pyramid scaling into winners and a redundant failsafe stop.
Three signal systems are included ready to backtest and deploy (EMA crossover, Turtle breakout, SFP - Swing Failure Pattern) that you can toggle on/off independently; replace or extend them with your own logic in three places: the input toggle, the signal condition, and the priority chain entry call. There are clear landmarks in the code to make it as straightforward as possible.
This strategy is built for you to hit the ground running backtesting or automating with a systematic framework to execute around your entry logic or the example signals provided. All signals fire on confirmed bar closes only. Entries, exits, pyramids, and stops are evaluated at close, not during the bar, so intrabar wick spikes do not trigger the system. This is by design. No lookahead bias: all highest/lowest references use prior-bar offsets, LinReg is calculated with offset=1, and no security() calls are used. The script does not repaint or compound returns.
WHAT THE STRATEGY SYSTEMIZES
1. Five-Level Priority Action Chain
Entries fire first. Pyramids fire second and block exits on the same bar. Trailing exits ride winners. Smart stops catch failing trades early. Failsafe stop is the absolute floor. The if/else order is intentional and prevents conflicts so that every action occurs only when it should.
2. Four ATR Trailing Stop Modes
Select from a dropdown. All use separate long/short look backs and multipliers because drops are faster than rallies; the defaults reflect this asymmetry.
• A3.1: LinReg + plain ATR, no ratchet. Baseline for comparison.
• A4.0 (default): LinReg + volume-weighted ATR + Efficiency Ratio + ratchet. VWATR discounts low-volume bars. ER tightens in chop (0.8x), widens in trend (1.2x). Ratchet means the stop only moves in your favor.
• A4.1: Chandelier + VWATR + ratchet + first-bar multiplier for tighter initial protection.
• A4.2: LinReg + VWATR, no ratchet or ER. Stop moves freely with projection.
***The multipliers determine how much room the stop gives price before triggering. They have the greatest influence on overall system performance and must be tuned to the asset and timeframe being traded. Default values are a starting point, not final settings.
• L Multi: 4.0 (long stop distance). Wider because uptrends are slower and require more room.
• S Multi: 2.0 (short stop distance). Tighter because drops are faster and corrections are sharper.
• Long LB: 14 bars. ATR lookback for long stops.
• Short LB: 26 bars. ATR lookback for short stops; longer lookback smooths volatile short-side moves.
• LinReg LB: 10 bars. LinReg projection window (A3.1, A4.0, A4.2).
• First Bar Mult: 1.5x (A4.1 only). Tighter stop on the entry bar; expands to standard multiplier after.
3. Smart Stops
Two trigger paths, both requiring open P&L below threshold (default -3.5%): (1) price crosses under the trailing stop while losing, or (2) price breaks the entry bar’s structure while losing. Either path exits the trade before the failsafe would trigger. The P&L condition on both paths prevents exits on noise when the trade is still within normal range.
4. Pyramid Entries
Scales into winning trades on 5-bar extremes. Requires full bar confirmation and must be within 13 bars of the initial entry.
5. Basic Entry Quality Filters
Applied automatically to every entry:
• Wick nullification: bars with wicks > 38.2% of range block entries in that direction
• SFP nullification: active reversal patterns block opposing entries
• Full bar filter: candle body must be >= 66.6% of total range
• Bar confirmation: entries only fire on confirmed bars
THREE SIGNALS INCLUDED (replace or extend)
• XO/XU: EMA crossover with four configurable pairs (5/13, 9/26, 12/25, 26/128). Requires price above swing high (longs) or below swing low (shorts) plus volume spike (Dropdown Selection).
• Turtle: 13/26 bar breakout with Lost Trade System logic. First breakout after an opposing signal gets priority.
• SFP: Swing Failure Pattern. Longs fire on either 5/5 with full-body confirmation or 5/2 with bullish candle confirmation and strong volume spike (1.618x average). Shorts fire on 5/5 with full-body or 13/3 with bearish candle confirmation. Dual-path per direction allows the signal to catch both high-conviction structure failures and high-volume reversals. The function accepts any left/right look back combination, making it straightforward to adapt. (#/# refers to pivot look back left and right)
Each has its own toggle. Enable one, combine them, or swap in your own signals.
WEBHOOK AUTOMATION
Every fill event fires through PulseWire’s built-in webhook system when enabled: entries, exits, pyramids, smart stops, and failsafe closes. To execute those webhooks on Hyperliquid, an intermediary service (execution layer) that accepts PulseWire webhooks and routes orders to Hyperliquid's API is required.
Setup:
1. Create an alert on this strategy
2. Set trigger to "Order fills only"
3. Check Webhook URL, paste your endpoint
4. Message box: {"ticker":"{{ticker}}","position":"{{strategy.market_position}}"}
5. Set expiration to Open-ended
The snippet will most likely require customization depending on your execution layer. The {{ticker}} and {{strategy.market_position}} fields are PulseWire placeholders that auto-populate when a strategy signal fires.
We recommend referencing PulseWire’s Strategy Alerts documentation to fully understand placeholder use and function when setting up your snippet for your execution layer: www.pulsewire.com
BUILDING WITH YOUR OWN SIGNALS
The most straightforward path is adding your own entry logic. The ATR module, smart stops, and pyramids can also be edited to preferred logic while still leveraging the systemized structure for clean execution when automating on an exchange.
Option 1: Replace an existing signal. Find its section under the SIGNALS header (look for "EXAMPLE 1", "EXAMPLE 2", or "EXAMPLE 3"). Delete the example code and write your condition in its place. Find the matching entry in the STRATEGY CALLS priority chain and swap the condition variable. The toggle still works; rename its label in the input line. Everything downstream works automatically.
Option 2: Add a new signal. Three places to touch:
1. Copy a strategy toggle line from the STRATEGIES input group, change the variable name and label
2. Add your signal logic in the SIGNALS section as a boolean
3. Add an else-if block in the STRATEGY CALLS priority chain using your toggle as the gate
Two test switches (Tsw1, Tsw2) are reserved in Settings for custom signals.
READING THE CHART
Candles are colored by direction: black bodies up, gray bodies down (Quant Filter toggle).
The trailing stop draws as a colored line following your position: green below price when long, red/orange above price when short. A gradient fill shades the zone between price and the stop; it intensifies as price approaches the exit level.
Green dots on the long stop line and red dots on the short stop line are ratchet markers (A4.0 and A4.1 only). Each dot means the stop locked in a new level and will not pull back.
Entry labels appear at each fill: "xoL" (EMA long), "xuS" (EMA short), "tL" (Turtle long), "tS" (Turtle short), "sfpL"/"sfpS" (SFP entries), "pyrL"/"pyrS" (pyramid adds). Exit labels: "Cl"/"Cs" (trailing close long/short), "smrtstp" (smart stop), "fstp" (failsafe).
SFP candle wicks are color-coded by lookback: 5/5 bull wick = bright green, 5/2 bull wick = dark green, 5/5 bear wick = bright red, 13/3 bear wick = dark red. The shade tells you which configuration triggered — brighter means the more common 5/5 detection, darker means the secondary lookback fired.
Horizontal lines extending from entry price are the Late Entry Window: white solid line is entry price, green dashed line is entry + ATR window, red dashed line is entry - ATR window. Visual reference only; does not affect trade logic. Useful when away from the screen to quickly see if a missed entry is still within a safe ATR range.
Market structure labels (HH, LH, HL, LL) appear at swing pivots when the Structure toggle is enabled.
RISK MATH
Order size is fixed at $5,000 (50% of starting capital). That means it's always a flat $5k order, no compounding. With the failsafe at -5.25%, maximum loss per trade is $262.50, or 2.625% of the $10,000 starting balance.
*Because order size is fixed in dollars while equity grows, risk as a percentage of equity decreases over time: 2.625% at start, 2.1% at $12,500, 1.75% at $15,000. The smart stop triggers before the failsafe in most cases, reducing average realized loss further.
STRATEGY PROPERTIES (What's used in the chart published here)
Strategies (all off by default - toggle on to activate):
• XO/XU: on
• Turtle: on
• SFP: on
Settings:
• Mode: Historical (switch to Bot Mode for live automation - limits calculation depth for speed)
• EMA Pair: 9/26
Risk Management:
• Smart Stop: on | -3.5%
• Failsafe Stop: on | -5.25%
• Mech TP/Cls: on
ATR Trailing Exits:
• Mode: A4.0
• L Multi: 4.0 | S Multi: 2.0
• Lng LB: 14 | Shrt LB: 26
• LinReg: 10 | First Bar: 1.5 (A4.1 only)
Backtest Properties:
• Initial capital: $10,000
• Commission: 0.05%
• Slippage: 2 ticks
• Order size: $5,000 (cash, fixed)
• Fill limit assumption: 5 ticks
• Max risk per trade: $262.50 (2.625% of starting equity)
CREDITS
ATR: J. Welles Wilder (1978).
Efficiency Ratio: Perry Kaufman.
Turtle breakout concept: Richard Donchian. Strategy

Institutional Footprint Divergence Engine🔹 Introduction
This indicator, the Institutional Footprint Divergence Engine, attempts to identify moments where price action and genuine order flow diverge — a condition that historically precedes reversals driven by smart money absorption and distribution. The core idea is this: if price makes a new swing high but the underlying buy-sell delta is contracting, the market is printing a higher high on less aggressive buying pressure, suggesting the move is being distributed into rather than genuinely accumulated. The inverse is equally meaningful at lows.
Unlike traditional divergence indicators that use derivative oscillators like RSI or MACD as the proxy for momentum, this script uses volume delta — the direct arithmetic difference between buying and selling volume at the bar level — sourced natively from PulseWire's newly released request.footprint() function where a Premium or Ultimate subscription is active. On standard charts, the indicator falls back to a tick-estimated delta approximation. The distinction matters, and I'll cover precisely why throughout this description.
Every detected divergence is assigned a composite quality score from 0 to 100, computed across five weighted dimensions that assess the structural strength, volume context, cumulative delta alignment, and volatility regime at the moment of detection. Only divergences that clear a user-defined score threshold are displayed — filtering the noise that plagues most divergence tools.
🔹 The Premise — Why Delta Divergence Reveals Institutional Behavior
🔸 What volume delta actually measures
Every transaction in a liquid market has a buyer and a seller. Volume delta measures the net directional aggression of those transactions: it is the sum of volume that traded at the ask (aggressive buying) minus the volume that traded at the bid (aggressive selling) within a single bar. A positive delta bar means buyers were more aggressive. A negative delta bar means sellers were more aggressive.
This is categorically different from price direction. A bar can close higher while posting a negative delta — meaning price moved up, but sellers were the more aggressive counterparty throughout the move. This is the fingerprint of absorption: a large participant or group of participants quietly selling into rising price, absorbing aggressive buy orders without allowing the market to fall. They want retail to push price higher. They're using that momentum as liquidity to distribute their position.
Delta divergence is the systematic detection of this condition across swing structures.
🔸 The mechanics of absorption at swing highs
Assume price has been in an uptrend and just made a swing high at $4,200 with a delta of +850 contracts — strong buyer aggression confirming the high. Price retraces, then pushes up again to $4,215, printing a higher high. But this time, the delta is only +210. Price went higher. The aggressive buying volume did not.
What does this tell you? The move to $4,215 required proportionally far less buyer aggression than the move to $4,200. Two possibilities explain this: either sellers are absorbing the buying (distribution), or organic buying interest is fading and the move is increasingly resting on passive limit sell orders being consumed by declining buy-side momentum. Either way, the structural message is identical — the higher high is not supported by the order flow that created it, and the probability of continuation has deteriorated meaningfully.
This is the ICT and Smart Money Concepts concept of distribution rendered in order flow terms rather than price structure terms alone.
🔸 The symmetric argument at swing lows
At swing lows, the bullish divergence condition is: price makes a lower low, but the negative delta at that low is less negative than the prior swing low. Less aggressive selling at a lower price. This is absorption at the demand side — large buyers accumulating into weakness, absorbing retail sell orders without allowing price to collapse further. The lower low prints because they let it — they need the price to be there to fill their orders. But the delta tells you that sellers were unable to drive the same aggression they managed at the prior low.
Harris (2003), in his foundational text on market microstructure, describes this phenomenon as informed traders systematically positioning against the uninformed flow — using the uninformed participants' aggression as liquidity.
Cont, Stoikov & Talreja (2010), in their research on limit order book dynamics, demonstrate empirically that large passive participants consistently exploit periods of high aggressive flow imbalance to establish positions at favorable prices.
Delta divergence is not a leading indicator in the traditional sense. It is a coincident indicator of order flow context that becomes meaningful when paired with a confirmed swing structure.
🔸 Why native footprint data changes the calculus
Prior to January 2026, Pine Script had no access to true intrabar volume distribution. Every "delta" calculation in PulseWire scripts was an estimate — typically assigning the bar's total volume directionally based on close position within the bar's range, or using up/down tick counting approximations. These methods are reasonable proxies but they introduce systematic errors: a bar that closes at its midpoint with heavy two-way activity looks identical to a quiet, directionless bar.
PulseWire's request.footprint() function changes this entirely. It exposes the actual buy and sell volume recorded at each price level (row) within the bar — the genuine transaction-level data that footprint chart platforms like Sierra Chart and Bookmap have historically required separate subscriptions and data feeds to access. The delta returned by fp.delta() is not an estimate. It is the arithmetic difference between actual ask-side and bid-side transactions aggregated across the bar.
This is the first time this data has been natively programmable in Pine Script, and IFDE is built specifically around it.
🔹 How It Works
🔸 Footprint Data and the Delta Fallback
On a Premium or Ultimate PulseWire account with a compatible symbol, request.footprint() returns a footprint object for each bar. IFDE calls fp.buy_volume() and fp.sell_volume() to get true directional volume, and fp.delta() for the bar's net delta. It also iterates every price row via fp.rows() and evaluates row.has_buy_imbalance() and row.has_sell_imbalance() — flagging bars where a disproportionate volume cluster exists at a specific price level, which often marks the precise price where institutional absorption occurred.
When footprint data is unavailable (standard account or non-supported symbol), the indicator falls back to a tick-estimated delta: up-close bars assign 100% of volume to the buy side; down-close bars assign 100% to the sell side; inside bars distribute proportionally based on close position within the range. This fallback is clearly flagged in the status label as ⚠️ ESTIMATED. The divergence logic functions identically in both modes — only the precision of the underlying delta changes.
The Ticks Per Footprint Row input controls the price granularity of the footprint: smaller values create more rows with finer resolution, larger values consolidate into fewer, broader rows. For index futures like ES and NQ, 4–10 ticks per row is typically appropriate. For crypto, you may need to experiment depending on the instrument's tick size.
🔸 Swing Pivot Detection
The indicator uses Pine's native ta.pivothigh() and ta.pivotlow() functions to identify confirmed swing highs and lows. The Swing Pivot Length input defines the lookback and lookahead symmetry of the pivot — a value of 10 means a bar must be the highest high within 10 bars on both sides to qualify as a pivot. Higher values find more significant structural swings but introduce more lag. Lower values are more responsive but noisier.
Critically, delta is sampled at the confirmed pivot bar using ta.valuewhen() — not at the current bar. This eliminates the most common repainting failure mode in divergence indicators: using the current bar's momentum reading to classify a past pivot. The delta value associated with each pivot is locked in the moment the pivot is confirmed.
🔸 Divergence Logic
Each time a new pivot high is confirmed, IFDE compares it against the previous confirmed pivot high. If the current price is higher but the current delta is lower, a bearish divergence is registered. The same comparison runs at pivot lows for bullish divergence, where current price lower and current delta less negative triggers the signal.
The Divergence Lookback setting controls the maximum bar distance between the two pivots being compared. Setting this too wide increases the chance of detecting structurally irrelevant comparisons — swings separated by 150 bars on a 5-minute chart may have no meaningful relationship. Setting it too tight misses legitimate multi-leg divergences. 40–60 bars is a reasonable starting point for most timeframes.
🔸 The ML Quality Score (0–100)
This is the engine's core differentiating feature. Every detected divergence is not displayed by default — it must first pass a composite quality score threshold. The score is calculated across five weighted dimensions:
Delta Magnitude is the most heavily weighted dimension by default (30%). It measures how extreme the opposing delta pressure is, normalised against the rolling maximum delta magnitude over the lookback window. A divergence where the delta is merely slightly less positive scores lower than one where the delta has completely reversed sign.
Volume Confirmation (25%) assesses whether total bar volume at the divergence pivot is above the 14-bar average. Low-volume divergences are structurally weaker — the absorption signal requires meaningful participation to be credible.
CVD Alignment (20%) checks whether the Cumulative Volume Delta — the running sum of all bar-level deltas, mean-reverted against its own moving average — is trending in the direction that supports the divergence. A bullish divergence at a price low carries far more weight when CVD has been quietly rising even as price made new lows.
Price Structure (15%) scores the magnitude of the price swing itself, relative to the current ATR. A divergence across a 0.5 ATR swing scores lower than one across a 2.5 ATR swing. Trivially small swings produce trivially meaningful divergence signals.
Regime Bonus (10%) applies a bonus or penalty based on the current volatility regime, described in detail below.
The weights are fully user-configurable in the 🤖 ML Score Weights input group. Shifting weight toward CVD Alignment, for example, will make the score more conservative and context-dependent. Shifting weight toward Delta Magnitude makes it more responsive to extreme single-bar order flow events. The scores are normalised internally so they always sum to 100 regardless of how you distribute the weights.
Only divergences scoring above the Min Quality Score threshold are displayed. The default of 55 is intentionally permissive to begin with. As you develop familiarity with the indicator on your instrument and timeframe, raising this to 65 or 70 will progressively filter toward only the highest-conviction setups.
🔸 Adaptive Regime Detection
The indicator compares the current 14-period ATR against its own simple moving average over the Regime Detection Period to classify the current volatility environment into three states: HIGH VOLATILITY, NORMAL, and LOW VOLATILITY.
In high volatility regimes, the score threshold is automatically scaled up by 20% — making it harder for a divergence to pass. This is because high-volatility environments produce frequent large delta swings that generate divergence signals with greater frequency but lower predictive value. The regime is tightening the filter precisely when noise is highest.
In low volatility regimes, the threshold is scaled down by 15%. Quiet, low-volatility markets are where institutional accumulation and distribution most commonly occurs under the radar — smaller delta contrasts carry more informational weight when total market activity is compressed.
The current regime and adjusted score floor are displayed in the status label in the top-left corner of the pane. A subtle background colour (green tint for low vol, red tint for high vol) is painted on the price chart to give continuous regime context at a glance.
🔸 The Pane Display
The indicator runs in its own pane below the price chart, containing three visual elements:
The delta histogram plots the smoothed EMA of bar-level delta as coloured columns — cyan for positive (net buying) and red for negative (net selling). The colour intensity scales with the magnitude of the delta relative to the recent maximum, so visually dominant bars correspond to the highest-conviction order flow readings.
The CVD deviation line in yellow shows the cumulative volume delta minus its moving average baseline. This is more useful than raw CVD for divergence context because it removes the secular trend in cumulative flow and focuses on relative shifts — making it easy to spot when CVD is rising or falling against price.
The zero line serves as the delta neutrality reference. Bars crossing from negative to positive delta, or vice versa, in the context of a divergence signal are particularly significant.
On the price chart, divergence lines connect the two pivot points being compared, with opacity scaling to score strength — higher-scoring divergences are rendered more vividly. Labels mark each divergence with its star rating (★ for score 55–69, ★★ for 70–84, ★★★ for 85–100) and the actual score value, along with whether live footprint data or tick estimation is in use.
🔹 Settings Reference
Swing Pivot Length — Controls pivot sensitivity. Lower = more signals, higher = more structural significance. Recommended: 8–15.
Divergence Lookback — Maximum bars between the two pivots being compared. Recommended: 30–75.
Min Quality Score — Score threshold below which divergences are hidden. Start at 55, tune upward as you calibrate to your instrument.
Ticks Per Footprint Row — Footprint granularity. Only relevant with live FP data. Tighter rows = more precision, more computation.
Delta Smoothing Period — EMA period applied to raw delta before divergence comparison. Smoothing reduces false triggers from single noisy bars. Recommended: 2–5.
CVD Baseline Length — Period of the SMA used to mean-revert the cumulative delta. Shorter = more responsive CVD; longer = smoother trend.
Alert Min Score — Score threshold for alert conditions. Set higher than the display threshold if you want alerts only for the strongest signals.
🔹 Closing Remarks
Delta divergence is one of the few conditions in technical analysis that has a genuinely defensible mechanical explanation rooted in market microstructure — it is not a pattern-matching heuristic but a direct observation of the imbalance between aggressive buying and selling pressure across a swing structure. The availability of native footprint data in Pine Script for the first time makes it possible to build this kind of tool without the estimations and approximations that have historically compromised order flow analysis within PulseWire.
That said, this indicator is a probabilistic model, not a signal generator. A score of 90 does not mean the trade works. It means the order flow context at that divergence was unusually well-structured relative to the five dimensions measured. Markets can and do continue trending through well-formed divergences, particularly in strongly trending regimes where institutional participants are not distributing but rather re-accumulating on every pullback.
The most effective use of IFDE is as a confluence filter — a condition that must be present alongside your existing structural, session, or macro framework before you engage a level. A bearish divergence at a weekly resistance level, in a high-volatility regime, scoring 82, with live footprint data showing 7 sell imbalance clusters, is a meaningfully different proposition than a 56-scoring divergence on estimated delta at a randomly selected intraday high.
Use the score. Respect the regime. Verify the data source. The rest is your edge.
🔹 References
Market Microstructure & Order Flow
Harris, L. (2003). Trading and Exchanges: Market Microstructure for Practitioners. Oxford University Press.
Cont, R., Stoikov, S., & Talreja, R. (2010). A stochastic model for order book dynamics. Operations Research, 58(3), 549–563.
Volume and Delta Analysis
Easley, D., & O'Hara, M. (1992). Time and the process of security price adjustment. Journal of Finance, 47(2), 577–605.
Easley, D., Hvidkjaer, S., & O'Hara, M. (2002). Is information risk a determinant of asset returns? Journal of Finance, 57(5), 2185–2221.
Institutional Order Flow & Smart Money
Chordia, T., Roll, R., & Subrahmanyam, A. (2002). Order imbalance, liquidity, and market returns. Journal of Financial Economics, 65(1), 111–130.
Grinblatt, M., & Keloharju, M. (2000). The investment behavior and performance of various investor types. Journal of Financial Economics, 55(1), 43–67. Indicator

TFPS_EngineLibrary "TFPS_Engine"
f_calculate_lead_lag(series1, series2, length, max_lag)
Parameters:
series1 (float)
series2 (float)
length (int)
max_lag (int)
f_calculate_pressure_score(spx_ticker, vix_ticker, dxy_ticker, us10y_ticker, benchmark_source, trend_lookback, score_smoothing, use_dynamic_weights, corr_lookback, w_spx, w_vix, w_dxy, w_us10y, zscore_lookback, max_lag)
Parameters:
spx_ticker (string)
vix_ticker (string)
dxy_ticker (string)
us10y_ticker (string)
benchmark_source (float)
trend_lookback (int)
score_smoothing (simple int)
use_dynamic_weights (bool)
corr_lookback (int)
w_spx (float)
w_vix (float)
w_dxy (float)
w_us10y (float)
zscore_lookback (int)
max_lag (int)
LeadLagOutput
Fields:
best_lag (series int)
max_corr (series float)
TFPS_Output
Fields:
historical_score (series float)
smoothed_score (series float)
z_score (series float)
regime_signal (series int)
lead_lag_bars (series int)
lead_lag_corr (series float)
weight_spx (series float)
weight_vix (series float)
weight_dxy (series float)
weight_us10y (series float) Library

*Auto Backtest & Optimize EngineFull-featured Engine for Automatic Backtesting and parameter optimization. Allows you to test millions of different combinations of stop-loss and take profit parameters, including on any connected indicators.
⭕️ Key Futures
Quickly identify the optimal parameters for your strategy.
Automatically generate and test thousands of parameter combinations.
A simple Genetic Algorithm for result selection.
Saves time on manual testing of multiple parameters.
Detailed analysis, sorting, filtering and statistics of results.
Detailed control panel with many tooltips.
Display of key metrics: Profit, Win Rate, etc..
Comprehensive Strategy Score calculation.
In-depth analysis of the performance of different types of stop-losses.
Possibility to use to calculate the best Stop-Take parameters for your position.
Ability to test your own functions and signals.
Customizable visualization of results.
Flexible Stop-Loss Settings:
• Auto ━ Allows you to test all types of Stop Losses at once(listed below).
• S.VOLATY ━ Static stop based on volatility (Fixed, ATR, STDEV).
• Trailing ━ Classic trailing stop following the price.
• Fast Trail ━ Accelerated trailing stop that reacts faster to price movements.
• Volatility ━ Dynamic stop based on volatility indicators.
• Chandelier ━ Stop based on price extremes.
• Activator ━ Dynamic stop based on SAR.
• MA ━ Stop based on moving averages (9 different types).
• SAR ━ Parabolic SAR (Stop and Reverse).
Advanced Take-Profit Options:
• R:R: Risk/Reward ━ sets TP based on SL size.
• T.VOLATY ━ Calculation based on volatility indicators (Fixed, ATR, STDEV).
Testing Modes:
• Stops ━ Cyclical stop-loss testing
• Pivot Point Example ━ Example of using pivot points
• External Example ━ Built-in example how test functions with different parameters
• External Signal ━ Using external signals
⭕️ Usage
━ First Steps:
When opening, select any point on the chart. It will not affect anything until you turn on Manual Start mode (more on this below).
The chart will immediately show the best results of the default Auto mode. You can switch Part's to try to find even better results in the table.
Now you can display any result from the table on the chart by entering its ID in the settings.
Repeat steps 3-4 until you determine which type of Stop Loss you like best. Then set it in the settings instead of Auto mode.
* Example: I flipped through 14 parts before I liked the first result and entered its ID so I could visually evaluate it on the chart.
Then select the stop loss type, choose it in place of Auto mode and repeat steps 3-4 or immediately follow the recommendations of the algorithm.
Now the Genetic Algorithm at the bottom right will prompt you to enter the Parameters you need to search for and select even better results.
Parameters must be entered All at once before they are updated. Enter recommendations strictly in fields with the same names.
Repeat steps 5-6 until there are approximately 10 Part's left or as you like. And after that, easily pour through the remaining Parts and select the best parameters.
━ Example of the finished result.
━ Example of use with Takes
You can also test at the same time along with Take Profit. In this example, I simply enabled Risk/Reward mode and immediately specified in the TP field Maximum RR, Minimum RR and Step. So in this example I can test (3-1) / 0.1 = 20 Takes of different sizes. There are additional tips in the settings.
━
* Soon you will start to understand how the system works and things will become much easier.
* If something doesn't work, just reset the engine settings and start over again.
* Use the tips I have left in the settings and on the Panel.
━ Details:
Sort ━ Sorting results by Score, Profit, Trades, etc..
Filter ━ Filtring results by Score, Profit, Trades, etc..
Trade Type ━ Ability to disable Long\Short but only from statistics.
BackWin ━ Backtest Window Number of Candle the script can test.
Manual Start ━ Enabling it will allow you to call a Stop from a selected point. which you selected when you started the engine.
* If you have a real open position then this mode can help to save good Stop\Take for it.
1 - 9 Сheckboxs ━ Allow you to disable any stop from Auto mode.
Ex Source - Allow you to test Stops/Takes from connected indicators.
Connection guide:
//@version=6
indicator("My script")
rsi = ta.rsi(close, 14)
buy = not na(rsi) and ta.crossover (rsi, 40) // OS = 40
sell = not na(rsi) and ta.crossunder(rsi, 60) // OB = 60
Signal = buy ? +1 : sell ? -1 : 0
plot(Signal, "🔌Connector🔌", display = display.none)
* Format the signal for your indicator in a similar style and then select it in Ex Source.
⭕️ How it Works
Hypothesis of Uniform Distribution of Rare Elements After Mixing.
'This hypothesis states that if an array of N elements contains K valid elements, then after mixing, these valid elements will be approximately uniformly distributed.'
'This means that in a random sample of k elements, the proportion of valid elements should closely match their proportion in the original array, with some random variation.'
'According to the central limit theorem, repeated sampling will result in an average count of valid elements following a normal distribution.'
'This supports the assumption that the valid elements are evenly spread across the array.'
'To test this hypothesis, we can conduct an experiment:'
'Create an array of 1,000,000 elements.'
'Select 1,000 random elements (1%) for validation.'
'Shuffle the array and divide it into groups of 1,000 elements.'
'If the hypothesis holds, each group should contain, on average, 1~ valid element, with minor variations.'
* I'd like to attach more details to My hypothesis but it won't be very relevant here. Since this is a whole separate topic, I will leave the minimum part for understanding the engine.
Practical Application
To apply this hypothesis, I needed a way to generate and thoroughly mix numerous possible combinations. Within Pine, generating over 100,000 combinations presents significant challenges, and storing millions of combinations requires excessive resources.
I developed an efficient mechanism that generates combinations in random order to address these limitations. While conventional methods often produce duplicates or require generating a complete list first, my approach guarantees that the first 10% of possible combinations are both unique and well-distributed. Based on my hypothesis, this sampling is sufficient to determine optimal testing parameters.
Most generators and randomizers fail to accommodate both my hypothesis and Pine's constraints. My solution utilizes a simple Linear Congruential Generator (LCG) for pseudo-randomization, enhanced with prime numbers to increase entropy during generation. I pre-generate the entire parameter range and then apply systematic mixing. This approach, combined with a hybrid combinatorial array-filling technique with linear distribution, delivers excellent generation quality.
My engine can efficiently generate and verify 300 unique combinations per batch. Based on the above, to determine optimal values, only 10-20 Parts need to be manually scrolled through to find the appropriate value or range, eliminating the need for exhaustive testing of millions of parameter combinations.
For the Score statistic I applied all the same, generated a range of Weights, distributed them randomly for each type of statistic to avoid manual distribution.
Score ━ based on Trade, Profit, WinRate, Profit Factor, Drawdown, Sharpe & Sortino & Omega & Calmar Ratio.
⭕️ Notes
For attentive users, a little tricks :)
To save time, switch parts every 3 seconds without waiting for it to load. After 10-20 parts, stop and wait for loading. If the pause is correct, you can switch between the rest of the parts without loading, as they will be cached. This used to work without having to wait for a pause, but now it does slower. This will save a lot of time if you are going to do a deeper backtest.
Sometimes you'll get the error “The scripts take too long to execute.”
For a quick fix you just need to switch the TF or Ticker back and forth and most likely everything will load.
The error appears because of problems on the side of the site because the engine is very heavy. It can also appear if you set too long a period for testing in BackWin or use a heavy indicator for testing.
Manual Start - Allow you to Start you Result from any point. Which in turn can help you choose a good stop-stick for your real position.
* It took me half a year from idea to current realization. This seems to be one of the few ways to build something automatic in backtest format and in this particular Pine environment. There are already better projects in other languages, and they are created much easier and faster because there are no limitations except for personal PC. If you see solutions to improve this system I would be glad if you share the code. At the moment I am tired and will continue him not soon.
Also You can use my previosly big Backtest project with more manual settings(updated soon)
Indicator

3D BowlingIntroducing the "3D Bowling Game" – a fun and interactive demo scene project in Pine Script, powered by a custom 3D engine! This bowling game showcases the potential of Pine Script for developing engaging and immersive experiences, even within the confines of a trading platform.
To play the game, you'll first be prompted to choose where you want to throw the ball. Next, you'll be asked to draw a line indicating the direction you want the ball to go. Sit back and enjoy as the game takes care of the rest!
The source code features various sections, including:
Types and helper functions to manipulate vectors, matrices, and angles
Routines for calculating cross products, dot products, and vector normalization
Transformation matrices for rotation and scaling
Functions for perspective transformation, mesh transformations, and face normal calculations
Culling and shading algorithms to provide a more realistic visual experience
The project's source code is an excellent starting point for anyone interested in exploring the capabilities of Pine Script beyond the typical trading indicators and strategies. The 3D Bowling Game demonstrates the flexibility of Pine Script and its potential for creating interactive experiences in a seemingly unconventional environment.
So, what are you waiting for? Dive into the source code, tweak it to your liking, or build upon it to create your own interactive 3D experiences. Enjoy the game, and happy coding!
With light. I will say there is an issue with the fact that you cant draw as may linefills as you can lines.
Indicator

3D Engine OverlayThe Overlay 3D Engine is an advanced and innovative indicator designed to render 3D objects on a trading chart using Pine Script language. This tool enables users to visualize complex geometric shapes and structures on their charts, providing a unique perspective on market trends and data. It is recommended to use this indicator with a time frame of 1 week or greater.
The code defines various data structures, such as vectors, faces, meshes, locations, objects, and cameras, to represent the 3D objects and their position in the 3D space. It also provides a set of functions to manipulate these structures, such as scaling, rotating, and translating the objects, as well as calculating their perspective transformation based on a given camera.
The main function, "render," takes a list of 3D objects (the scene) and a camera as input, processes the scene, and then generates the corresponding 2D lines to be drawn on the chart. The true range of the asset's price is calculated using an Exponential Moving Average (EMA), which helps adjust the rendering based on the asset's volatility.
The perspective transformation function "perspective_transform" takes a mesh, a camera, an object's vertical offset, and the true range as input and computes the 2D coordinates for each vertex in the mesh. These coordinates are then used to create a list of polygons that represent the visible faces of the objects in the scene.
The "process_scene" function takes a list of 3D objects and a camera as input and applies the perspective transformation to each object in the scene, generating a list of 2D polygons that represent the visible faces of the objects.
Finally, the "render" function iterates through the list of 2D polygons and draws the corresponding lines on the chart, effectively rendering the 3D objects in a 2D projection on the trading chart. The rendering is done using Pine Script's built-in "line" function, which allows for scalable and efficient visualization of the objects.
One of the challenges faced while developing the Overlay 3D Engine indicator was ensuring that the 3D objects rendered on the chart would automatically scale correctly for different time frames and trading pairs. Various assets and time frames exhibit different price ranges and volatilities, which can make it difficult to create a one-size-fits-all solution for rendering the 3D objects in a visually appealing and easily interpretable manner.
To overcome this challenge, I implemented a dynamic scaling mechanism that leverages the true range of the asset's price and a calculated ratio. The true range is calculated using an Exponential Moving Average (EMA) of the difference between the high and low prices of the asset. This measure provides a smooth estimate of the asset's volatility, which is then used to adjust the scaling of the 3D objects rendered on the chart.
The ratio is calculated by dividing the asset's opening price by the true range, which is then divided by a constant factor (32 in this case). This ratio effectively normalizes the scaling of the 3D objects based on the asset's price and volatility, ensuring that the rendered objects appear correctly sized and positioned on the chart, regardless of the time frame or trading pair being analyzed.
By incorporating the true range and the calculated ratio into the rendering process, the Overlay 3D Engine indicator is able to automatically adjust the scaling of the 3D objects on the chart, providing a consistent and visually appealing representation of the objects across various time frames and trading pairs. This dynamic scaling mechanism enhances the overall utility and versatility of the indicator, making it a valuable tool for traders and analysts seeking a unique perspective on market trends.
In addition to the dynamic scaling mechanism mentioned earlier, the Overlay 3D Engine indicator also employs a sophisticated perspective transformation to render the 3D objects on the chart. Perspective transformation is an essential aspect of 3D graphics, as it provides the necessary conversion from 3D coordinates to 2D coordinates, allowing the 3D objects to be displayed on a 2D chart.
The perspective transformation process in the Overlay 3D Engine indicator begins by taking the 3D mesh data of the objects and transforming their vertices based on the position, orientation, and field of view of a virtual camera. The camera's field of view (FOV) is adjusted using a tangent function, which ensures that the rendered objects appear with the correct perspective, regardless of the chart's aspect ratio.
Once the vertices of the 3D objects have been transformed, the perspective-transformed 2D coordinates are then used to create polygons that can be rendered on the chart. These polygons represent the visible faces of the 3D objects and are drawn using lines that connect the transformed vertices.
The incorporation of perspective transformation in the Overlay 3D Engine indicator ensures that the 3D objects are rendered with a realistic appearance, providing a visually engaging and informative representation of the market trends. This technique, combined with the dynamic scaling mechanism, makes the Overlay 3D Engine indicator a powerful and innovative tool for traders and analysts seeking to visualize and interpret market data in a unique and insightful manner.
In summary, the Overlay 3D Engine indicator offers a novel way to interpret and visualize market data, enhancing the overall trading experience by providing a unique perspective on market trends. Indicator

3D EngineHello everyone,
I am excited to share with you the first 3D engine in Pine Script! This is a remarkable achievement that will enable traders to explore the possibilities of 3D objects in their technical analysis.
To use this engine, you will need to use a higher time frame (1W or greater) to load the 3D objects in time. The code is straightforward and easy to use, with various input options to customize the object's position, rotation, and scale. You can select between two default 3D objects, Pin or Ball, by changing the 'list' input string.
The 3D engine is based on the vector and mesh data structures, and it includes several utility functions to perform operations such as rotation, translation, and scaling on these structures. It also includes functions to calculate perspective transformation for projecting 3D objects onto a 2D surface, which is the essential step in rendering the object in a 2D chart.
The 'process_scene' function is the main function that converts the 3D object data into 2D polygon data, which can be rendered on the chart. This function uses the 'process_object' function, which applies the object's transformation (position, rotation, and scale) and returns a scaled and rotated mesh that is ready for projection.
At the end of the code, there is a camera object that defines the camera's position, target, and field of view. You can customize this camera object to change the perspective of the rendered object.
To make your own 3D object, you can use the included Python program to convert an OBJ file into the format used by the engine. This program converts the OBJ file into a list of vector4 objects, which can be copy-pasted into the 'pin_vertex_list' array or a similar array. Please note that this process requires some knowledge of Python and the OBJ file format.
Overall, this is a fantastic achievement that opens up new possibilities for technical analysis in Pine Script. I encourage you to try it out and see what you can create with it.
In this code, there are several functions and data structures used to represent and manipulate 3D objects in a simple 3D engine. I will explain each function in detail below:
radians(degree): Converts an angle in degrees to radians.
quat_identity(): Returns a quaternion representing the identity rotation.
quat_from_axis_angle(axis, angle): Creates a quaternion from an axis of rotation and an angle.
quat_multiply(q1, q2): Multiplies two quaternions, q1 and q2, and returns the result.
quat_conjugate(q): Returns the conjugate of a quaternion, q.
quat_rotate(q, v): Rotates a 3D vector, v, by a quaternion, q, and returns the result.
rotate_vector_by_quaternion(v, q): Rotates a 3D vector, v, by a quaternion, q, and returns the result.
scale_vector(vector, constant): Scales a 3D vector by a constant and returns the result.
scale_mesh(mesh_obj, constant): Scales a mesh by a constant and returns the new mesh.
rotate_mesh(mesh_obj, axis, angle): Rotates a mesh around a specified axis by a given angle and returns the new mesh.
quat_translate(src, offset): Translates a 3D vector, src, by an offset and returns the result.
translate_mesh(mesh_obj, offset): Translates a mesh by an offset and returns the new mesh.
perspective_transform(msh, cam): Transforms a 3D mesh into a 2D mesh using a camera.
process_object(obj, cam): Processes a 3D object with a camera and returns a 2D mesh.
size(scene): Calculates the total number of vertices in a scene.
make_poly(scene): Converts a scene of 2D meshes into an array of polygons.
process_scene(scn, cam): Processes an entire scene of 3D objects with a camera and returns an array of polygons.
These functions work together to create a simple 3D engine that can manipulate, transform, and render 3D objects as 2D polygons. The main part of the script defines the camera, vertices, and faces for a pin object, and then uses the functions to process and render the object.
Note that some types are also defined in the code, including vector2, vector3, vector4, face, mesh, mesh2d, location, object, poly4, polyg, and camera. These types represent various mathematical structures and entities used in 3D graphics, such as vectors, faces, meshes, and cameras.
Here is an explanation of the inputs for all the functions in the given code:
radians(degree):
degree: Angle in degrees to be converted to radians.
quat_from_axis_angle(axis, angle):
axis: A vector3 object representing the axis of rotation.
angle: The angle in radians to rotate about the axis.
quat_multiply(q1, q2):
q1, q2: Two quaternion objects to be multiplied.
quat_conjugate(q):
q: A quaternion object whose conjugate is to be calculated.
quat_rotate(q, v):
q: The quaternion representing the rotation.
v: The vector3 object to be rotated.
rotate_vector_by_quaternion(v, q):
v: The vector3 object to be rotated.
q: The quaternion representing the rotation.
scale_vector(vector, constant):
vector: A vector4 object to be scaled.
constant: The scaling factor.
scale_mesh(mesh_obj, constant):
mesh_obj: A mesh object to be scaled.
constant: The scaling factor.
rotate_mesh(mesh_obj, axis, angle):
mesh_obj: A mesh object to be rotated.
axis: A vector3 object representing the axis of rotation.
angle: The angle in radians to rotate the mesh.
quat_translate(src, offset):
src: A vector4 object representing the source position.
offset: A vector3 object representing the translation offset.
translate_mesh(mesh_obj, offset):
mesh_obj: A mesh object to be translated.
offset: A vector3 object representing the translation offset.
perspective_transform(msh, cam):
msh: A mesh object to be transformed.
cam: A camera object used for the transformation.
process_object(obj, cam):
obj: An object containing a mesh and its location.
cam: A camera object used for processing the object.
make_poly(scene):
scene: An array of mesh2d objects to generate polygons from.
process_scene(scn, cam):
scn: An array of objects containing meshes and their locations.
cam: A camera object used for processing the scene.
Note that some of these functions are utility functions or internal functions, and their inputs are derived from other functions or user inputs.
I will make a library eventually. Indicator

Replica of PulseWire's Backtesting Engine with ArraysHello everyone,
Here is a perfectly replicated PulseWire backtesting engine condensed into a single library function calculated with arrays. It includes PulseWire's calculations for Net profit, Total Trades, Percent of Trades Profitable, Profit Factor, Max Drawdown (absolute and percent), and Average Trade (absolute and percent). Here's how PulseWire defines each aspect of its backtesting system:
Net Profit: The overall profit or loss achieved.
Total Trades: The total number of closed trades, winning and losing.
Percent Profitable: The percentage of winning trades, the number of winning trades divided by the total number of closed trades.
Profit Factor: The amount of money the strategy made for every unit of money it lost, gross profits divided by gross losses.
Max Drawdown: The greatest loss drawdown, i.e., the greatest possible loss the strategy had compared to its highest profits.
Average Trade: The sum of money gained or lost by the average trade, Net Profit divided by the overall number of closed trades.
Here's how each variable is defined in the library function:
_backtest(bool _enter, bool _exit, float _startQty, float _tradeQty)
bool _enter: When the strategy should enter a trade (entry condition)
bool _exit: When the strategy should exit a trade (exit condition)
float _startQty: The starting capital in the account (for BTCUSD, it is the amount of USD the account starts with)
float _tradeQty: The amount of capital traded (if set to 1000 on BTCUSD, it will trade 1000 USD on each trade)
Currently, this library only works with long strategies, and I've included a commented out section under DEMO STRATEGY where you can replicate my results with PulseWire's backtesting engine. There's tons I could do with this beyond what is shown, but this was a project I worked on back in June of 2022 before getting burned out. Feel free to comment with any suggestions or bugs, and I'll try to add or fix them all soon. Here's my list of thing to add to the library currently (may not all be added):
Add commission calculations.
Add support for shorting
Add a graph that resembles PulseWire's overview graph.
Clean and optimize code.
Clean up in a way that makes it easy to add other PulseWire calculations (such as Sharpe and Sortino ratio).
Separate all variables, so they become accessible outside of calculations (such as gross profit, gross loss, number of winning trades, number of losing trades, etc.).
Thanks for reading,
OztheWoz Library

Visual RSI [LucF]Visual RSI offers a different way of looking at RSI by providing a composite representation of 9 different RSI-generated components. Instead of focusing on one line only, this approach blends multiple sources to provide the viewer with a larger context RSI-based picture.
For those who don’t want to read
• Green in bullish (>50) zone is the most bullish.
• Red in bullish zone doesn’t necessarily mean bearish—it just means bullish strength is weakening. It may be just a pause before a reprise or exhaustion signalling a reversal—impossible to tell.
• The same in inverse applies to the bearish zone (<50).
For those who want to understand
The nine components making up Visual RSI are:
• a current timeframe RSI
• a higher timeframe RSI
• the delta between these two RSI lines
• for each of these three basic components, two independent Bollinger band: one calculated for the bullish section of the scale (>50) and a separate one calculated for the lower bearish region.
Dual BBs
In my view, RSI’s position with regards to the centerline is much more important than its position in extreme areas. Why? Because the building block of RSI is the ratio of the averages of up/down moves during the RSI period. When the average of ups is greater, RSI is > 50. So while a rising signal starting from 20 let’s say, indicates that the rate of change is increasing, only when it crosses 50 can we say that sentiment balance has truly become bullish, and this information is more reliable than the signal being at a level corresponding to whatever estimate we make of what constitutes an extreme value. In my landscape, the general balance of a ratio provides more valuable information than the ratio’s exact value.
The idea behind the dual BBs is to provide independent tracking information for both halves of the indicator’s space, which I find more useful than the normal method of simply adding a multiple of the standard deviation on both sides of the mean. With dual BBs, the upper BB will never go lower than the indicator’s centerline, and the lower BB will never go higher. The upper BB focuses on upper-bound volatility when the signal is bearish, and the lower BB focuses on downside volatility when the signal is bearish.
The functions used to calculate the independent BBs are reusable on other signals if a centerline can be defined for them. A clamping percentage is implemented, so that when a BB line is hugging the centerline it clamps to it. This helps in providing earlier signals when they use the BB line states.
Providing context to RSI
What RSI measures indirectly is the balance in the rate of change—or the speed of price movement, but not its instant value, otherwise RSI would be even noisier. More precisely, RSI represents the relative strength of the up/down movement in the last n bars of RSI’s length, with 14 often used because that’s what Wilder proposed (Visual RSI’s defaults are 20 for the current timeframe and 40 for the higher timeframe). At every bar, a new value is added to the equation and an old value carrying equal weight is dropped, so a large dropped off value will have more impact on RSI’s value if the new bar’s move is small. This accounts for some of RSI’s speed in identifying exhaustion after important moves, but almost for some of its noise.
Visual RSI is the result of trying to drown RSI’s noise in the context of other informational streams, while simultaneously providing even faster information than RSI alone, by giving more visual weight to the delta between the current and higher timeframe RSI’s.
How to read Visual RSI
The default settings show all 9 basic components as green/red areas of intensities varying with their importance. The most intense colors are reserved for the delta RSI and the BBs have the lightest intensities. The individual lines of components are intentionally difficult to distinguish so that focus is first on the general picture, including the all-important six-state background, and then on the delta RSI.
One entry setup could be reversals in a larger trend context, so low pivots of the delta in a fully bullish context (a green background in the upper section of the indicator), and inversely, high pivots in a fully bearish context (a red background in the lower section of the indicator).
Please resist the common misconception, when interpreting RSI, that a reversal in the signal will necessarily lead to a reversal in price. Each trend has its rhythm. Only machine-generated price action can progress regularly. It’s normal for trends to take a breather for some time before they continue or reverse, as traders driving the trend experience emotional fatigue and gradual fear. RSI reversals merely signify that such a breather has occurred—nothing more. Only the larger context can provide information that can situate that pause and put more meaningful odds on it having more probability of continuing in one direction or the other. This is the reasoning behind the setup just described.
Features
• All components can be hidden, displayed as a simple line, a uniformly colored fill, or a green/red fill (the default).
• The background can be colored using 9 different methods, including 3 six-state methods using the rising/falling BB lines of the 3 basic components. These six states allow for bullish/bearish/neutral sentiment in both the upper and lower regions of the indicator. A bearish (dark red) background in the bullish (>50) section of the indicator represents decreasing bullishness. A bearish (slightly brighter red) in the bearish (<50) section of the indicator means incresingly bearish sentiment. The six-state backgrounds allow for neutral (no color) sentiment when no compelling signs can be found to conclude anything with meaningful odds. The default background uses the six-state method on the higher timeframe RSI’s BBs because I find it the most useful, as it represents the largest—and slowest—context sentiment among all the indicator’s components.
• A thin status bar in the top part of the indicator also allows selection of the same 9 methods to color it. The default is a triple-state system using the rising/falling characteristics of the current timeframe RSI’s BBs to provide a short-term counterbalance to the long-term background.
• Three different markers can be configured using approximately 70 permutations each, each filtered by 20 different filter permutations. When modification of the relevant parameters in the script’s Settings/Settings/Parameters section is added, possibilities are almost endless. If the generated signals are then fed into the PineCoders Engine and combined with the Engine’s own options, the permutations go up another order of magnitude, and changes to any setting can be instantly evaluated using the Engine’s backtesting results.
• Five simple filters can be combined. They are additive. They include volume-related conditions and a chandelier, which I find useful because both volume and volatility (the chandelier using highs/lows and ATR) are sensible complementary sources to RSI’s momentum information. The filter’s state can be shown as a thin line at the bottom of the indicator.
• Alerts can be configured using any of the marker/filter combinations mentioned. As usual, once your markers/filters are set up the way you want, create your alert from the chart/timeframe you want the alert to run on and be sure to use the “Once Per Bar Close” triggering condition. Use an alert message that will remind you of which combination of markers were used when creating the alert.
• A plot providing entry signals for the PineCoders Backtesting & Trading Engine is supplied. It will use whichever marker/filter configuration is active to generate signals.
• All higher timeframe information is non-repainting. Higher timeframe lines can be smoothed (the default). The selection of the higher timeframe can be made using 3 different methods:
1. By steps (if current timeframe <= 1 minute: 60 min, <= 60 min: 1D, <= 6H: 3D, <= 1D: 1W, <=1W: 1M, >1W: 12M)
2. By a user-defined multiple of the current timeframe
3. Using a fixed timeframe
Thanks to:
• Alex Orekhov aka @everget for the chandelier code.
• @RicardoSantos who through a small remark early on, unknowingly put me on the track of eliminating noise through visual crowding.
• The brilliant guys in the PineCoders Pro room for your knowledge, limitless creativity and constant companionship.
Indicator

Backtesting & Trading Engine [PineCoders]The PineCoders Backtesting and Trading Engine is a sophisticated framework with hybrid code that can run as a study to generate alerts for automated or discretionary trading while simultaneously providing backtest results. It can also easily be converted to a PulseWire strategy in order to run TV backtesting. The Engine comes with many built-in strats for entries, filters, stops and exits, but you can also add you own.
If, like any self-respecting strategy modeler should, you spend a reasonable amount of time constantly researching new strategies and tinkering, our hope is that the Engine will become your inseparable go-to tool to test the validity of your creations, as once your tests are conclusive, you will be able to run this code as a study to generate the alerts required to put it in real-world use, whether for discretionary trading or to interface with an execution bot/app. You may also find the backtesting results the Engine produces in study mode enough for your needs and spend most of your time there, only occasionally converting to strategy mode in order to backtest using TV backtesting.
As you will quickly grasp when you bring up this script’s Settings, this is a complex tool. While you will be able to see results very quickly by just putting it on a chart and using its built-in strategies, in order to reap the full benefits of the PineCoders Engine, you will need to invest the time required to understand the subtleties involved in putting all its potential into play.
Disclaimer: use the Engine at your own risk.
Before we delve in more detail, here’s a bird’s eye view of the Engine’s features:
More than 40 built-in strategies,
Customizable components,
Coupling with your own external indicator,
Simple conversion from Study to Strategy modes,
Post-Exit analysis to search for alternate trade outcomes,
Use of the Data Window to show detailed bar by bar trade information and global statistics, including some not provided by TV backtesting,
Plotting of reminders and generation of alerts on in-trade events.
By combining your own strats to the built-in strats supplied with the Engine, and then tuning the numerous options and parameters in the Inputs dialog box, you will be able to play what-if scenarios from an infinite number of permutations.
USE CASES
You have written an indicator that provides an entry strat but it’s missing other components like a filter and a stop strategy. You add a plot in your indicator that respects the Engine’s External Signal Protocol, connect it to the Engine by simply selecting your indicator’s plot name in the Engine’s Settings/Inputs and then run tests on different combinations of entry stops, in-trade stops and profit taking strats to find out which one produces the best results with your entry strat.
You are building a complex strategy that you will want to run as an indicator generating alerts to be sent to a third-party execution bot. You insert your code in the Engine’s modules and leverage its trade management code to quickly move your strategy into production.
You have many different filters and want to explore results using them separately or in combination. Integrate the filter code in the Engine and run through different permutations or hook up your filtering through the external input and control your filter combos from your indicator.
You are tweaking the parameters of your entry, filter or stop strat. You integrate it in the Engine and evaluate its performance using the Engine’s statistics.
You always wondered what results a random entry strat would yield on your markets. You use the Engine’s built-in random entry strat and test it using different combinations of filters, stop and exit strats.
You want to evaluate the impact of fees and slippage on your strategy. You use the Engine’s inputs to play with different values and get immediate feedback in the detailed numbers provided in the Data Window.
You just want to inspect the individual trades your strategy generates. You include it in the Engine and then inspect trades visually on your charts, looking at the numbers in the Data Window as you move your cursor around.
You have never written a production-grade strategy and you want to learn how. Inspect the code in the Engine; you will find essential components typical of what is being used in actual trading systems.
You have run your system for a while and have compiled actual slippage information and your broker/exchange has updated his fees schedule. You enter the information in the Engine and run it on your markets to see the impact this has on your results.
FEATURES
Before going into the detail of the Inputs and the Data Window numbers, here’s a more detailed overview of the Engine’s features.
Built-in strats
The engine comes with more than 40 pre-coded strategies for the following standard system components:
Entries,
Filters,
Entry stops,
2 stage in-trade stops with kick-in rules,
Pyramiding rules,
Hard exits.
While some of the filter and stop strats provided may be useful in production-quality systems, you will not devise crazy profit-generating systems using only the entry strats supplied; that part is still up to you, as will be finding the elusive combination of components that makes winning systems. The Engine will, however, provide you with a solid foundation where all the trade management nitty-gritty is handled for you. By binding your custom strats to the Engine, you will be able to build reliable systems of the best quality currently allowed on the TV platform.
On-chart trade information
As you move over the bars in a trade, you will see trade numbers in the Data Window change at each bar. The engine calculates the P&L at every bar, including slippage and fees that would be incurred were the trade exited at that bar’s close. If the trade includes pyramided entries, those will be taken into account as well, although for those, final fees and slippage are only calculated at the trade’s exit.
You can also see on-chart markers for the entry level, stop positions, in-trade special events and entries/exits (you will want to disable these when using the Engine in strategy mode to see TV backtesting results).
Customization
You can couple your own strats to the Engine in two ways:
1. By inserting your own code in the Engine’s different modules. The modular design should enable you to do so with minimal effort by following the instructions in the code.
2. By linking an external indicator to the engine. After making the proper selections in the engine’s Settings and providing values respecting the engine’s protocol, your external indicator can, when the Engine is used in Indicator mode only:
Tell the engine when to enter long or short trades, but let the engine’s in-trade stop and exit strats manage the exits,
Signal both entries and exits,
Provide an entry stop along with your entry signal,
Filter other entry signals generated by any of the engine’s entry strats.
Conversion from strategy to study
PulseWire strategies are required to backtest using the PulseWire backtesting feature, but if you want to generate alerts with your script, whether for automated trading or just to trigger alerts that you will use in discretionary trading, your code has to run as a study since, for the time being, strategies can’t generate alerts. From hereon we will use indicator as a synonym for study.
Unless you want to maintain two code bases, you will need hybrid code that easily flips between strategy and indicator modes, and your code will need to restrict its use of strategy() calls and their arguments if it’s going to be able to run both as an indicator and a strategy using the same trade logic. That’s one of the benefits of using this Engine. Once you will have entered your own strats in the Engine, it will be a matter of commenting/uncommenting only four lines of code to flip between indicator and strategy modes in a matter of seconds.
Additionally, even when running in Indicator mode, the Engine will still provide you with precious numbers on your individual trades and global results, some of which are not available with normal PulseWire backtesting.
Post-Exit Analysis for alternate outcomes (PEA)
While typical backtesting shows results of trade outcomes, PEA focuses on what could have happened after the exit. The intention is to help traders get an idea of the opportunity/risk in the bars following the trade in order to evaluate if their exit strategies are too aggressive or conservative.
After a trade is exited, the Engine’s PEA module continues analyzing outcomes for a user-defined quantity of bars. It identifies the maximum opportunity and risk available in that space, and calculates the drawdown required to reach the highest opportunity level post-exit, while recording the number of bars to that point.
Typically, if you can’t find opportunity greater than 1X past your trade using a few different reasonable lengths of PEA, your strategy is doing pretty good at capturing opportunity. Remember that 100% of opportunity is never capturable. If, however, PEA was finding post-trade maximum opportunity of 3 or 4X with average drawdowns of 0.3 to those areas, this could be a clue revealing your system is exiting trades prematurely. To analyze PEA numbers, you can uncomment complete sets of plots in the Plot module to reveal detailed global and individual PEA numbers.
Statistics
The Engine provides stats on your trades that TV backtesting does not provide, such as:
Average Profitability Per Trade (APPT), aka statistical expectancy, a crucial value.
APPT per bar,
Average stop size,
Traded volume .
It also shows you on a trade-by-trade basis, on-going individual trade results and data.
In-trade events
In-trade events can plot reminders and trigger alerts when they occur. The built-in events are:
Price approaching stop,
Possible tops/bottoms,
Large stop movement (for discretionary trading where stop is moved manually),
Large price movements.
Slippage and Fees
Even when running in indicator mode, the Engine allows for slippage and fees to be included in the logic and test results.
Alerts
The alert creation mechanism allows you to configure alerts on any combination of the normal or pyramided entries, exits and in-trade events.
Backtesting results
A few words on the numbers calculated in the Engine. Priority is given to numbers not shown in TV backtesting, as you can readily convert the script to a strategy if you need them.
We have chosen to focus on numbers expressing results relative to X (the trade’s risk) rather than in absolute currency numbers or in other more conventional but less useful ways. For example, most of the individual trade results are not shown in percentages, as this unit of measure is often less meaningful than those expressed in units of risk (X). A trade that closes with a +25% result, for example, is a poor outcome if it was entered with a -50% stop. Expressed in X, this trade’s P&L becomes 0.5, which provides much better insight into the trade’s outcome. A trade that closes with a P&L of +2X has earned twice the risk incurred upon entry, which would represent a pre-trade risk:reward ratio of 2.
The way to go about it when you think in X’s and that you adopt the sound risk management policy to risk a fixed percentage of your account on each trade is to equate a currency value to a unit of X. E.g. your account is 10K USD and you decide you will risk a maximum of 1% of it on each trade. That means your unit of X for each trade is worth 100 USD. If your APPT is 2X, this means every time you risk 100 USD in a trade, you can expect to make, on average, 200 USD.
By presenting results this way, we hope that the Engine’s statistics will appeal to those cognisant of sound risk management strategies, while gently leading traders who aren’t, towards them.
We trade to turn in tangible profits of course, so at some point currency must come into play. Accordingly, some values such as equity, P&L, slippage and fees are expressed in currency.
Many of the usual numbers shown in TV backtests are nonetheless available, but they have been commented out in the Engine’s Plot module.
Position sizing and risk management
All good system designers understand that optimal risk management is at the very heart of all winning strategies. The risk in a trade is defined by the fraction of current equity represented by the amplitude of the stop, so in order to manage risk optimally on each trade, position size should adjust to the stop’s amplitude. Systems that enter trades with a fixed stop amplitude can get away with calculating position size as a fixed percentage of current equity. In the context of a test run where equity varies, what represents a fixed amount of risk translates into different currency values.
Dynamically adjusting position size throughout a system’s life is optimal in many ways. First, as position sizing will vary with current equity, it reproduces a behavioral pattern common to experienced traders, who will dial down risk when confronted to poor performance and increase it when performance improves. Second, limiting risk confers more predictability to statistical test results. Third, position sizing isn’t just about managing risk, it’s also about maximizing opportunity. By using the maximum leverage (no reference to trading on margin here) into the trade that your risk management strategy allows, a dynamic position size allows you to capture maximal opportunity.
To calculate position sizes using the fixed risk method, we use the following formula: Position = Account * MaxRisk% / Stop% [, which calculates a position size taking into account the trade’s entry stop so that if the trade is stopped out, 100 USD will be lost. For someone who manages risk this way, common instructions to invest a certain percentage of your account in a position are simply worthless, as they do not take into account the risk incurred in the trade.
The Engine lets you select either the fixed risk or fixed percentage of equity position sizing methods. The closest thing to dynamic position sizing that can currently be done with alerts is to use a bot that allows syntax to specify position size as a percentage of equity which, while being dynamic in the sense that it will adapt to current equity when the trade is entered, does not allow us to modulate position size using the stop’s amplitude. Changes to alerts are on the way which should solve this problem.
In order for you to simulate performance with the constraint of fixed position sizing, the Engine also offers a third, less preferable option, where position size is defined as a fixed percentage of initial capital so that it is constant throughout the test and will thus represent a varying proportion of current equity.
Let’s recap. The three position sizing methods the Engine offers are:
1. By specifying the maximum percentage of risk to incur on your remaining equity, so the Engine will dynamically adjust position size for each trade so that, combining the stop’s amplitude with position size will yield a fixed percentage of risk incurred on current equity,
2. By specifying a fixed percentage of remaining equity. Note that unless your system has a fixed stop at entry, this method will not provide maximal risk control, as risk will vary with the amplitude of the stop for every trade. This method, as the first, does however have the advantage of automatically adjusting position size to equity. It is the Engine’s default method because it has an equivalent in TV backtesting, so when flipping between indicator and strategy mode, test results will more or less correspond.
3. By specifying a fixed percentage of the Initial Capital. While this is the least preferable method, it nonetheless reflects the reality confronted by most system designers on PulseWire today. In this case, risk varies both because the fixed position size in initial capital currency represents a varying percentage of remaining equity, and because the trade’s stop amplitude may vary, adding another variability vector to risk.
Note that the Engine cannot display equity results for strategies entering trades for a fixed amount of shares/contracts at a variable price.
SETTINGS/INPUTS
Because the initial text first published with a script cannot be edited later and because there are just too many options, the Engine’s Inputs will not be covered in minute detail, as they will most certainly evolve. We will go over them with broad strokes; you should be able to figure the rest out. If you have questions, just ask them here or in the PineCoders Telegram group.
Display
The display header’s checkbox does nothing.
For the moment, only one exit strategy uses a take profit level, so only that one will show information when checking “Show Take Profit Level”.
Entries
You can activate two simultaneous entry strats, each selected from the same set of strats contained in the Engine. If you select two and they fire simultaneously, the main strat’s signal will be used.
The random strat in each list uses a different seed, so you will get different results from each.
The “Filter transitions” and “Filter states” strats delegate signal generation to the selected filter(s). “Filter transitions” signals will only fire when the filter transitions into bull/bear state, so after a trade is stopped out, the next entry may take some time to trigger if the filter’s state does not change quickly. When you choose “Filter states”, then a new trade will be entered immediately after an exit in the direction the filter allows.
If you select “External Indicator”, your indicator will need to generate a +2/-2 (or a positive/negative stop value) to enter a long/short position, providing the selected filters allow for it. If you wish to use the Engine’s capacity to also derive the entry stop level from your indicator’s signal, then you must explicitly choose this option in the Entry Stops section.
Filters
You can activate as many filters as you wish; they are additive. The “Maximum stop allowed on entry” is an important component of proper risk management. If your system has an average 3% stop size and you need to trade using fixed position sizes because of alert/execution bot limitations, you must use this filter because if your system was to enter a trade with a 15% stop, that trade would incur 5 times the normal risk, and its result would account for an abnormally high proportion in your system’s performance.
Remember that any filter can also be used as an entry signal, either when it changes states, or whenever no trade is active and the filter is in a bull or bear mode.
Entry Stops
An entry stop must be selected in the Engine, as it requires a stop level before the in-trade stop is calculated. Until the selected in-trade stop strat generates a stop that comes closer to price than the entry stop (or respects another one of the in-trade stops kick in strats), the entry stop level is used.
It is here that you must select “External Indicator” if your indicator supplies a +price/-price value to be used as the entry stop. A +price is expected for a long entry and a -price value will enter a short with a stop at price. Note that the price is the absolute price, not an offset to the current price level.
In-Trade Stops
The Engine comes with many built-in in-trade stop strats. Note that some of them share the “Length” and “Multiple” field, so when you swap between them, be sure that the length and multiple in use correspond to what you want for that stop strat. Suggested defaults appear with the name of each strat in the dropdown.
In addition to the strat you wish to use, you must also determine when it kicks in to replace the initial entry’s stop, which is determined using different strats. For strats where you can define a positive or negative multiple of X, percentage or fixed value for a kick-in strat, a positive value is above the trade’s entry fill and a negative one below. A value of zero represents breakeven.
Pyramiding
What you specify in this section are the rules that allow pyramiding to happen. By themselves, these rules will not generate pyramiding entries. For those to happen, entry signals must be issued by one of the active entry strats, and conform to the pyramiding rules which act as a filter for them. The “Filter must allow entry” selection must be chosen if you want the usual system’s filters to act as additional filtering criteria for your pyramided entries.
Hard Exits
You can choose from a variety of hard exit strats. Hard exits are exit strategies which signal trade exits on specific events, as opposed to price breaching a stop level in In-Trade Stops strategies. They are self-explanatory. The last one labelled When Take Profit Level (multiple of X) is reached is the only one that uses a level, but contrary to stops, it is above price and while it is relative because it is expressed as a multiple of X, it does not move during the trade. This is the level called Take Profit that is show when the “Show Take Profit Level” checkbox is checked in the Display section.
While stops focus on managing risk, hard exit strategies try to put the emphasis on capturing opportunity.
Slippage
You can define it as a percentage or a fixed value, with different settings for entries and exits. The entry and exit markers on the chart show the impact of slippage on the entry price (the fill).
Fees
Fees, whether expressed as a percentage of position size in and out of the trade or as a fixed value per in and out, are in the same units of currency as the capital defined in the Position Sizing section. Fees being deducted from your Capital, they do not have an impact on the chart marker positions.
In-Trade Events
These events will only trigger during trades. They can be helpful to act as reminders for traders using the Engine as assistance to discretionary trading.
Post-Exit Analysis
It is normally on. Some of its results will show in the Global Numbers section of the Data Window. Only a few of the statistics generated are shown; many more are available, but commented out in the Plot module.
Date Range Filtering
Note that you don’t have to change the dates to enable/diable filtering. When you are done with a specific date range, just uncheck “Date Range Filtering” to disable date filtering.
Alert Triggers
Each selection corresponds to one condition. Conditions can be combined into a single alert as you please. Just be sure you have selected the ones you want to trigger the alert before you create the alert. For example, if you trade in both directions and you want a single alert to trigger on both types of exits, you must select both “Long Exit” and “Short Exit” before creating your alert.
Once the alert is triggered, these settings no longer have relevance as they have been saved with the alert.
When viewing charts where an alert has just triggered, if your alert triggers on more than one condition, you will need the appropriate markers active on your chart to figure out which condition triggered the alert, since plotting of markers is independent of alert management.
Position sizing
You have 3 options to determine position size:
1. Proportional to Stop -> Variable, with a cap on size.
2. Percentage of equity -> Variable.
3. Percentage of Initial Capital -> Fixed.
External Indicator
This is where you connect your indicator’s plot that will generate the signals the Engine will act upon. Remember this only works in Indicator mode.
DATA WINDOW INFORMATION
The top part of the window contains global numbers while the individual trade information appears in the bottom part. The different types of units used to express values are:
curr: denotes the currency used in the Position Sizing section of Inputs for the Initial Capital value.
quote: denotes quote currency, i.e. the value the instrument is expressed in, or the right side of the market pair (USD in EURUSD ).
X: the stop’s amplitude, itself expressed in quote currency, which we use to express a trade’s P&L, so that a trade with P&L=2X has made twice the stop’s amplitude in profit. This is sometimes referred to as R, since it represents one unit of risk. It is also the unit of measure used in the APPT, which denotes expected reward per unit of risk.
X%: is also the stop’s amplitude, but expressed as a percentage of the Entry Fill.
The numbers appearing in the Data Window are all prefixed:
“ALL:” the number is the average for all first entries and pyramided entries.
”1ST:” the number is for first entries only.
”PYR:” the number is for pyramided entries only.
”PEA:” the number is for Post-Exit Analyses
Global Numbers
Numbers in this section represent the results of all trades up to the cursor on the chart.
Average Profitability Per Trade (X): This value is the most important gauge of your strat’s worthiness. It represents the returns that can be expected from your strat for each unit of risk incurred. E.g.: your APPT is 2.0, thus for every unit of currency you invest in a trade, you can on average expect to obtain 2 after the trade. APPT is also referred to as “statistical expectancy”. If it is negative, your strategy is losing, even if your win rate is very good (it means your winning trades aren’t winning enough, or your losing trades lose too much, or both). Its counterpart in currency is also shown, as is the APPT/bar, which can be a useful gauge in deciding between rivalling systems.
Profit Factor: Gross of winning trades/Gross of losing trades. Strategy is profitable when >1. Not as useful as the APPT because it doesn’t take into account the win rate and the average win/loss per trade. It is calculated from the total winning/losing results of this particular backtest and has less predictive value than the APPT. A good profit factor together with a poor APPT means you just found a chart where your system outperformed. Relying too much on the profit factor is a bit like a poker player who would think going all in with two’s against aces is optimal because he just won a hand that way.
Win Rate: Percentage of winning trades out of all trades. Taken alone, it doesn’t have much to do with strategy profitability. You can have a win rate of 99% but if that one trade in 100 ruins you because of poor risk management, 99% doesn’t look so good anymore. This number speaks more of the system’s profile than its worthiness. Still, it can be useful to gauge if the system fits your personality. It can also be useful to traders intending to sell their systems, as low win rate systems are more difficult to sell and require more handholding of worried customers.
Equity (curr): This the sum of initial capital and the P&L of your system’s trades, including fees and slippage.
Return on Capital is the equivalent of TV’s Net Profit figure, i.e. the variation on your initial capital.
Maximum drawdown is the maximal drawdown from the highest equity point until the drop . There is also a close to close (meaning it doesn’t take into account in-trade variations) maximum drawdown value commented out in the code.
The next values are self-explanatory, until:
PYR: Avg Profitability Per Entry (X): this is the APPT for all pyramided entries.
PEA: Avg Max Opp . Available (X): the average maximal opportunity found in the Post-Exit Analyses.
PEA: Avg Drawdown to Max Opp . (X): this represents the maximum drawdown (incurred from the close at the beginning of the PEA analysis) required to reach the maximal opportunity point.
Trade Information
Numbers in this section concern only the current trade under the cursor. Most of them are self-explanatory. Use the description’s prefix to determine what the values applies to.
PYR: Avg Profitability Per Entry (X): While this value includes the impact of all current pyramided entries (and only those) and updates when you move your cursor around, P&L only reflects fees at the trade’s last bar.
PEA: Max Opp . Available (X): It’s the most profitable close reached post-trade, measured from the trade’s Exit Fill, expressed in the X value of the trade the PEA follows.
PEA: Drawdown to Max Opp . (X): This is the maximum drawdown from the trade’s Exit Fill that needs to be sustained in order to reach the maximum opportunity point, also expressed in X. Note that PEA numbers do not include slippage and fees.
EXTERNAL SIGNAL PROTOCOL
Only one external indicator can be connected to a script; in order to leverage its use to the fullest, the engine provides options to use it as either an entry signal, an entry/exit signal or a filter. When used as an entry signal, you can also use the signal to provide the entry’s stop. Here’s how this works:
For filter state: supply +1 for bull (long entries allowed), -1 for bear (short entries allowed).
For entry signals: supply +2 for long, -2 for short.
For exit signals: supply +3 for exit from long, -3 for exit from short.
To send an entry stop level with an entry signal: Send positive stop level for long entry (e.g. 103.33 to enter a long with a stop at 103.33), negative stop level for short entry (e.g. -103.33 to enter a short with a stop at 103.33). If you use this feature, your indicator will have to check for exact stop levels of 1.0, 2.0 or 3.0 and their negative counterparts, and fudge them with a tick in order to avoid confusion with other signals in the protocol.
Remember that mere generation of the values by your indicator will have no effect until you explicitly allow their use in the appropriate sections of the Engine’s Settings/Inputs.
An example of a script issuing a signal for the Engine is published by PineCoders.
RECOMMENDATIONS TO ASPIRING SYSTEM DESIGNERS
Stick to higher timeframes. On progressively lower timeframes, margins decrease and fees and slippage take a proportionally larger portion of profits, to the point where they can very easily turn a profitable strategy into a losing one. Additionally, your margin for error shrinks as the equilibrium of your system’s profitability becomes more fragile with the tight numbers involved in the shorter time frames. Avoid <1H time frames.
Know and calculate fees and slippage. To avoid market shock, backtest using conservative fees and slippage parameters. Systems rarely show unexpectedly good returns when they are confronted to the markets, so put all chances on your side by being outrageously conservative—or a the very least, realistic. Test results that do not include fees and slippage are worthless. Slippage is there for a reason, and that’s because our interventions in the market change the market. It is easier to find alpha in illiquid markets such as cryptos because not many large players participate in them. If your backtesting results are based on moving large positions and you don’t also add the inevitable slippage that will occur when you enter/exit thin markets, your backtesting will produce unrealistic results. Even if you do include large slippage in your settings, the Engine can only do so much as it will not let slippage push fills past the high or low of the entry bar, but the gap may be much larger in illiquid markets.
Never test and optimize your system on the same dataset , as that is the perfect recipe for overfitting or data dredging, which is trying to find one precise set of rules/parameters that works only on one dataset. These setups are the most fragile and often get destroyed when they meet the real world.
Try to find datasets yielding more than 100 trades. Less than that and results are not as reliable.
Consider all backtesting results with suspicion. If you never entertained sceptic tendencies, now is the time to begin. If your backtest results look really good, assume they are flawed, either because of your methodology, the data you’re using or the software doing the testing. Always assume the worse and learn proper backtesting techniques such as monte carlo simulations and walk forward analysis to avoid the traps and biases that unchecked greed will set for you. If you are not familiar with concepts such as survivor bias, lookahead bias and confirmation bias, learn about them.
Stick to simple bars or candles when designing systems. Other types of bars often do not yield reliable results, whether by design (Heikin Ashi) or because of the way they are implemented on TV (Renko bars).
Know that you don’t know and use that knowledge to learn more about systems and how to properly test them, about your biases, and about yourself.
Manage risk first , then capture opportunity.
Respect the inherent uncertainty of the future. Cleanse yourself of the sad arrogance and unchecked greed common to newcomers to trading. Strive for rationality. Respect the fact that while backtest results may look promising, there is no guarantee they will repeat in the future (there is actually a high probability they won’t!), because the future is fundamentally unknowable. If you develop a system that looks promising, don’t oversell it to others whose greed may lead them to entertain unreasonable expectations.
Have a plan. Understand what king of trading system you are trying to build. Have a clear picture or where entries, exits and other important levels will be in the sort of trade you are trying to create with your system. This stated direction will help you discard more efficiently many of the inevitably useless ideas that will pop up during system design.
Be wary of complexity. Experienced systems engineers understand how rapidly complexity builds when you assemble components together—however simple each one may be. The more complex your system, the more difficult it will be to manage.
Play! . Allow yourself time to play around when you design your systems. While much comes about from working with a purpose, great ideas sometimes come out of just trying things with no set goal, when you are stuck and don’t know how to move ahead. Have fun!
@LucF
NOTES
While the engine’s code can supply multiple consecutive entries of longs or shorts in order to scale positions (pyramid), all exits currently assume the execution bot will exit the totality of the position. No partial exits are currently possible with the Engine.
Because the Engine is literally crippled by the limitations on the number of plots a script can output on TV; it can only show a fraction of all the information it calculates in the Data Window. You will find in the Plot Module vast amounts of commented out lines that you can activate if you also disable an equivalent number of other plots. This may be useful to explore certain characteristics of your system in more detail.
When backtesting using the TV backtesting feature, you will need to provide the strategy parameters you wish to use through either Settings/Properties or by changing the default values in the code’s header. These values are defined in variables and used not only in the strategy() statement, but also as defaults in the Engine’s relevant Inputs.
If you want to test using pyramiding, then both the strategy’s Setting/Properties and the Engine’s Settings/Inputs need to allow pyramiding.
If you find any bugs in the Engine, please let us know.
THANKS
To @glaz for allowing the use of his unpublished MA Squize in the filters.
To @everget for his Chandelier stop code, which is also used as a filter in the Engine.
To @RicardoSantos for his pseudo-random generator, and because it’s from him that I first read in the Pine chat about the idea of using an external indicator as input into another. In the PineCoders group, @theheirophant then mentioned the idea of using it as a buy/sell signal and @simpelyfe showed a piece of code implementing the idea. That’s the tortuous story behind the use of the external indicator in the Engine.
To @admin for the Volatility stop’s original code and for the donchian function lifted from Ichimoku .
To @BobHoward21 for the v3 version of Volatility Stop .
To @scarf and @midtownsk8rguy for the color tuning.
To many other scripters who provided encouragement and suggestions for improvement during the long process of writing and testing this piece of code.
To J. Welles Wilder Jr. for ATR, used extensively throughout the Engine.
To PulseWire for graciously making an account available to PineCoders.
And finally, to all fellow PineCoders for the constant intellectual stimulation; it is a privilege to share ideas with you all. The Engine is for all PulseWire PineCoders, of course—but especially for you.
Look first. Then leap.
Indicator

Signal for Backtesting-Trading Engine [PineCoders]This is a companion script to the PineCoders Backtesting-Trading Engine. It illustrates how to build a signal plot in another script, which can in turn be fed in the Engine to provide entry, exit, filter and stop information.
Connection to the Engine is done through its “External Indicator” input field at the very bottom of the Engine’s Settings/Inputs.
The Engine must be operating in study mode to be able to connect an external indicator to it.
The way this script builds the signal is straightforward, as you will see in the code. Two aspects are worth mentioning:
The “FudgeStop()” function used to fudge the stop value by one tick for the rare cases where it will match one of the protocol reserved values, i.e. 1, 2 or 3.
The priority and exclusivity given to the different types of signals in the signal-building “Signal = …” line. No two signals can be sent simultaneously through the signal plot, except for the entry and stop combination.
You can determine in this script’s Settings/Inputs the type of signals that will go through the signal plot.
This script respects the following protocol:
EXTERNAL SIGNAL PROTOCOL
Only one external indicator can be connected to a script; in order to leverage its use to the fullest, the engine provides options to use it as either an entry signal, an entry/exit signal or a filter. When used as an entry signal, you can also use the signal to provide the entry’s stop. Here’s how this works:
For filter state: supply +1 for bull (long entries allowed), -1 for bear (short entries allowed).
For entry signals: supply +2 for long, -2 for short.
For exit signals: supply +3 for exit from long, -3 for exit from short.
To send an entry stop level with an entry signal: Send positive stop level for long entry (e.g. 103.33 to enter a long with a stop at 103.33), negative stop level for short entry (e.g. -103.33 to enter a short with a stop at 103.33). If you use this feature, your indicator will have to check for exact stop levels of 1.0, 2.0 or 3.0 and their negative counterparts, and fudge them with a tick in order to avoid confusion with other signals in the protocol.
Remember that mere generation of the values by your indicator will have no effect until you explicitly allow their use in the appropriate sections of the Engine’s Settings/Inputs.
Look first. Then leap.
Indicator
