---
title: "Color constants"
description: "The named colors a chart accepts in an Indicator's declarations, where a name is refused and a hex form is required, and how to build a palette array for…"
order: 27
section: "core-concepts"
---

<!-- source: docs/indicators/core-concepts/color-constants.md; generated by packages/cli/scripts/gen-indicator-docs.ts, do not edit -->

# Color constants

The named colors a chart accepts in an Indicator's declarations, where a
name is refused and a hex form is required, and how to build a palette
array for per-bar coloring. kScript (legacy) shipped a table of named
constants usable in any `colors=[...]` array; an Indicator writes the same
names as string literals on outputs, segments, renderers, and borders,
and writes hex on anything that takes an opacity.

## Available named colors

The chart interprets a declared color string as a CSS color, so the
familiar names work on every surface that does not blend a fill. The names
kScript documented, with the hex value each one stands for:

| Color | Hex value | Usage |
| --- | --- | --- |
| `yellow` | `#FFFF00` | Highlights, warnings |
| `orange` | `#FFA500` | Accent color, signals |
| `purple` | `#800080` | Secondary indicators |
| `gray` | `#808080` | Neutral, background |
| `black` | `#000000` | Text, borders |
| `white` | `#FFFFFF` | Light themes, contrast |
| `red` | `#FF0000` | Bearish, sell signals |
| `green` | `#008000` | Bullish, buy signals |
| `blue` | `#0000FF` | Primary indicators |
| `silver` | `#C0C0C0` | Subtle backgrounds |
| `maroon` | `#800000` | Dark red tones |
| `fuchsia` | `#FF00FF` | Vibrant highlights |
| `lime` | `#00FF00` | Bright green |
| `olive` | `#808000` | Muted yellow-green |
| `navy` | `#000080` | Dark blue |
| `teal` | `#008080` | Blue-green |
| `aqua` | `#00FFFF` | Bright cyan |

Write the hex value instead of the name and the result is identical on
every surface, including the one that refuses names. That is the habit
this tree's examples follow.

## Where a name is accepted, and where it is refused

| Declaration | `color` accepts | Why |
| --- | --- | --- |
| `output(..., { color })` and the `colors` palette | a name, hex, `rgb()`, `hsl()` | the chart parses it as a CSS color |
| `segment(..., { color })` | a name, hex, `rgb()`, `hsl()` (1 to 64 characters) | a stroke, no fill |
| `box(..., { borderColor })` | the same as a segment | a stroke |
| `box(..., { color })` | hex (3, 4, 6, or 8 digits), `rgb()` / `rgba()`, `hsl()` / `hsla()` only | the fill takes the box's `opacity`, so the host must be able to rewrite the color with an alpha channel; a name is refused at validation with `color must be a hex, rgb() or hsl() color (the fill takes the opacity)` |
| `render.text`, `render.label`, `render.shape`, `render.bgcolor`, `draw.*` | a name, hex, `rgb()`, `hsl()` | strokes and text |
| `range(..., { color, colors })` | a name, hex, `rgb()`, `hsl()` | the band's edges and tint |

Alpha rides in the color itself as an eight-digit hex (`#2563eb33`) or an
`rgba()` / `hsla()` form, or on top through the `opacity` option (0..1) of
an output, a box, or a range. The two compose: a box with `color:
"#2563eb"` and `opacity: 0.15` fills at fifteen percent.

## Using colors in your Indicators

### Single color

Use one color per output for simple lines. A name and its hex are
interchangeable here:

```text
output("sma20", line, overlay, { color: "orange", width: 2 });
output("sma50", line, overlay, { color: "#FFA500", width: 2 });   // the same orange
```

### Multi-color Indicators

Combine colors across outputs for a multi-line study. Each line owns its
color; there is no shared array with a `colorIndex` argument:

```text
output("sma10", line, overlay, { color: "blue", width: 2 });
output("sma20", line, overlay, { color: "orange", width: 2 });
output("sma50", line, overlay, { color: "green", width: 2 });
```

### Conditional colors

kScript switched a line's color per bar with `colors=[...]` and a computed
`colorIndex`. An Indicator declares the palette on the output as `colors`
and names a data-only output as `color_by`; that output's per-bar value
(floored) indexes the palette, and a missing or out-of-range index falls
back to entry 0. An output cannot color itself, so the decision is its own
output. RSI colored by level, with a named color in the palette to show
the names are accepted there:

```typescript
import { input, line, lower, none, ohlcv, output, param } from "./sdk/declare";
import { in_close } from "./gen/inputs";
import { emitRow, out_level, out_rsi } from "./gen/outputs";
import { p_period } from "./gen/params";
import { Rsi } from "./sdk/ta";

param("period", 14, { min: 2, max: 200, description: "RSI length" });
input("close", ohlcv.close);
// colors is the palette; level picks the entry per bar: 0 red (overbought), 1 green (oversold), 2 blue (neutral).
output("rsi", line, lower, { width: 2, color_by: "level", colors: ["#FF0000", "green", "#0000FF"], description: "RSI with conditional colors" });
output("level", none, lower, { description: "0 above 70, 1 below 30, 2 in between" });

let rsi = new Rsi(14);
let value: f64 = NaN;

export function init(): void {
  rsi = new Rsi(i32(p_period()));
}

export function state(): i32 {
  value = rsi.update(in_close());
  return isNaN(value) ? 0 : 1;
}

export function finalize(): void {
  out_rsi(value);
  out_level(value > 70.0 ? 0.0 : value < 30.0 ? 1.0 : 2.0);
  emitRow();
}

export function reset(): void {
  rsi.reset();
  value = NaN;
}
```

The ladder is a bucket ladder, not a gradient: a continuous color from a
value is **not in Indicators yet** (`functions/color-functions.md`), and
the worked alternative is a palette with as many entries as you want
buckets. `width_by` with a `widths` array is the same ladder for line
width.

## Recommended palettes

Pre-designed combinations that work well together, written as the
`colors` array of a `color_by` output or spread across several outputs.

### Trading signals

Classic colors for buy/sell signals and trend indicators:

```text
colors: ["green", "red", "blue"]
```

### Technical analysis

Professional colors for technical indicators and overlays:

```text
colors: ["orange", "purple", "teal"]
```

### Volume analysis

Distinct colors for volume-based indicators:

```text
colors: ["lime", "yellow", "fuchsia"]
```

### The tree's own palette

The worked examples across this documentation use one muted set that reads
on dark and light chart themes alike: `#2563eb` blue, `#16a34a` green,
`#dc2626` red, `#f59e0b` amber, `#7c3aed` violet, `#94a3b8` slate for
reference lines, and `#22d3a5` / `#ff5b7f` for bull and bear tints.

## Best practices

- **Consistent branding.** Use the same color scheme across related
  Indicators; a package's colors are declarations, so they are easy to
  keep aligned across versions.
- **Accessibility.** Choose colors with enough contrast, and never rely on
  color alone: a `shape` mark or a data-only output carries the same
  decision for anyone who cannot see the tint (and for an alert, which
  cannot see it at all).
- **Semantic colors.** Green for bullish signals and positive values, red
  for bearish signals and losses, blue for neutral indicators and
  reference lines, orange or yellow for warnings.
- **Hex on anything with a fill.** A box's `color` must be hex, `rgb()`,
  or `hsl()`; writing hex everywhere means never meeting that refusal.
