MMTMMT Docs

Colors

Built-in color constants and helpers.

Color helpers accept hex strings (#RRGGBB or #RRGGBBAA) or ABGR numeric values. Functions like color.rgb() return hex strings, so they can be used anywhere a color is accepted by plots, fills, or entities.

For gradient helpers, prefer the enum-style aliases color.mode.*, color.space.*, and color.easing.*. Raw strings still work for compatibility.

For full scripts, see the Colors & Gradients examples.

Constants

Available via color.*:

ConstantValue
color.up(default; set by chart theme config)
color.down(default; set by chart theme config)
color.red
color.maroon
color.brown
color.orange
color.amber
color.yellow
color.olive
color.green
color.emerald
color.teal
color.cyan
color.lightskyblue
color.blue
color.indigo
color.navy
color.purple
color.magenta
color.pink
color.white
color.silver
color.gray
color.black
color.transparent

color.up and color.down are based on your terminals theme up and down colors.

Gradient option aliases:

  • color.mode.clamp
  • color.mode.wrap
  • color.mode.mirror
  • color.space.rgb
  • color.space.hsl
  • color.easing.linear
  • color.easing.smoothstep
  • color.easing.smootherstep

Functions

color.rgb

color.rgb(r, g, b, a?) -> string

Builds a color from 8-bit channel values. a is optional and defaults to 255 (fully opaque).

ParamTypeDescription
rnumberRed channel (0255)
gnumberGreen channel (0255)
bnumberBlue channel (0255)
anumberOptional alpha channel (0255)
const c = color.rgb(17, 34, 51, 68)
plot("RGB", 1, { color: c })

color.r / color.g / color.b / color.t

color.r(color) -> number
color.g(color) -> number
color.b(color) -> number
color.t(color) -> number

Extract 8-bit channel values from a color. color.t() returns the fourth channel value (0255).

const c = color.rgb(17, 34, 51, 68)
log(color.r(c), color.g(c), color.b(c), color.t(c))

color.fromGradient

color.fromGradient(value, bottomValue, topValue, bottomColor, topColor) -> string

Interpolates between two colors across a numeric range.

For more advanced gradient mapping, use color.grade or color.scale

ParamTypeDescription
valuenumberCurrent value to map
bottomValuenumberLower bound
topValuenumberUpper bound
bottomColorcolorColor used at or below bottomValue
topColorcolorColor used at or above topValue
color.fromGradient(barIndex(), 0, 100, color.red, color.green)

color.grade

color.grade(value, stops, options?) -> string

Interpolates across multiple color stops for more flexible color grading.

Stops can use any numeric range — they don't need to be 0..100.

ParamTypeDescription
valuenumberCurrent value to map
stopsarrayAt least 2 stops, either [value, color], { value, color }, or { at, color }
optionsobjectOptional grading controls

Supported options:

OptionTypeDefaultDescription
modestringcolor.mode.clampOut-of-range handling: color.mode.clamp, color.mode.wrap, or color.mode.mirror
spacestringcolor.space.hslInterpolation space: color.space.rgb or color.space.hsl
easingstringcolor.easing.linearSegment easing: color.easing.linear, color.easing.smoothstep, or color.easing.smootherstep
const rsiValue = ta.rsi(candles.close(), 14)
const heat = typeof rsiValue === "number" ? color.grade(rsiValue, [
  [0, color.blue],
  [30, color.teal],
  [50, color.yellow],
  [70, color.orange],
  [100, color.red]
], {
  space: color.space.hsl,
  easing: color.easing.smoothstep
}) : color.transparent

plot("RSI Heat", rsiValue, { color: heat })
const regime = color.grade(candles.close(), [
  [95000, color.blue],
  [100000, color.yellow],
  [105000, color.red]
])

plot("Price Regime", candles.close(), { color: regime })
RGB

Midpoint stays muddy olive because the channels blend directly.

HSL

Midpoint passes through bright yellow because hue rotates through the shortest path.

Linear

Color changes at a constant rate across the bar.

Smoothstep

The ends ease in and out, so the middle transitions faster.

Smootherstep

The same shape, but with even softer acceleration at both ends.

color.scale

color.scale(stops, options?) -> { sample(value): string }

Creates a reusable color scale object. Use this when you want to define the stops once and then sample multiple values from the same gradient.

color.grade(value, stops, options) is the one-off shorthand. color.scale(stops, options).sample(value) is the reusable form.

See the dynamic and static examples for fuller chart-ready versions.

ParamTypeDescription
stopsarrayAt least 2 stops, either [value, color], { value, color }, or { at, color }
optionsobjectOptional grading controls, see color.grade for details

Static scale

Use a static scale when you want consistent coloring across history.

//@version=2
indicator("Color Scale Example", true)
const candles = subscribe(data.OHLCV)

const heatScale = color.scale([
  [0, color.blue],
  [30, color.teal],
  [50, color.yellow],
  [70, color.orange],
  [100, color.red]
], {
  space: color.space.hsl,
  easing: color.easing.smoothstep
})

function onBar(index) {
  const rsiValue = ta.rsi(candles.close(), 14)
  plot("RSI Heat", rsiValue, {
    color: typeof rsiValue === "number" ? heatScale.sample(rsiValue) : color.transparent
  })
}

Dynamic scale

Use a dynamic scale when the stops should adapt to the current bar context. This is useful for relative coloring, but it will not stay historically fixed if the stop values keep moving.

//@version=2
indicator("Color Scale Example", true)
const candles = subscribe(data.OHLCV)

function onBar(index) {
  const rangeLow = ta.lowest(candles.close(), 200)
  const rangeHigh = ta.highest(candles.close(), 200)
  if (typeof rangeLow !== "number" || typeof rangeHigh !== "number") return

  const sessionScale = color.scale([
    [rangeLow, color.blue],
    [rangeHigh, color.red]
  ], {
    space: color.space.hsl
  })

  const emaValue = ta.ema(candles.close(), 20)
  plot("Close", candles.close(), { color: sessionScale.sample(candles.close()) })
  plot("EMA", emaValue, {
    color: typeof emaValue === "number" ? sessionScale.sample(emaValue) : color.transparent
  })
}

color.transp

color.transp(color, percentage) -> string

Applies transparency to a color. 0 is fully opaque, 100 is fully invisible.

See the lighten, darken, and transparency example for a combined overlay use case.

ParamTypeDescription
colorcolorInput color (hex string or ABGR number)
percentagenumberTransparency level (0–100)
color.transp(color.blue, 50)
color.transp("#ff0000", 80)
0
20
40
60
80
100

color.lighten

color.lighten(color, percent) -> string

Lightens a color by increasing RGB channels toward white.

ParamTypeDescription
colorcolorInput color
percentnumberLightness increase (0–100)
color.lighten(color.red, 30)
0
20
40
60
80
100

color.darken

color.darken(color, percent) -> string

Darkens a color by decreasing RGB channels toward black.

ParamTypeDescription
colorcolorInput color
percentnumberDarkness increase (0–100)
color.darken(color.green, 40)
0
20
40
60
80
100

On this page