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

# Draw a level and a label

> Draw a line at the highest high of the last N bars and a label with its price, created once on the last bar and then moved instead of redrawn.

In this tutorial we draw a horizontal line at the highest high of the last N bars and a label that names its price. We draw them
once, on the last bar of the chart, and then keep them and move them as the chart grows, instead of drawing new ones. Every step is a
whole script: replace what is in the editor, and check it.

Unlike `plot`, the drawing calls (`line.new`, `label.new`, `box.new`, ...) may be called inside an `if`, a loop or a function. They
return a handle you can keep, change and delete.

### 1. find the level

`talib.highest(source, length)` is the highest value of `source` over the last `length` bars. We plot it first to see what we are
going to draw.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("High line and label", overlay=true)
length = input.int(50, "Bars", minval=1, maxval=200)
float level = talib.highest(high, length)
plot(level, title="Highest high", color=color.orange)
```

A stepped orange line follows the highest high of the last 50 bars.

### 2. draw the line on the last bar

`line.new(x1, y1, x2, y2)` draws a line between two points. The x values are bar numbers (`bar_index` is the number of the bar the
script is on), the y values are prices. `barstate.islast` is true only on the last bar, so the line is drawn once the script reaches
the end of the history. `extend=extend.right` carries it past the last bar.

```lipi highlight={5-8} theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("High line and label", overlay=true)
length = input.int(50, "Bars", minval=1, maxval=200)
float level = talib.highest(high, length)
firstBar = math.max(bar_index - length + 1, 0)
if barstate.islast {
    line.new(firstBar, level, bar_index, level, extend=extend.right, color=color.orange)
}
```

The line starts at the first bar of the window and runs to the last bar at the level of the highest high. `math.max` keeps the start
from going below bar 0 on a short chart.

### 3. add the label

`label.new(x, y, text)` puts text at a point. The text is joined from strings, and numbers are converted with `str.tostring`.

```lipi wrap highlight={8} theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("High line and label", overlay=true)
length = input.int(50, "Bars", minval=1, maxval=200)
float level = talib.highest(high, length)
firstBar = math.max(bar_index - length + 1, 0)
if barstate.islast {
    line.new(firstBar, level, bar_index, level, extend=extend.right, color=color.orange)
    label.new(bar_index, level, text="High of " + str.tostring(length) + " bars: " + str.tostring(math.round(level, 2)), color=color.orange, textcolor=color.white)
}
```

### 4. keep the drawings and move them

A drawing stays on the chart until the script deletes it or the limit for its kind trims it (50 of each kind unless the declaration
raises it). A script that calls `line.new` every time it reaches the last bar adds a line each time. Instead, create the line and
the label once, hold them in `static` variables, and move them afterwards.

* `static line levelLine = na` and `static label levelLabel = na` declare empty handles that last across bars.
* `na(levelLine)` is true until a line has been assigned to it, so the first branch runs once.
* `line.set_xy1`, `line.set_xy2`, `label.set_xy` and `label.set_text` change the existing drawings.

```lipi theme={"languages":{"custom":["/languages/lipi.json","/languages/lipi-invalid.json"]}}
//@lipi=2
indicator("High line and label", overlay=true)
length = input.int(50, "Bars", minval=1, maxval=200)
float level = talib.highest(high, length)
firstBar = math.max(bar_index - length + 1, 0)
static line levelLine = na
static label levelLabel = na
string note = "High of " + str.tostring(length) + " bars: " + str.tostring(math.round(level, 2))
if barstate.islast {
    if na(levelLine) {
        levelLine := line.new(firstBar, level, bar_index, level, extend=extend.right, color=color.orange)
        levelLabel := label.new(bar_index, level, text=note, color=color.orange, textcolor=color.white)
    } else {
        line.set_xy1(levelLine, firstBar, level)
        line.set_xy2(levelLine, bar_index, level)
        label.set_xy(levelLabel, bar_index, level)
        label.set_text(levelLabel, note)
    }
}
```

Name the string variable something other than `text`: `text` is the name of a built-in namespace, and a variable called `text`
compiles with the warning ``Variable `text` hides the built-in namespace `text`.``

## What we built

An indicator with one setting that keeps a single line and a single label on the chart and moves them to the current highest high of
the last N bars.

## Next

* [Lines, labels, boxes and polylines](https://gocharting.com/docs/scripting/chart-output/drawings.md): every drawing function and its arguments.
* [How to keep one label that moves with the last bar](https://gocharting.com/docs/scripting/how-to/keep-one-label-that-moves.md)
* [How to keep drawings under the limit](https://gocharting.com/docs/scripting/how-to/keep-drawings-under-the-limit.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.