AlgoHive
Reference

Code Blocks

Write custom logic in JavaScript code blocks.

Code blocks let you write custom JavaScript logic when expressions aren't enough.

When to Use Code Blocks

Use code blocks for:

  • Complex calculations that don't fit expression syntax
  • Looping over arrays with custom logic
  • External API calls (with permissions)
  • Multi-step algorithms
  • Custom indicators not in the library

Prefer expressions when possible — they're faster and easier to debug.

Creating a Code Block

  1. Click Add Analysis in the workflow editor
  2. Select Code Block
  3. Write your JavaScript code
  4. Define outputs

Code Format

Code blocks use arrow function syntax with destructured context parameters:

({ data, analysis, utils, barCount, timestamps }) => {
  // Your analysis logic here
  return { output1: [...], output2: [...] };
}

Return a flat object with named outputs. The type is automatically inferred:

  • Arrays of numbers become values
  • Arrays of booleans become signals

Context Parameters

ParameterTypeDescription
dataMap<string, DataSeries>Access OHLCV market data via data.get('alias')
analysisObjectResults from prior analysis blocks (value blocks, computed values)
utilsObjectHelper functions and indicators via utils.indicators
barCountnumberTotal number of bars in dataset
timestampsnumber[]Array of timestamps for all bars (ms since epoch)
secretsRecord<string, string>API keys (when secrets configured)

Data Access

Access market data using the alias defined in your strategy:

({ data, utils }) => {
  // Get market data by alias
  const btc = data.get('btc');
  if (!btc) return {};
  
  // Destructure OHLCV arrays from .values
  const { close, high, low, volume } = btc.values;
  
  // Now use the arrays with indicators
  const { RSI, SMA } = utils.indicators;
  const rsi = RSI(close, 14);
  const sma = SMA(close, 20);
  const oversold = rsi.map(r => r < 30);
  
  return { rsi, sma, oversold };
}

Return Format

Return a flat object with named outputs:

return {
  rsi: rsi,              // Array of numbers → becomes a "value"
  sma_diff: diff,        // Array of numbers → becomes a "value"
  buy: crossAbove,       // Array of booleans → becomes a "signal"
  oversold: isOversold   // Array of booleans → becomes a "signal"
};

The type is automatically inferred from the data — arrays of booleans become signals, arrays of numbers become values.

Examples

Custom RSI with Smoothing

({ data, analysis, utils }) => {
  const btc = data.get('btc');
  if (!btc) return {};
  
  const { close } = btc.values;
  
  // Get values from prior analysis blocks (e.g., value blocks)
  const period = analysis.rsi_period ?? 14;
  
  // Calculate indicators
  const { RSI, SMA } = utils.indicators;
  const rsi = RSI(close, period);
  const smoothRsi = SMA(rsi, 3);
  const oversold = rsi.map(r => r < 30);
  
  return { rsi, smoothRsi, oversold };
}

Volume Spike Detection

({ data, utils }) => {
  const btc = data.get('btc');
  if (!btc) return {};
  
  const { volume } = btc.values;
  const { SMA } = utils.indicators;
  
  const avgVolume = SMA(volume, 20);
  
  const spike = volume.map((v, i) => {
    if (i < 20) return false;
    return v > avgVolume[i] * 2;
  });
  
  const ratio = volume.map((v, i) => {
    if (i < 20 || avgVolume[i] === 0) return 0;
    return v / avgVolume[i];
  });
  
  return { ratio, spike };
}

Combining Multiple Analysis Blocks

({ data, analysis, utils }) => {
  // Reference outputs from other analysis blocks
  const trend = analysis.trendSignals.bullish;  // boolean[]
  const rsiValue = analysis.indicators.rsi;     // number[]
  
  // Combine signals
  const entry = trend.map((t, i) => t && rsiValue[i] < 40);
  
  return { entry };
}

Available Indicators

Code blocks include 40 built-in indicators via utils.indicators. For the full 100+ indicators, use expression-based analysis blocks instead.

You can destructure the indicators you need:

const { RSI, SMA, MACD, BOLLINGER } = utils.indicators;

Trend Indicators (6)

FunctionDescription
SMA(source, period)Simple Moving Average
EMA(source, period)Exponential Moving Average
WMA(source, period)Weighted Moving Average
DEMA(source, period)Double EMA
TEMA(source, period)Triple EMA
HMA(source, period)Hull Moving Average

Momentum Indicators (9)

FunctionDescription
RSI(source, period)Relative Strength Index
MACD(source, fast, slow, signal)Returns { line, signal, histogram }
STOCH(high, low, close, k, kSmooth, dSmooth)Returns { k, d }
CCI(high, low, close, period)Commodity Channel Index
WILLR(high, low, close, period)Williams %R
ADX(high, low, close, period)Average Directional Index
ROC(source, period)Rate of Change
MOM(source, period)Momentum
AROON(high, low, period)Returns { aroonup, aroondown }

Volatility Indicators (4)

FunctionDescription
ATR(high, low, close, period)Average True Range
BOLLINGER(source, period, stddev)Returns { upper, middle, lower }
KELTNER(high, low, close, period, mult)Returns { upper, middle, lower }
DONCHIAN(high, low, period)Returns { upper, middle, lower }

Math & Stats (10)

FunctionDescription
STDEV(source, period)Standard Deviation
HIGHEST(source, period)Highest value in period
LOWEST(source, period)Lowest value in period
SUM(source, period)Sum over period
MAX(a, b)Element-wise maximum
MIN(a, b)Element-wise minimum
CHANGE(source, period)Value change from n bars ago
PCT_CHANGE(source, period)Percent change from n bars ago
CROSS_ABOVE(a, b)True when a crosses above b
CROSS_BELOW(a, b)True when a crosses below b

Network Access (Auto-Detected)

Just use fetch() in your code — domains are automatically detected!

async ({ data, secrets }) => {
  // Domain (api.example.com) is auto-detected from the URL
  const response = await fetch('https://api.example.com/data');
  const externalData = await response.json();
  
  // ...process data...
  
  return { values: { metric: externalData.values }, signals: {} };
}
⚠️Warning

Network-enabled code blocks cannot be backtested.

Secrets (Auto-Detected)

Just use secrets.KEY_NAME in your code — keys are automatically detected!

async ({ data, secrets }) => {
  // Secret key (API_KEY) is auto-detected from usage
  const apiKey = secrets.API_KEY;
  
  const response = await fetch('https://api.example.com/data', {
    headers: { 'Authorization': `Bearer ${apiKey}` }
  });
  
  // ...
}

Configure actual secret values in Settings → Credentials.

Best Practices

  1. Keep it simple — Complex code is hard to debug
  2. Handle edge cases — Check for empty arrays and division by zero
  3. Return consistent arrays — All outputs must have the same length
  4. Use built-in indicators — They're optimized and tested
  5. Document your logic — Add comments explaining the algorithm
  6. Test thoroughly — Backtest extensively before live trading

Limitations

  • Memory limit — 128MB (Paper), 256MB (Trader), 1GB (Pro)
  • Execution time — Code must complete within timeout
  • No persistent state — Each bar evaluation is independent
  • Network access — Auto-detected and displayed for transparency (shown on marketplace listings)

Debugging

  1. Use the backtest console to see errors
  2. Return intermediate values as outputs to inspect them
  3. Start with simple logic and add complexity gradually
  4. Test with small date ranges first

On this page