> ## Documentation Index
> Fetch the complete documentation index at: https://docs.myfundedperpetuals.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom Scripts

> Write your own chart indicators in a Pine-style script language, with lines, colors, markers, background shading, and adjustable inputs.

Custom Scripts let you build your own indicators on the trade chart and the
trade journal chart. You write a short script, in a language modeled on
TradingView's Pine Script, and the chart draws the result on every candle.

There are two Custom Script indicators:

| Indicator | Where it draws |
| - | - |
| **MFP Custom Script** | Its own pane below the price chart, like RSI or MACD. |
| **MFP Custom Script Overlay** | On top of the candles, like a moving average. |

<Note>
  Custom Scripts are rolling out gradually. If you don't find them in the
  **Indicators** dialog, they aren't available on your account yet.
</Note>

## Add a script

1. Open the chart and select **Indicators**.
2. Search for **MFP** and choose **MFP Custom Script** or **MFP Custom Script
   Overlay**.
3. Open the indicator's settings from its row in the chart legend.
4. On the **Inputs** tab, replace the text in the **Script** box with your
   script and select **Ok**.

Your script is saved with your chart layout, so it comes back when you
reload the page. You can add each indicator more than once to run several
scripts side by side.

Scripts run only in your browser, on the candles already loaded on your
chart. A script can read prices and draw on the chart. It can't place
orders, change settings, or read anything else about your account, so a
script someone shares with you can't act on your behalf.

## Fix errors

If a script has a mistake, the indicator draws nothing and a notice appears
at the bottom of the chart. The notice gives the line and column of the
problem and, where it can, a suggestion:

```
Line 2, column 6: Unknown name "clsoe". Did you mean "close"?
```

The notice clears as soon as the script is valid. You can dismiss it with
the close button; it stays hidden until a different error appears or you
reload the page.

## Write a script

A script is a list of statements, one per line. You can also separate
statements with a semicolon. Text after `//` is a comment.

```
// Two moving averages
fast = ema(close, 9)
slow = ema(close, 21)
plot(fast, "Fast", color=color.blue)
plot(slow, "Slow", color=color.orange)
```

* **Names.** `fast = ema(close, 9)` gives a value a name you can reuse on
  later lines. Each name can be set once, and a name can't reuse a built-in
  value such as `close` or `na`.
* **One-line scripts.** A script that is a single expression, such as
  `ema(close, 21)`, draws that expression as a line.
* **Long lines.** A line continues onto the next one when the next line is
  indented, when it starts with an operator such as `+` or `?`, or when the
  line ends with an operator, a comma, or an open bracket.
* **History.** Add `[n]` to read a value from `n` candles ago: `close[1]` is
  the previous close, and `fast[5]` is `fast` five candles back.
* **Missing values.** `na` means "no value". Math with `na` gives `na`, and a
  line isn't drawn where its value is `na`. Early candles often have no value
  because a moving average needs a full window first.

### Operators

| Operator | Meaning |
| - | - |
| `+` `-` `*` `/` `%` | Arithmetic. Dividing by zero gives `na`. |
| `>` `<` `>=` `<=` `==` `!=` | Comparisons. They give `1` for true and `0` for false. |
| `and` `or` `not` | Logic. Any nonzero value counts as true. |
| `condition ? a : b` | `a` when the condition is true, otherwise `b`. |

`&&` and `!` work like `and` and `not`, and a double vertical bar works like
`or`. `true` and `false` are the same as `1` and `0`.

## Draw lines

`plot(value, title, color, linewidth, style)` draws a line. Only the value
is required; the other arguments can be passed in order or by name.

```
plot(rsi(close, 14), "RSI", color=color.purple, linewidth=2)
hline(70, "Overbought", color=color.gray)
hline(30, "Oversold", color=color.gray)
```

`hline(price, title, color, linestyle, linewidth)` draws a horizontal level.
It is dashed unless you set `linestyle`.

| Argument | Values |
| - | - |
| `style` | `plot.style_line`, `plot.style_linebr`, `plot.style_stepline`, `plot.style_histogram`, `plot.style_columns`, `plot.style_area`, `plot.style_areabr`, `plot.style_circles`, `plot.style_cross` |
| `linewidth` | A whole number from 1 to 4. |
| `linestyle` | `hline.style_solid`, `hline.style_dotted`, `hline.style_dashed` |

A script can draw up to 8 lines between `plot` and `hline`. In the
indicator's **Style** tab they appear in order as **Plot 1** to **Plot 8**;
titles are for your own reference and don't rename those rows. The style and
width you set in the script apply whenever you add the indicator or edit the
script. Between edits you can still change them in the **Style** tab.

## Colors

Colors come from your script, so the **Style** tab has no color pickers for
Custom Scripts. A line with no color uses its slot's default color.

| Form | Example |
| - | - |
| Named color | `color.red` |
| Hex code | `#FF5252`, or `#FF525280` with transparency |
| Transparency (0 is solid, 100 is invisible) | `color.new(color.green, 80)` |
| Red, green, blue, and optional transparency | `color.rgb(255, 82, 82, 50)` |
| A blend between two colors | `color.from_gradient(rsi(close, 14), 30, 70, color.red, color.green)` |

The named colors are `color.aqua`, `color.black`, `color.blue`,
`color.fuchsia`, `color.gray`, `color.green`, `color.lime`, `color.maroon`,
`color.navy`, `color.olive`, `color.orange`, `color.purple`, `color.red`,
`color.silver`, `color.teal`, `color.white`, and `color.yellow`.

A color can change from candle to candle:

```
hist = ema(close, 12) - ema(close, 26)
plot(hist, "Momentum", color = hist >= 0 ? color.green : color.red, style=plot.style_columns)
```

Older scripts that pass `transp=` alongside a color are also supported.

## Mark candles

`plotshape(condition, title, style, location, color)` draws a marker on every
candle where the condition is true. A script can have up to 4 markers.

```
fast = ema(close, 9)
slow = ema(close, 21)
plotshape(crossover(fast, slow), "Cross up", style=shape.triangleup, location=location.belowbar, color=color.green)
plotshape(crossunder(fast, slow), "Cross down", style=shape.triangledown, location=location.abovebar, color=color.red)
```

| Argument | Values |
| - | - |
| `style` | `shape.triangleup`, `shape.triangledown`, `shape.arrowup`, `shape.arrowdown`, `shape.labelup`, `shape.labeldown`, `shape.circle`, `shape.square`, `shape.diamond`, `shape.flag`, `shape.cross`, `shape.xcross` |
| `location` | `location.abovebar`, `location.belowbar`, `location.top`, `location.bottom`, `location.absolute` |

With `location.absolute`, the marker sits at the value you pass instead of at
the candle, for example `plotshape(high, location=location.absolute)`. In
**MFP Custom Script**, which draws in its own pane, above-bar and below-bar
markers are placed at the top and bottom of that pane.

## Shade the background and candles

`bgcolor(color)` shades the chart background behind candles. `barcolor(color)`
recolors the candles themselves. Pass `na` to leave a candle unchanged.

```
bgcolor(rsi(close, 14) > 70 ? color.new(color.red, 85) : na)
barcolor(volume > 2 * sma(volume, 20) ? color.yellow : na)
```

If a script calls either function more than once, later calls take
priority wherever they give a color.

## Add adjustable inputs

Inputs let you change a script's numbers without editing the script.

```
length = input.int(20, "Length", minval=1)
source = input.source(close, "Source")
plot(sma(source, length))
```

The **Inputs** tab has fields **Input 1** to **Input 8**. They match the
script's inputs in the order they appear: the first `input` call is
**Input 1**, the second is **Input 2**, and so on. Leave a field blank to use
the script's default, or type a value to replace it. A value outside
`minval` or `maxval`, or of the wrong kind, shows an error that names the
input.

Inputs can also appear directly inside a helper. For example,
`sma(input.source(close), input.int(20))` uses **Input 1** for the source
and **Input 2** for the length. Each input call uses one field, including
inside helpers such as `vwma`, `cci`, `hma`, and `stoch`.

| Function | Accepts |
| - | - |
| `input.int(default, title, minval, maxval)` | A whole number. |
| `input.float(default, title, minval, maxval)` | Any number. |
| `input.bool(default, title)` | `true` or `false` (also `yes`, `no`, `on`, `off`, `1`, `0`). |
| `input.source(default, title)` | `open`, `high`, `low`, `close`, `volume`, `hl2`, `hlc3`, `ohlc4`, or `hlcc4`. |
| `input(default, title)` | Takes its kind from the default: a whole number, a decimal, `true`/`false`, or a source. |

## Built-in values

| Name | Value |
| - | - |
| `open` `high` `low` `close` `volume` | The candle's prices and volume. |
| `hl2` `hlc3` `ohlc4` `hlcc4` | Averages of the candle's prices. |
| `tr` | True range, which counts a gap from the previous close. |
| `vwap` | Volume-weighted average price since 00:00 UTC. |
| `bar_index` | The candle's position, starting at 0. |
| `math.pi` `math.e` | Math constants. |

## Built-in functions

Lengths and occurrences must be whole numbers known before the script runs:
a number, an input, or a name set to one of those (for example
`len = input.int(14)` or `slow = len * 2`). You can write functions with or
without Pine's `ta.` and `math.` prefixes, so `ta.sma` and `sma` are the same.

| Group | Functions |
| - | - |
| Moving averages | `sma(src, len)`, `ema(src, len)`, `wma(src, len)`, `rma(src, len)`, `hma(src, len)`, `vwma(src, len)`, `vwap(src)` |
| Oscillators | `rsi(src, len)`, `stoch(src, high, low, len)`, `cci(src, len)`, `atr(len)`, `tr()` |
| Windows | `highest(src, len)`, `lowest(src, len)`, `sum(src, len)`, `stdev(src, len)`, `variance(src, len)`, `dev(src, len)`, `median(src, len)` |
| Change | `change(src, len)`, `mom(src, len)`, `roc(src, len)`, `cum(src)` |
| Signals | `crossover(a, b)`, `crossunder(a, b)`, `cross(a, b)`, `rising(src, len)`, `falling(src, len)`, `barssince(cond)`, `valuewhen(cond, src, occurrence)` |
| Missing values | `na(x)`, `nz(x, replacement)`, `iff(cond, a, b)` |
| Math | `abs`, `sqrt`, `exp`, `log`, `log10`, `pow`, `floor`, `ceil`, `round(x, decimals)`, `sign`, `min`, `max`, `avg`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan` |

Notes on specific functions:

* `highest(len)` and `lowest(len)` with only a length use `high` and `low`.
* `change`, `mom`, and `roc` compare against one candle back when you leave
  out the length.
* `stdev` and `variance` measure the whole window (population), matching
  Pine.
* `valuewhen(cond, src, 0)` is the value at the most recent candle where the
  condition was true; `1` is the one before that, up to `9`.
* `min`, `max`, and `avg` take 2 to 10 values.

## Limits

| Limit | Value |
| - | - |
| Script length | 4,000 characters |
| Lines (`plot` and `hline`) | 8 |
| Markers (`plotshape`) | 4 |
| Inputs | 8 |
| History reference (`close[n]`) | 5,000 candles |
| Length of any one function | 5,000 candles |
| All function lengths in one script, added up | 20,000 candles |

The last limit keeps a script from slowing down your chart. A script over
any limit shows an error instead of running.

## Differences from Pine Script

Many simple Pine Script indicators paste in with little or no change, and
headers such as `//@version=5` and `indicator(...)` are accepted. These parts
of Pine Script aren't supported, and each shows an error explaining so:

* `if`, `for`, `while`, and `switch` blocks. Use `condition ? a : b`.
* `var`, reassigning with `:=`, and your own functions.
* Lists, tuples such as `[a, b] = ...`, and text other than titles.
* Data from other markets or timeframes (`request.security`).
* Strategies, alerts, `fill`, `plotchar`, `plotarrow`, and drawing objects
  such as labels, lines, boxes, and tables.
* `offset=` on plots, and `input.string`, `input.color`, and
  `input.timeframe`.

`plotshape` accepts `text=` and `size=`, but markers are drawn without text,
at the chart's standard size. `alertcondition` is accepted and has no effect.

## Examples

### MACD

```
fastLen = input.int(12, "Fast")
slowLen = input.int(26, "Slow")
macd = ema(close, fastLen) - ema(close, slowLen)
signal = ema(macd, 9)
hist = macd - signal
plot(hist, "Histogram", color = hist >= 0 ? color.green : color.red, style=plot.style_columns)
plot(macd, "MACD", color=color.blue)
plot(signal, "Signal", color=color.orange)
hline(0)
```

Use **MFP Custom Script** so it draws in its own pane.

### Bollinger Bands with breakouts

```
len = input.int(20, "Length")
mult = input.float(2, "Width")
basis = sma(close, len)
band = mult * stdev(close, len)
plot(basis, "Basis", color=color.orange)
plot(basis + band, "Upper", color=color.teal)
plot(basis - band, "Lower", color=color.teal)
plotshape(crossover(close, basis + band), "Breakout", style=shape.triangleup, location=location.belowbar, color=color.lime)
bgcolor(close > basis + band ? color.new(color.green, 85) : na)
```

Use **MFP Custom Script Overlay** so it draws on the candles.

### RSI with colored levels

```
r = rsi(close, 14)
plot(r, "RSI", color=color.from_gradient(r, 30, 70, color.red, color.green))
hline(70)
hline(30)
bgcolor(r > 70 or r < 30 ? color.new(color.gray, 85) : na)
```
