---
title: General FAQ
description: >-
  Frequently asked questions about kScript, covering everything from basic
  syntax to advanced topics.
---

<div class="flex gap-3 mb-6">
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-yellow-50 text-yellow-600 text-sm font-medium">
    FAQ
  </span>
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-gray-100 text-gray-600 text-sm font-medium">
    5 min read
  </span>
</div>

## Getting Started

{% faqgroup %}
{% faqitem question="What is kScript?" %}

kScript is a TypeScript-based domain-specific language designed for financial data analysis and visualization. It allows you to write scripts for technical analysis, trading indicators, and market data processing with a syntax similar to Pine Script but powered by modern web technologies.
{% endfaqitem %}

{% faqitem question="Do I need to know TypeScript to use kScript?" %}

No, you don't need to know TypeScript. kScript has its own simplified syntax. However, familiarity with programming concepts will help you write more complex scripts.
{% endfaqitem %}
{% endfaqgroup %}

## Data Sources and Context

{% faqgroup %}
{% faqitem question="What are currentSymbol and currentExchange?" %}

These are built-in context variables that automatically contain the current trading pair and exchange being analyzed:

```javascript title="Context Variables" lines wrap
timeseries data = ohlcv(currentSymbol, currentExchange)
print("Analyzing:", currentSymbol, "on", currentExchange)
```
{% endfaqitem %}

{% faqitem question="Why do I get NaN when accessing historical data in early bars?" %}

kScript executes per-bar, meaning on each bar, only data up to that point is available. When you access historical data like `data[5]`, the first 4 bars will return NaN because there aren't 5 bars of history yet.

**Solution:** Always check for NaN or ensure enough historical data exists before using it in calculations. You can use the `barIndex` to make sure you're not accessing data too early.

```javascript title="Historical NaN" lines wrap
timeseries trade = ohlcv(currentSymbol, currentExchange)

// Accessing 5 bars back
print(trade[5])

// Output on bars 0-3: NaN (not enough history)
// Output on bar 4 onwards: actual data from 5 bars ago
```
{% endfaqitem %}

{% faqitem question="Can I analyze multiple symbols in one script?" %}

Yes, but you need to explicitly specify each symbol:

```javascript title="Multiple Symbols" lines wrap
timeseries btc_data = ohlcv("BTCUSDT", "BINANCE")
timeseries eth_data = ohlcv("ETHUSDT", "BINANCE")
```
{% endfaqitem %}

{% faqitem question="Can I write a script without source data?" %}

**No**, you cannot run a script without source data. kScript is designed for time-series analysis and requires data to create the timeline for bar-by-bar execution. Even if you declare sources but they return empty data, the script won't run because there are no bars to process.

```javascript title="Script Without Source Data" lines wrap
// ✗ Won't produce any output
define("Empty Script", "onchart", true)
var value = 100
plotLine(value)  // Never executes because there are no bars

// ✓ Correct - with data source
define("Working Script", "onchart", true)
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")
var value = ohlcvData.close
plotLine(value)  // Executes for each bar
```
{% endfaqitem %}

{% faqitem question="Can I subscribe to sources inside control structures (if/while/for)?" %}

**No**, you cannot call source functions inside control structures. Source subscriptions must be declared at the root level of your script in `timeseries` declarations.

**Why:** Sources need to be fetched and prepared before the script can execute. The runtime extracts source calls during the initialization phase, before the bar-by-bar loop begins. Dynamic source subscription during control flow would require async operations that aren't supported.

```javascript title="Source Calls in Control Structures" lines wrap
// ✓ Correct - at root level
timeseries ohlcv = source("ohlcv", "BTCUSDT", "BINANCE")

// ✗ Wrong - inside control structure
if (someCondition) {
  timeseries ohlcv = source("ohlcv", "BTCUSDT", "BINANCE")  // Won't work
}
```
{% endfaqitem %}

{% faqitem question="How do I access orderbook heatmap raw data?" %}

Orderbook data is accessed through specialized built-in functions that operate on orderbook timeseries sources. The data structure is `[timestamp, price1, amount1, price2, amount2, ...]` where positive amounts are bids and negative amounts are asks.

**Available functions:**

- `sumBids(source, depthPct=10)` - Sum of all bid amounts within depth percentage
- `sumAsks(source, depthPct=10)` - Sum of all ask amounts within depth percentage
- `maxBidAmount(source, depthPct=10)` - Maximum bid amount within depth
- `maxAskAmount(source, depthPct=10)` - Maximum ask amount within depth
- `minBidAmount(source, depthPct=10)` - Minimum bid amount within depth
- `minAskAmount(source, depthPct=10)` - Minimum ask amount within depth

```javascript title="Orderbook Access" lines wrap
timeseries orderbookData = source("orderbook", "BTCUSDT", "BINANCE")

var totalBids = sumBids(orderbookData, depthPct=5)
var totalAsks = sumAsks(orderbookData, depthPct=5)
var bidAskRatio = totalBids / totalAsks

plotLine(value=bidAskRatio, width=2, colors=["blue"], label=["Bid/Ask Ratio"], desc=["Bid Ask Ratio"])
```
{% endfaqitem %}

{% faqitem question="How does kScript handle data gaps and interpolation?" %}

kScript fills data gaps with `NaN` values. The system creates a continuous timestamp array based on the interval, and when fetched data doesn't match the timeline length, gaps are pre-filled with `NaN`.

**Important:** For line plots, kScript will interpolate to connect points across gaps. For other use cases, if you need interpolation (forward fill, linear interpolation, etc.), you must implement it manually using custom logic.

```javascript title="Data Gaps and Interpolation" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

 static lastValue = 0

var currentValue = ohlcvData.close
if (isnan(currentValue)) {
  currentValue = lastValue  // Forward fill
} else {
  lastValue = currentValue
}

plotLine(value=currentValue, width=2, colors=["blue"], label=["Current Value"], desc=["Current Value"])
```
{% endfaqitem %}
{% endfaqgroup %}

## Technical Indicators

{% faqgroup %}
{% faqitem question="Why am I getting NaN values in my calculations?" %}

NaN (Not a Number) usually occurs when:

- There's insufficient historical data for the calculation
- You're dividing by zero
- The data source has gaps

**Solution:** Check for NaN values:

```javascript title="NaN Handling" lines wrap
var safe_value = !isnan(sma_value) ? sma_value : 0
```
{% endfaqitem %}
{% endfaqgroup %}

## Plotting and Visualization

{% faqgroup %}
{% faqitem question="How do I plot multiple indicators on the same chart?" %}

```javascript title="Multiple Plots" lines wrap
plotLine(value=sma20, width=1, colors=["blue"], label=["SMA 20"], desc=["20-period Simple Moving Average"])
plotLine(value=sma50, width=2, colors=["red"], label=["SMA 50"], desc=["50-period Simple Moving Average"])
```
{% endfaqitem %}

{% faqitem question="Can I plot conditional signals?" %}

Yes, use ternary operators or conditional values:

```javascript title="Conditional Plot" lines wrap
var buy_signal = crossover(sma_fast, sma_slow)
plotShape(value=buy_signal ? data.low : na, shape="circle", width=2, colors=["green"], label=["Buy Signal"], desc=["Buy Signal Marker"])
```
{% endfaqitem %}

{% faqitem question="How do I change plot colors dynamically?" %}

Use the `colorIndex` parameter:

```javascript title="Dynamic Colors" lines wrap
var trend = sma_fast > sma_slow ? 1 : 0
plotLine(value=data.close, width=2, colors=["red", "green"], colorIndex=trend, label=["Price"], desc=["Price with Dynamic Colors"])
```
{% endfaqitem %}

{% faqitem question="Can I call plot functions inside conditionals (if-else) or loops?" %}

**Conditionals (if-else): Yes** - You can call plot functions inside if-else statements. The plot will execute conditionally based on the condition at each bar.

**Loops: Not allowed** - Plotting inside loops would create multiple plot outputs per bar, which is not the intended behavior and may cause unexpected results.

```javascript title="Plot Calls in Conditionals and Loops" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// ✓ Allowed in conditionals
if (ohlcv.close > ohlcv.open) {
  plotLine(value=ohlcvData.close, width=2, colors=["green"], label=["Bullish"], desc=["Bullish Price"])
} else {
  plotLine(value=ohlcvData.close, width=2, colors=["red"], label=["Bearish"], desc=["Bearish Price"])
}

// ✗ Not recommended in loops
for (var i = 0; i < 10; i++) {
  plotLine(value=i, width=1, colors=["blue"], label=["Loop"], desc=["Loop Value"])  // Creates multiple plots per bar
}
```
{% endfaqitem %}

{% faqitem question='Difference between plotLine() and plot(plotType="line")?' %}

There is **NO functional difference**. `plot()` with `plotType="line"` is simply an alias that internally calls `plotLine()`. The `plot()` function is a generic interface that can create different plot types by changing the `plotType` parameter.

**Available plot types via `plot()`:**

- `plotType="line"` or `"spline"` -> calls `plotLine()`
- `plotType="bar"` -> calls `plotBar()`
- `plotType="candle"` -> calls `plotCandle()`
- `plotType="point"` -> calls `plotShape()`

```javascript title="plotLine() vs plot()" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// These three are identical
plotLine(value=ohlcvData.close, width=2, colors=["blue"], label=["Price"], desc=["Close Price"])
plot(value=ohlcvData.close, plotType="line", width=2, colors=["blue"], label=["Price"], desc=["Close Price"])
plot(value=ohlcvData.close, plotType="spline", width=2, colors=["blue"], label=["Price"], desc=["Close Price"])

// plot() can also create other types
plot(value=ohlcvData.close, plotType="bar", width=1, colors=["green"], label=["Volume"], desc=["Volume Bars"])
plot(value=[ohlcvData.open, ohlcvData.high, ohlcvData.low, ohlcvData.close], plotType="candle", width=1, colors=["red", "green"], label=["OHLC"], desc=["OHLC Candlestick"])
```
{% endfaqitem %}

{% faqitem question="How does the positioning system work for shape and text plots?" %}

Shape and text plots use a coordinate-based positioning system with price (y-axis) and time (x-axis):

- **X-axis (Time):** Automatically set to the current bar timestamp. For `plotRange()`, you can specify custom timestamps for `time1` and `time2`.
- **Y-axis (Price):** Explicitly provided as the `price` or `value` parameter.
- **Text alignment:** `xAlign` and `yAlign` parameters affect rendering relative to the anchor point.

```javascript title="Shape and Text Positioning" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// Plot shape at high price
if (ohlcvData.close > ohlcvData.open) {
  plotShape(value=ohlcvData.high, shape="circle", width=3, colors=["green"], label=["Bullish"], desc=["Bullish Signal"])
}

// Plot text at specific price level
plotText("Signal", "yellow", ohlcvData.close, size=12, fill=true, backgroundColor="black")

// Plot range between two points
var prevTime = time() - (60 * 60 * 1000)  // 1 hour ago
plotRange(prevTime, ohlcvData.low, time(), ohlcvData.high, color="blue", fillColor="rgba(0,0,255,0.2)")
```
{% endfaqitem %}
{% endfaqgroup %}

## Common Issues and Troubleshooting

{% faqgroup %}
{% faqitem question="My script isn't displaying anything. What's wrong?" %}

Check:

- You have a proper `define()` statement
- You're plotting something with `plotLine()`, `plotBar()`, etc.
- Your data source is valid. Empty data sources can lead to empty charts.
- Check the Problem pop up for error messages

<img src="/images/kScript/error_output.png" alt="kScript error output" style="margin-top: 1rem; border-radius: 8px; max-width: 100%" />
{% endfaqitem %}

{% faqitem question="Undefined identifier errors" %}

Make sure:

- Variables are declared before use
- Variable names are spelled correctly
- You're using proper scope (variables declared in functions are local)
{% endfaqitem %}

{% faqitem question="How do I debug my kScript code?" %}

Use `print()` and `printTimeSeries()` statements to output values:

```javascript title="Debugging" lines wrap
print("Current price:", data.close)
print("SMA value:", sma_value)
printTimeSeries(data, priceIndex=4)  // Print close prices
```
{% endfaqitem %}

{% faqitem question="Why is my indicator not updating in real-time?" %}

Ensure you're:

- Using timeseries data correctly
- Not using static calculations where dynamic ones are needed
- Plotting the results properly
{% endfaqitem %}

{% faqitem question="Can I use null instead of na for empty data?" %}

**No**, using `null` will cause plot values to become `0` because the runtime's `Number(null)` returns `0`, not `NaN`. This means your "empty" data points will plot as zero values instead of gaps.

**Solution:** Use `NaN` to represent missing data. The runtime properly handles `NaN` as missing data, and plot functions will show gaps where `NaN` values occur.

```javascript title="Null vs NaN" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// ✗ Wrong - null becomes 0
var value1 = isnan(ohlcvData.close) ? null : ohlcvData.close
plotLine(value1)  // Will plot 0 for missing data

// ✓ Correct - use NaN
var value2 = isnan(ohlcvData.close) ? NaN : ohlcvData.close
plotLine(value2)  // Will show gap for missing data
```
{% endfaqitem %}
{% endfaqgroup %}

## Language Features and Syntax

{% faqgroup %}
{% faqitem question="Does kScript support switch statements?" %}

**No**, kScript v2 does NOT support switch statements. Only `if-else` conditionals and loops (`for`, `while`) are supported control structures.

**Workaround:** Use nested if-else chains to achieve similar functionality.

```javascript title="Switch Statement Workaround" lines wrap
// ✗ Switch statements not supported
// switch (signal) {
//   case "buy": ...
//   case "sell": ...
// }

// ✓ Use if-else chains instead
if (signal == "buy") {
  plotShape(value=data.low, shape="circle", width=2, colors=["green"], label=["Buy"], desc=["Buy Signal"])
} else if (signal == "sell") {
  plotShape(value=data.high, shape="circle", width=2, colors=["red"], label=["Sell"], desc=["Sell Signal"])
} else if (signal == "hold") {
  // Do nothing
} else {
  // Default action
}
```
{% endfaqitem %}

{% faqitem question="Are objects and arrays supported in kScript?" %}

**Arrays: Partial support** - Arrays are supported with type restrictions. Arrays must contain elements of the same type (homogeneous arrays).

**Supported array types:**

- `number[]` - Array of numbers
- `string[]` - Array of strings
- `any[]` - Generic arrays (for mixed timeseries/number)

**Objects: Very limited** - Objects are treated as type `any`. Main use cases are `input()` constraints like `{min: 0, max: 100}` and accessing timeseries fields via member access like `ohlcv.close`. You cannot create custom objects with arbitrary properties.

```javascript title="Arrays and Objects" lines wrap
// ✓ Homogeneous arrays
var colors = ["red", "green", "blue"]
var prices = [100, 200, 300]

// ✓ Array of timeseries values
var ohlc = [ohlcv.open, ohlcv.high, ohlcv.low, ohlcv.close]
plotCandle(value=ohlc, width=1, colors=["green", "red"], label=["OHLC"], desc=["OHLC Candlestick"])

// ✗ Mixed type arrays not allowed
var mixed = [100, "hello", true]  // Error

// ✓ Object for constraints (limited support)
var userLength = input("Length", "number", defaultValue=14, constraints={min:1, max:100})
```
{% endfaqitem %}

{% faqitem question="Can a script get signals from another script or indicator?" %}

**No**, kScript v2 does NOT currently support cross-script communication. Each script runs in isolation and cannot access data or signals from other scripts. Each script has its own runtime context, data manager, variable environment, and series storage.

**Note:** Cross-script communication will be added as a feature soon.

**Workaround:** Use shared data sources. Both scripts can subscribe to the same source data and process it independently. Alternatively, combine the logic of multiple indicators into a single script.

```javascript title="Cross-Script Signals" lines wrap
// ✗ Cannot access signals from other scripts
// var otherRSI = getScriptValue("RSI Indicator", "rsi")  // Not supported

// ✓ Workaround: Combine logic in a single script
define("Combined Indicator + Strategy", "onchart", true)
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// Calculate indicator
var rsiData = rsi(ohlcvData.close, period=14)

// Use indicator for strategy
if (rsiData > 70) {
  plotShape(value=ohlcvData.high, shape="circle", width=5, colors=["red"], label=["Overbought"], desc=["Overbought Signal"])
} else if (rsiData < 30) {
  plotShape(value=ohlcvData.low, shape="circle", width=5, colors=["green"], label=["Oversold"], desc=["Oversold Signal"])
}

plotLine(value=rsiData, width=2, colors=["purple"], label=["RSI"], desc=["Relative Strength Index"])
```
{% endfaqitem %}

{% faqitem question="Can I use timeseries in custom functions and control structures?" %}

**Yes and No**, with important constraints:

**Custom Functions:**

- Timeseries CAN be passed as parameters to custom functions
- Inside functions, timeseries are automatically indexed at the current bar to get numeric values. However, the behavior will not be intended, as the timeseries will be treated as a single value. For example, OHLCV timeseries data will be treated as a singular open data value.

**Control Structures:**

- Timeseries cannot be declared inside control structures (if/for/while)

```javascript title="Timeseries in Custom Functions" lines wrap
timeseries ohlcvData = source("ohlcv", "BTCUSDT", "BINANCE")

// Custom function with timeseries parameter
func calculateRange(data) {
  var high = data.high
  var low = data.low
  return high - low
}

// Use in control structure
if (ohlcvData.close > ohlcvData.open) {
  var range = calculateRange(ohlcvData)
  plotLine(value=range, width=2, colors=["green"], label=["Range"], desc=["Price Range"])
} else {
  plotLine(value=0, width=2, colors=["red"], label=["Zero"], desc=["Zero Line"])
}
```
{% endfaqitem %}

{% faqitem question="Does kScript support alerts?" %}

**No**, kScript does not currently support alerts. Alert functionality is yet to be implemented for kScripts.
{% endfaqitem %}

{% faqitem question="Can trades be executed from kScript?" %}

**No**, kScript does not support trade execution. kScript is designed for analysis and visualization purposes only. You cannot place orders, execute trades, or interact with exchange APIs for trading directly from kScript.
{% endfaqitem %}
{% endfaqgroup %}

## Performance and Optimization

{% faqgroup %}
{% faqitem question="My script is running slowly. How can I optimize it?" %}

- Use `static` for constants
- Avoid redundant calculations
- Use built-in functions instead of custom implementations
- Limit historical data lookback when possible

```javascript title="Optimization" lines wrap
// Good: Calculate once
static fibonacci_level = 0.618

// Avoid: Recalculating every bar
var fibonacci_level = 618 / 1000
```
{% endfaqitem %}
{% endfaqgroup %}

## Common Error Messages

{% faqgroup %}
{% faqitem question='What does "source must be a timeseries" mean?' %}

You're passing a regular variable to a function that expects timeseries data:

```javascript title="Source Timeseries Error" lines wrap
var number = 42
var sma_val = sma(number, 14)  // Wrong: number is not timeseries

timeseries prices = ohlcv(currentSymbol, currentExchange)
var sma_val = sma(prices.close, 14)  // Correct
```
{% endfaqitem %}
{% endfaqgroup %}

## Still Have Questions?

Can't find what you're looking for? We're here to help!

Join the discussion in [**#kscript-floor**](https://discord.gg/hjQRzQtbNu) or check out the [kScript Reference](/kscript/reference/quick-reference) for more details.
