Multi-Timeframe (MTF)
Multi-Timeframe Analysis
The request.security() function allows you to request data from higher timeframes without lookahead bias.
request.security(symbol, timeframe, exprFn)
- symbol: The trading pair symbol (e.g., "BTC-USD"). Note: Currently only the active chart symbol is supported.
- timeframe: A string like "5", "15", "1H", "4H", "1D", "1W".
- exprFn: A callback function returning the indicator or value you want evaluated on the higher timeframe.
Example: 1-Hour SMA on a 5-Minute Chart
// This evaluates an SMA 20 on 1-hour candles, and aligns it to your current chart
const htfSma = request.security(sym, '1H', () => ta.sma(close, 20));
plot(htfSma, { title: '1H SMA', color: '#ffeb3b', width: 2 });
Coordinate Mapping
Drawing on a canvas requires pixel coordinates. The system provides two primary helper conversion methods on the ctx context:
ctx.barToX(i): Converts a bar indexi(from0tobars.length - 1) to its respective X pixel coordinate on the canvas.ctx.priceToY(p): Converts a numeric price valuep(e.g.1.2345) to its respective Y pixel coordinate on the canvas.
State Preservation
Because scripts execute repeatedly on every UI draw call, understanding scope is critical:
- Persistent State (var): Declaring variables in the global block scope (which translates to outer declarations in the transpiler) preserves their values across render cycles. Use these to store rolling totals, win/loss stats, or active drawing references.
- Loop State: Variables defined inside the main bar execution loop are re-initialized on each bar iteration and do not persist across bars or render cycles.
Exposing Technical Indicators & Volume
Your custom indicator scripts have access to standard technical indicator values in two distinct ways:
- Built-in Math Helpers: Call standard math functions directly from
ctx(such asctx.sma(closes, 20),ctx.rsi(closes, 14), orctx.macd(closes)) to calculate indicators dynamically. - Active Indicators Array: Inspect
ctx.indicatorsto read pre-calculated arrays for active indicators running on the chart. Every indicator object contains a populated.valuesproperty. - Accessing Volume: Retrieve raw bar volume using
ctx.bars[i].volume, or get the entire history array viactx.vol(ctx.bars).
Rendering Optimization & 60 FPS Guidelines
To ensure high-performance scripting (60 FPS rendering without lag or stutter):
- Clamp rendering loops: Restrict canvas rendering iterations from
Math.max(0, Math.floor(bounds.startIndex) - 1)toMath.ceil(bounds.endIndex) + 1. This padding ensures indicators pan smoothly without abruptly disappearing. Avoid looping through the entire historical dataset. - Function Hoisting (CRITICAL): Never declare helper functions inside loops or main rendering callbacks. Hoist all user-defined functions to the global scope to prevent heavy memory allocation.
- Local Scoping: Scope loop-local variables with block-level
letorconstto prevent global namespace lookups and scope leaks. - Map Callback Dereferencing: Avoid allocating new array references or parsing objects inside map callbacks. Dereference precalculated indicator arrays directly using index keys.
- Execution Limits: Scripts taking longer than 12ms to execute will trigger a performance warning in the console.
Mouse Interactions
You can query the real-time mouse position and action states using the ctx.mouse object. This allows you to build interactive hover overlays, highlight target coordinates, or reveal tooltip stats under the cursor.