Control Structures
All control structures in Navi are expressions — they produce a value. The last expression evaluated in the executed branch or iteration is the returned value. This means if, for, while, and switch can all appear on the right-hand side of an assignment.
if / else if / else
if close > open {
label.new(bar_index, high, "Bullish")
} else if close < open {
label.new(bar_index, low, "Bearish")
} else {
label.new(bar_index, close, "Doji")
}Returning a value from if
The last expression in each branch is the result. All branches must return the same type:
let x = if close > open {
close
} else {
open
};
plot(x);With else if:
let x = if open > close {
5
} else if high > low {
close
} else {
open
};When the else block is omitted, the result is na (or false / "" for bool/string) when the condition is false:
let x = if close > open {
close
};
// x is na when close <= openReturning tuples from if
Each branch must return a tuple of the same structure:
let (v1, v2) = if close > open {
(high, close)
} else {
(close, low)
};for Loop
Counting Form
let sum = 0.0;
for i = 0 to 9 {
sum += close[i]
}
let averageClose = sum / 10;With a step:
for i = 0 to 20 by 2 {}
// i = 0, 2, 4, 6, ..., 20Reverse loop with negative step:
for i = 10 to 0 by -1 {
array.push(arr, i)
}
// i = 10, 9, 8, ..., 0Collection Iteration (for...in)
Iterate over arrays with value only, or with both index and value:
var prices = array.from(100.0, 200.0, 300.0);
// Value only
for value in prices {
log.info(str.tostring(value))
}
// Index and value (destructured)
for (index, value) in prices {
log.info(str.tostring(index) + ": " + str.tostring(value))
}Returning a value from for
A for loop returns the last expression evaluated in its final iteration. If no iterations execute, it returns na:
// Count how many OHLC values are greater than the SMA
let ohlcValues: array<float> = array.from(open, high, low, close);
fn qtyGreaterThan(value, array) {
let result: int = 0;
for currentElement in array {
if currentElement > value {
result += 1
}
result
}
}
plot(qtyGreaterThan(ta.sma(close, 20), ohlcValues));while Loop
let i = 0;
let sum = 0.0;
while i < 10 {
sum += close[i];
i += 1
}Returning a value from while
Like for, a while loop returns the last expression evaluated in its final iteration:
let i: int = 0;
let result: int = while i < 10 {
i += 1;
i * 2
};
// result is 20 (last iteration: i = 10, 10 * 2 = 20)break and continue
breakexits the loop immediately. The loop returns the value of the last expression evaluated beforebreak.continueskips the rest of the current iteration and proceeds to the next one.
for i = 0 to 99 {
if close[i] < 0 {
break // Exit the loop
} // Exit the loop
if na(close[i]) {
continue // Skip this iteration
} // Skip this iteration
}
// process close[i]Using break and continue with loop return values:
let tempString: string = "";
let finalText: string = for number in randomArray {
if number == 8 {
break // exit loop; returns last evaluated expression
} else if number % 2 == 0 {
continue // skip even numbers
} // skip even numbers
tempString = tempString + str.tostring(number) + ", "
};
// finalText holds the returned value after loop terminationswitch
With Value
Match against a specific value:
Inline branches end with ,; a brace-block branch omits the trailing ,.
let dayName = switch day_of_week {
DayOfWeek.Monday => "Mon",
DayOfWeek.Tuesday => "Tue",
DayOfWeek.Wednesday => "Wed",
DayOfWeek.Thursday => "Thu",
DayOfWeek.Friday => "Fri",
=> "Weekend",
};let i_maType: string = input.string(
"EMA",
"MA type",
options: [
"EMA",
"SMA",
"RMA",
"WMA"
]
);
let ma: float = switch i_maType {
"EMA" => ta.ema(close, 10),
"SMA" => ta.sma(close, 10),
"RMA" => ta.rma(close, 10),
=> ta.wma(close, 10),
};
plot(ma);Without Value (condition-based)
When no key expression is provided, each arm uses a boolean condition. The first matching arm executes:
let direction = switch {
close > open => "up",
close < open => "down",
=> "flat",
};Multi-statement branch
Use a brace block for multiple statements. No trailing , after }:
let label = switch dayOfWeek {
1 => "Mon",
2 => {
let s = "Tue";
s;
}
=> "other",
};Returning tuples from switch
let (v1, v2) = switch {
close > open => (high, close),
=> (close, low),
};switch arms use => to separate the condition from the body. The default arm has no condition before =>.
Next Steps
- Functions & Methods — defining custom functions
- Custom Types & Enums — user-defined types