Documentation
Welcome to the Frans' Bot developer manual. This system allows you to build, backtest, and deploy automated trading strategies using JavaScript. It is designed to be powerful yet safe.
JavaScript Environment
Scripts are written in standard ES6 JavaScript but have limited access to the browser window or external network requests. You must use the provided API functions to interact with market data.
Case Sensitivity
Most functions are available in both lowercase and capitalized forms (e.g., crossover and Crossover both work). Use whichever style you prefer.
The Workflow
To successfully deploy a trading bot, follow this standard lifecycle:
- Write Code: Implement your logic in the provided editor.
- Get Chart: Load historical data for your desired symbol and timeframe.
- Run Backtest: Validate your strategy against historical data.
- Configure Settings: Adjust TP, SL, and custom parameters in the settings panel.
- Deploy: Deploy your strategy to send signals to the live bot.
Script Structure
Every strategy MUST be contained within a single main function named indicator. This function is called for every candle in the dataset.
function indicator(data, params) {
// 1. Extract Data
const { close } = data;
// 2. Compute Indicators
const rsi = RSI(close, 14);
// 3. Logic & Signals
if (rsi[rsi.length - 1] < 30) {
signal('BUY_SIGNAL');
}
}
Data Access
The data object passed to your main function contains arrays of historical price data. Index 0 is the oldest candle, and length - 1 is the most recent (current) candle.
| Property | Type | Description |
|---|---|---|
data.close |
Array<number> | Closing prices |
data.open |
Array<number> | Opening prices |
data.high |
Array<number> | Daily/Session Highs |
data.low |
Array<number> | Daily/Session Lows |
data.volume |
Array<number> | Trading volume |
data.timestamp |
Array<number> | Unix timestamp (milliseconds) |
Warm-up Period
Most indicators require a certain number of candles before they can produce valid values. During this "warm-up" period, they return null. Always check for null values before using indicator output in your logic.
Important
Failing to check for null can cause unexpected behavior. All indicators return null during their warm-up period.
function indicator(data, params) {
const { close } = data;
// Calculate Bollinger Bands (needs 20 candles by default)
const bb = BB(close, 20, 2);
// Get the most recent values
const currentLower = bb.lower[bb.lower.length - 1];
const currentUpper = bb.upper[bb.upper.length - 1];
// ALWAYS check for null before using!
if (currentLower === null || currentUpper === null) {
return; // Not enough data yet, skip this candle
}
// Now safe to use the values
if (close[close.length - 1] <= currentLower) {
signal('BUY');
}
}
Indicator Library
The system includes a comprehensive suite of built-in technical indicators. All indicators return arrays aligned with the input data (index 0 = oldest, last index = most recent).
Moving Averages
| Function | Format | Returns |
|---|---|---|
SMA |
SMA(data, period) | (number|null)[] - Simple Moving Average |
EMA |
EMA(data, period) | (number|null)[] - Exponential Moving Average |
WMA |
WMA(data, period) | (number|null)[] - Weighted Moving Average |
VWMA |
VWMA(close, volume, period) | (number|null)[] - Volume Weighted Moving Average |
HMA |
HMA(data, period) | (number|null)[] - Hull Moving Average (WMA-based) |
HMA_VWMA |
HMA_VWMA(close, volume, period) | (number|null)[] - Hull MA (VWMA-based, TradingView compatible) |
RMA |
RMA(data, period) | (number|null)[] - Wilder's Smoothing (Running MA) |
DEMA |
DEMA(data, period) | (number|null)[] - Double EMA |
TEMA |
TEMA(data, period) | (number|null)[] - Triple EMA |
Oscillators & Momentum
| Function | Format (defaults shown) | Returns |
|---|---|---|
RSI |
RSI(data, period=14) | (number|null)[] - Relative Strength Index (0-100). Returns null during warm-up. |
Stochastic |
Stochastic(high, low, close, kPeriod=14, dPeriod=3) | {k: (number|null)[], d: (number|null)[]} - Stochastic Oscillator. Also available as STOCH. |
MACD |
MACD(data, fast=12, slow=26, signal=9) | {macd: (number|null)[], signal: (number|null)[], histogram: (number|null)[]} |
MFI |
MFI(high, low, close, volume, period=14) | (number|null)[] - Money Flow Index (0-100) |
CCI |
CCI(high, low, close, period=20) | (number|null)[] - Commodity Channel Index |
WILLR |
WILLR(high, low, close, period=14) | (number|null)[] - Williams %R (-100 to 0) |
roc |
roc(data, period) | (number|null)[] - Rate of Change (%) |
mom |
mom(data, period) | (number|null)[] - Momentum |
Trend Indicators
| Function | Format (defaults shown) | Returns |
|---|---|---|
ADX |
ADX(high, low, close, period=14) | {adx: (number|null)[], plusDI: (number|null)[], minusDI: (number|null)[]} |
SuperTrend |
SuperTrend(high, low, close, period=10, multiplier=3) | {trend: (number|null)[], direction: (number|null)[]} (direction: 1=up, -1=down) |
SAR |
SAR(high, low, close, start=0.02, increment=0.02, max=0.2) | (number|null)[] - Parabolic SAR |
Volatility & Volume
| Function | Format (defaults shown) | Returns |
|---|---|---|
ATR |
ATR(high, low, close, period=14) | (number|null)[] - Average True Range |
tr |
tr(high, low, close) | number[] - True Range (single bar, no warm-up needed) |
BB |
BB(data, period=20, stdDev=2) | {upper: (number|null)[], middle: (number|null)[], lower: (number|null)[]} |
StdDev |
StdDev(data, period) | (number|null)[] - Standard Deviation. Also available as stddev. |
OBV |
OBV(close, volume) | number[] - On-Balance Volume (no warm-up needed) |
VWAP |
VWAP(high, low, close, volume) | number[] - Volume Weighted Average Price (no warm-up needed) |
Pivot Detection
| Function | Format | Returns |
|---|---|---|
pivothigh |
pivothigh(data, leftBars, rightBars) | (number|null)[] - Pivot value at confirmation bar, null elsewhere. Also available as PivotHigh. |
pivotlow |
pivotlow(data, leftBars, rightBars) | (number|null)[] - Pivot value at confirmation bar, null elsewhere. Also available as PivotLow. |
Utility Functions
| Function | Format (defaults shown) | Returns |
|---|---|---|
crossover |
crossover(seriesA, seriesB) | boolean - True if A crossed ABOVE B on the last candle. Also available as Crossover. |
crossunder |
crossunder(seriesA, seriesB) | boolean - True if A crossed BELOW B on the last candle. Also available as Crossunder. |
highest |
highest(data, period) | number[] - Highest value in last N periods. Also available as Highest. |
lowest |
lowest(data, period) | number[] - Lowest value in last N periods. Also available as Lowest. |
change |
change(data, length=1) | (number|null)[] - Price change over N bars. Also available as Change. |
rising |
rising(data, length) | boolean - True if price rose for N consecutive bars. Also available as Rising. |
falling |
falling(data, length) | boolean - True if price fell for N consecutive bars. Also available as Falling. |
barssince |
barssince(condition[]) | number - Bars since condition was last true (or array length if never true). Also available as Barssince. |
valuewhen |
valuewhen(condition[], source[], occurrence=0) | number|null - Value from source when condition was true (0 = most recent). Also available as ValueWhen. |
Signals & Deploying
To make a trade, your script must emit a signal using the signal() function.
The signal() Function
| Function | Format | Description |
|---|---|---|
signal |
signal(name) | Emits a named signal for the current candle. Returns nothing. |
signal('MY_SIGNAL_NAME');
You can name signals whatever you want (e.g., LONG, SHORT, PANIC_SELL). When you Deploy your strategy, you will map each signal name to a specific bot action (e.g., Open Long, Close Position).
Multiple Signals
You can call signal() multiple times per candle with different names. Each unique signal name will appear in the deployment configuration, allowing you to map them to different actions.
Important for Deployment
Always SAVE your script before deploying. The deployment system links to the saved version of your script database. Unsaved changes in the editor will NOT be active in the live bot.
Plotting Indicators
The plot() function lets you visualize indicator values in a sub-chart below the main candlestick chart during backtesting. This is useful for debugging your strategy and understanding how your indicators behave over time.
The plot() Function
| Parameter | Type | Description |
|---|---|---|
seriesName |
string | Label for the series (e.g., "RSI", "MACD") |
value |
number | The value to plot for the current candle |
options |
object (optional) | Styling options for the series (see below) |
Options
| Property | Type | Default | Description |
|---|---|---|---|
color |
string | "#c77dff" |
CSS color for the series line or histogram |
type |
"line" | "histogram" |
"line" |
Render as a line chart or histogram bars |
lineWidth |
number | 2 |
Width of the line (only applies to line type) |
function indicator(data, params) {
const { close, high, low } = data;
// Calculate indicators
const rsi = RSI(close, params.rsiPeriod || 14);
const macdResult = MACD(close, 12, 26, 9);
const currentRsi = rsi[rsi.length - 1];
const currentMacd = macdResult.histogram[macdResult.histogram.length - 1];
if (currentRsi === null || currentMacd === null) return;
// Plot RSI as a line with reference levels
plot('RSI', currentRsi, { color: '#c77dff' });
plot('Overbought', 70, { color: '#ff6b6b', lineWidth: 1 });
plot('Oversold', 30, { color: '#51cf66', lineWidth: 1 });
// Plot MACD histogram as bars
plot('MACD Hist', currentMacd, { color: '#74b9ff', type: 'histogram' });
// Trading logic
if (currentRsi < 30) signal('BUY');
if (currentRsi > 70) signal('SELL');
}
Visualization Only
plot() is strictly for visualization during backtesting. It does not affect signal generation, trade execution, or deployed strategies.
Multiple Series
You can call plot() multiple times with different series names to overlay multiple indicators in the same sub-chart. Each unique series name creates a separate visual layer.
Parameters System
You can make your scripts configurable without changing the code. The system automatically parses your code for parameter definitions using a specific pattern.
Syntax Requirement
To register a parameter, you MUST use the params.name || default pattern.
// Correct usage - Will appear in Settings UI
const period = params.rsiPeriod || 14;
const threshold = params.buyThreshold || 30;
// Incorrect - Will NOT appear in UI
const period = 14;
Once defined in code, these parameters will appear in the Indicator Settings panel under "Indicator Parameters". Prioritize using these over hardcoded values.
Backtesting & Settings Workflow
Understanding how settings interact with your code is crucial for accurate testing.
Settings Hierarchy
Values set in the UI always override values in your code.
- Code Defaults: Used only if no UI setting exists.
- UI Settings: Overwrite code defaults instantly.
Live Updates
When you change a value in the "Settings" tab, simply click Run Backtest again. You do NOT need to save the script or reload the page. The runner injects the current UI values into the params object at runtime.
Take Profit & Stop Loss
The "Backtest Settings" panel (TP/SL/Pyramiding) handles trade management externally from your indicator logic.
- TP Levels: Supports multiple targets (e.g., exit 50% at 2%, 50% at 4%).
- SL Levels: Supports multiple stagged stops.
- Add to Position: Enables pyramiding.
These settings mimic the bot's execution engine and are applied after your signal is generated.