ScriptingWriting ScriptsStyle guide

Style Guide

Introduction

This style guide provides recommendations on naming variables and organizing your Lipi scripts in a standardized manner that enhances readability, comprehension, and maintainability. Following these best practices will ensure your scripts are easier to read, understand, and maintain.

Naming Conventions

We recommend the use of:

  • camelCase for all identifiers, such as variable or function names: ma, maFast, maLengthInput, maColor, roundedOHLC(), pivotHi().
  • All caps SNAKE_CASE for constants: BULL_COLOR, BEAR_COLOR, MAX_LOOKBACK.
  • Qualifying suffixes when they add valuable context about the type or origin of a variable: maShowInput, bearColor, bearColorInput,maPlotID.

Script Organization

The Lipi Script compiler is quite flexible with the positioning of statements or version annotations in a script. While other arrangements may be syntactically correct, we recommend the following organization:

<declaration_statement>
<import_statements>
<constant_declarations>
<inputs>
<function_declarations>
<calculations>
<visuals>

Declaration Statement

This is the mandatory declaration statement that defines the type of your Lipi Script. It must be a call to either indicator().

Import Statements

The import statement is used to include and access pre-written modules or external scripts within your own Lipi Script code.

Constant Declarations

Scripts can declare variables qualified as “const”, which reference constant values.

We consider variables as “constants” when they meet the following criteria:

  • Their declaration includes the optional const keyword (see our User Manual’s section on type qualifiers for more details).
  • They are initialized with a literal (e.g., 100 or "AAPL") or a built-in qualified as “const” (e.g., color.green).
  • Their value remains unchanged throughout the script’s execution.

We use SNAKE_CASE for naming these variables and recommend grouping their declarations near the top of the script. For example:

// ————— Constants
int     MS_IN_MIN   = 60 * 1000
int     MS_IN_HOUR  = MS_IN_MIN  * 60
int     MS_IN_DAY   = MS_IN_HOUR * 24
 
color   GRAY        = #808080ff
color   LIME        = #00FF00ff
color   MAROON      = #800000ff
color   ORANGE      = #FF8000ff
color   PINK        = #FF0080ff
color   TEAL        = #008080ff
color   BG_DIV      = color.new(ORANGE, 90)
color   BG_RESETS   = color.new(GRAY, 90)
 
string  RST1        = "No reset; cumulate since the beginning of the chart"
string  RST2        = "On a stepped higher timeframe (HTF)"
string  RST3        = "On a fixed HTF"
string  RST4        = "At a fixed time"
string  RST5        = "At the beginning of the regular session"
string  RST6        = "At the first visible chart bar"
string  RST7        = "Fixed rolling period"
 
string  LTF1        = "Least precise, covering many chart bars"
string  LTF2        = "Less precise, covering some chart bars"
string  LTF3        = "More precise, covering less chart bars"
string  LTF4        = "Most precise, 1min intrabars"
 
string  TT_TOTVOL     = "The 'Bodies' value is the transparency of the total volume candle bodies. Zero is opaque, 100 is transparent."
string  TT_RST_HTF    = "This value is used when '" + RST3 +"' is selected."
string  TT_RST_TIME   = "These values are used when '" + RST4 +"' is selected.
  A reset will occur when the time is greater or equal to the bar's open time, and less than its close time.\nHour: 0-23\nMinute: 0-59"
string  TT_RST_PERIOD = "This value is used when '" + RST7 +"' is selected."

In this example:

  • The RST* and LTF* constants will be used as tuple elements in the options argument of input.*() calls.
  • The TT_* constants will be used as tooltip arguments in input.*() calls. Notice how a line continuation is used for long string literals.
  • We do not use var to initialize constants. Although the Lipi Script runtime is optimized to handle declarations on each bar, using var to initialize a variable only on its first declaration incurs a minor performance penalty, as var variables require maintenance on subsequent bars.

Note:

  • Literals used in multiple locations within a script should always be declared as constants. Declaring the constant with a meaningful name enhances readability and ease of maintenance. For example, even though the quantity of milliseconds in a day is unlikely to change, MS_IN_DAY is far more meaningful than 1000 * 60 * 60 * 24.
  • Constants that are only used within a local block of a function, if, while, etc., can be declared within that specific local block.

Inputs

Scripts are much easier to read when all input variables are grouped within the same code section. Positioning this section at the beginning of the script also aligns with runtime processing, where inputs are handled before the script’s execution.

Suffixing input variable names with input makes them more identifiable when used later in the script: maLengthInput, bearColorInput, showAvgInput, etc.

// ————— Inputs
string  resetInput              = input.string(RST2,        "CVD Resets",                       inline = "00", options = [RST1, RST2, RST3, RST4, RST5, RST6, RST7])
int     hourInput               = input.int(9,              "  Fixed time hour:  ",             inline = "01", minval = 0, maxval = 23)
int     minuteInput             = input.int(30,             "minute",                           inline = "01", minval = 0, maxval = 59, tooltip = TT_RST_TIME)
int     fixedPeriodInput        = input.int(20,             "  Fixed period:  ",                inline = "02", minval = 1, tooltip = TT_RST_PERIOD)
string  ltfModeInput            = input.string(LTF3,        "Intrabar precision",               inline = "03", options = [LTF1, LTF2, LTF3, LTF4])

Function Declarations

All user-defined functions must be defined in the script’s global scope; nested function definitions are not allowed in Lipi Script.

Optimal function design should aim to minimize the use of global variables within the function’s scope, as they reduce function portability. When the use of global variables is unavoidable, such functions should follow the global variable declarations in the code, which means they may not always appear in the function_declarations section. Dependencies on global variables should ideally be documented in the function’s comments.

//
indicator("<function_declarations>", "", true)
 
// Define constants for size options
string SIZE_LARGE  = "Large"
string SIZE_NORMAL = "Normal"
string SIZE_SMALL  = "Small"
 
// Input for size selection
string sizeInput = input.string(SIZE_NORMAL, "Size", options = [SIZE_LARGE, SIZE_NORMAL, SIZE_SMALL])
 
// Function to determine size output
getTextSize(simple string userSize) =>
    var string result = "normal"  // Default value
    if userSize == SIZE_LARGE
        result := "large"
    else if userSize == SIZE_NORMAL
        result := "normal"
    else if userSize == SIZE_SMALL
        result := "small"
    result
 
// Rising condition logic
isRising = talib.rising(close, 3)
if isRising
    // Perform local actions if needed
    var int risingCount = 0
    risingCount := risingCount + 1
 
// Use plotshape globally
plotshape(series = isRising, style = shape.triangleup, location = location.abovebar, color = color.new(color.green, 0))

Calculations

This section is where the script’s core calculations and logic should be placed. Code readability can be improved by placing variable declarations near the code segment where they are used. Some developers prefer to declare all non-constant variables at the beginning of this section; however, this may not always be possible, as certain variables may require prior calculations before declaration.

Visuals

This section should ideally contain all statements responsible for producing the script’s visuals, such as plots, drawings, background colors, or candle-plotting. For more details on determining the relative depth of visuals, refer to the Lipi Script user manual’s section on visuals.

Spacing

A space should be used on both sides of all operators, except for unary operators (e.g., -1). Additionally, it is recommended to use a space after all commas and when using named function arguments, as in plot(series = close):

int a = close > open ? 1 : -1
var int newLen = 2
newLen := min(20, newlen + 1)
float a = -b
float c = d > e ? d - e : d
int index = bar_index % 2 == 0 ? 1 : 2
plot(close, color = color.red)

Vertical Alignment

Using vertical alignment with tabs or spaces can improve readability in code sections containing many similar lines, such as constant declarations or inputs. Vertical alignment can also make mass edits easier when using the Lipi Editor’s multi-cursor feature (Ctrl + Alt + ↑).

// Colors used as defaults in inputs.
color COLOR_AQUA  = #0080FFff
color COLOR_BLACK = #000000ff
color COLOR_BLUE  = #013BCAff
color COLOR_CORAL = #FF8080ff
color COLOR_GOLD  = #CCCC00ff

Explicit Typing

Including variable types in declarations is not required, but it can make scripts easier to read, navigate, and understand. Explicit typing clarifies the expected types at each stage of a script’s execution and helps distinguish between a variable’s declaration (using =) and its reassignments (using :=). Using explicit typing can also simplify debugging