Loops

Introduction

Loops are structures that repeatedly execute a block of statements based on specified criteria. They enable scripts to perform repetitive tasks without the need for duplicated lines of code. Lipi Script offers one distinct loop type: while.

Every loop structure in Lipi Script consists of two main components: a loop header and a loop body. The loop header determines the criteria under which the loop executes, while the loop body is the indented block of code (local block) that the script executes during each loop cycle (iteration) as long as the header’s conditions remain valid. Refer to the Common Characteristics section for more details.

Understanding when and how to use loops is crucial for harnessing the full potential of Lipi Script. Inefficient or unnecessary use of loops can result in suboptimal runtime performance. However, effectively employing loops when needed allows scripts to perform a wide array of calculations that would otherwise be impractical or impossible.

When Loops Are Unnecessary

Lipi’s execution model and time series structure make loops unnecessary in many scenarios.

When a user adds a Lipi Script to a chart, it runs within the equivalent of a large loop, executing its code once on every historical bar and real-time tick in the available data. Scripts can access the values from previous executions using the history-referencing operator, and calculated values can persist across executions when assigned to variables declared with the static or intra keywords. These features enable scripts to utilize bar-by-bar calculations to accomplish various tasks instead of relying on explicit loops.

Moreover, several built-in functions, such as those in the ta.* namespace, are internally optimized to eliminate the need for loops in various calculations.

When Loops Are Necessary

While Lipi’s execution model, time series, and available built-ins often remove the need for loops in many situations, not all iterative tasks can be accomplished without them. Loops are essential for various types of tasks, including:

  • Performing calculations that cannot be achieved using loop-free expressions or available built-ins
  • Analyzing past bars by referencing values only available on the current bar

For instance, a loop is required to determine which past bars’ high values exceed the current bar’s high since the current value cannot be accessed during a script’s execution on previous bars. The script can only reference the current bar’s value while executing on that bar, necessitating a look back through the historical series during that execution to compare previous values.

Structure and Syntax

In any loop statement, programmers establish the criteria that determine how long a script remains in the loop and performs iterations. An iteration refers to a single execution of the code within the loop’s local block (body). These criteria are outlined in the loop header. A script evaluates the header’s criteria before each iteration, allowing new iterations to occur only while the criteria remain valid. Once the header’s criteria are no longer valid, the script exits the loop and bypasses its body.

Loop statements in Lipi Script adhere to the following general syntax:

[var_declaration =] loop_header statements | continue | break return_expression

Where:

  • loop_header refers to the header statement of the loop structure, which defines the criteria controlling its iterations.
  • statements represent the code statements and expressions within the loop’s body, i.e., the indented block of code beneath the loop header. All statements within the body belong to the loop’s local scope.
  • continue and break are loop-specific keywords that dictate the flow of a loop’s iterations. The continue keyword instructs the script to skip the remainder of the current iteration and proceed to the next one. Conversely, the break keyword prompts the script to terminate the current iteration and exit the loop entirely. For further details, see this section.
  • return_expression signifies the last line or block of code within the loop’s body. The loop returns results from this code after the final iteration. To utilize values from a loop’s return expression, assign the results to a variable or tuple.
  • var_declaration is an optional declaration for a variable or tuple. If a loop statement includes a declared variable or tuple, the return_expression determines the assigned values. If the header’s conditions prevent the loop from iterating, the assigned values will be na.

Scope

All code lines executed within a loop must be indented by four spaces or a tab relative to the loop’s header. The indented lines following the header define the loop’s body, representing a local block. This means that all definitions within the body are accessible only during the loop’s execution, and the code within the loop’s body is part of its local scope.

Scripts can modify and reassign most variables from outer scopes inside a loop. However, any variables declared within the loop’s body strictly belong to that loop’s local scope, making them inaccessible outside the local block.

Note:

  • Variables declared within a loop’s header are also part of the local scope.
  • The body of any Lipi loop statement can incorporate conditional structures and nested loop statements. When a loop contains nested structures, each structure within the body maintains its own distinct local scope. For example, variables declared within an outer loop’s scope are accessible to an inner loop, but variables declared within the inner loop’s scope are not accessible to the outer loop.

Keywords and Return Expressions

In Lipi Script, every loop implicitly returns a result. The values returned by a loop are derived from the last expression or nested structure executed within the loop body during the final iteration. If no iterations occur, the loop will return na values. The returned results from a loop are only usable if they are not of the void type and if the script assigns a variable or tuple declaration to the loop statement. These declared variables will hold the values from the return expression, making them available for further calculations outside the loop’s scope.

The returned values may originate from evaluating the last expression or nested code block during the final iteration of the loop. However, the loop’s body can include continue and break keywords to manage the flow of iterations beyond what is defined in the loop header, which can also influence the returned results. Programmers typically incorporate these keywords within conditional structures to dictate how iterations behave under certain conditions.

The continue keyword instructs the script to skip the remaining statements and expressions in the current iteration, re-evaluate the loop header’s criteria, and proceed to the next iteration. If the header’s conditions do not permit another iteration, the script will exit the loop.

Conversely, the break keyword tells the script to terminate the loop immediately and exit at that point, preventing any further iterations. Once the loop is broken, the script bypasses any remaining code within the loop’s body and does not re-evaluate the header’s conditions.

If a loop is halted prematurely due to a continue or break keyword, it will return the values from the last iteration where the script evaluated the return expression. If the return expression was never evaluated during any of the iterations, the loop will return na results.

while loops

while

The while statement enables the conditional execution of a local code block based on a specified condition.

Syntax

variable_declaration = while condition

    continue

    break

    _return_expression

Parameters

  • variable_declaration
    An optional variable declaration. The return expression can provide the initialization value for this variable.

  • condition
    A condition that, when true, executes the local block of the while statement. When false, the script resumes execution after the while statement.

  • continue
    The continue keyword skips the remaining code in the current loop iteration and branches to the next iteration.

  • break
    The break keyword terminates the loop. The script resumes execution after the while statement.

  • return_expression
    An optional line that specifies the return value of the while statement.

Example:

indicator("while")
// This is a simple example of calculating a factorial using a while loop.
int i_n = input.int(10, "Factorial Size", minval=0)
int counter   = i_n
int factorial = 1
while counter > 0 {
    factorial := factorial * counter
    counter   := counter - 1
}
 
plot(factorial)

Note: The code block following the while statement must be indented with four spaces or a tab. The loop will stop executing when the boolean condition after while evaluates to false or if a break statement is executed.