RTL Conditional Operator

The RTL Language has a special operator for conditional evaluation. The operator is designed to allow formulas where one result is desired in some cases and another result in other cases. For example, suppose you want to write a custom indicator formula where the value of the custom indicator is the maximum close in 5 periods for bars that close higher than they opened, but for bars that close at or below their open, the value is to be the minimum close in 5 periods. This kind of conditional formula can be cleverly written as:

(CL > OP) * MAX(CL,5) + (CL <= OP) * MIN(CL, 5)

While this formula does do the job, it relies on the understanding that relational (true/false) expressions such as (CL > OP) evaluate mathematically to 0.0 or 1.0 thus the multiplication by zero or one cancels out one part of the result and preserves the other. Another disadvantage of this technique is that it requires the comparison of the CL and OP twice, thus it is inefficient. In this example the two expressions that control the evaluation are (CL > OP) vs. (CL <= OP). This formulation is more error prone since you must take care to assure that all possible cases are covered. For example if you mistakenly wrote the formula as:

(CL > OP) * MAX(CL,5) + (CL < OP) * MIN(CL, 5)

the indicator would mistakenly evaluate to zero whenever the close equals the open since both CL > OP and CL < OP are false in that case and have a value of zero.

The RTL "Conditional Operator" (the ? operator) addresses these concerns and allows conditional expressions to be written more succinctly, e.g.:

CL > OP ? MAX(CL,5) : MIN(CL,5)

The left operand of the ? operator is the conditional expression to be evaluated. The right side of the ? operator provides two alternatives (the "true" alternative, and the "false" alternative) separated by a colon. For custom indicators like this one, the expression CL > OP is evaluated bar by bar; for each bar for which the expression is true, the first of the alternatives is the resulting value, otherwise the second alternative value is used.

The Conditional Operator can be used in scans and signals. For example:

SET(HIALARM, CL > MA ? MAX(MA,5) : MA )

This formula, run as a scan, will set the high price alarm level of the subject instruments conditionally, depending upon the relationship of the current price to some user-specified moving average. When the current price is above the moving average, the maximum value of that moving average during the preceeding 5 periods is used to set the alarm, otherwise, the alarm is set to occur if price reaches or exceeds the moving average itself.

This formulation is equivalent to the more verbose "IF THEN ELSE" alternative:

IF (CL > MA) THEN SET(HIALARM, MAX(MA,5)) ELSE SET(HIALARM, MA)

In general, anywhere you want a numeric expression in RTL you can use a formulation of the form:

<conditional expression> ? <expressionA> : <expressionB>

where <conditional expression> is any RTL expression that can be evaluated as true or false, and the two alternative expressions are of arbitrary complexity. Unlike IF THEN ELSE, conditional expressions formed with ? and : can be nested. Be sure to use appropriate parentheses to guide the proper evaluation of more complex expressions. Here is an example of a nested conditional:

CL > OP ? MAX(CL,5) : ( CL < MID ? MIN(CL,5) : MIN(CL,3) )

This formula will compute the value of the indicator as MAX (CL,5) for each bar where CL > OP. For bars that close at or below the open, a second conditional evaluation occurs. For those bars, when the close is below the MID (the midpoint of the high-low range) the indicator result is MIN(CL,5), but closes above the midpoint of the range get MIN(CL,3).The entire expression above could be put into a scan that sets the value of a V# variable, i.e.

SET(V#33, CL > OP ? MAX(CL,5) : ( CL < MID ? MIN(CL,5) : MIN(CL,3) ) )

When formulating complex, possibly nested expressions such as this, use the "Check" button in the RTL setup window to review the evaluation steps Investor/RT will use when processing your formula. For the example above you will see something like this:

Parsing: CL > OP ? MAX(CL,5) : (CL < MID ? MIN(CL,5) : MIN(CL,3))

#1. Evaluate: T1=CL > OP
#2. Evaluate: T2=MAX(CL, 5)
#3. Evaluate: T3=CL < MID
#4. Evaluate: T4=MIN(CL, 5)
#5. Evaluate: T5=MIN(CL, 3)
#6. Evaluate: T6=T4 : T5
#7. Evaluate: T7=T3 ? T6
#8. Evaluate: T8=T2 : T7
#9. Result is: T9=T1 ? T8

If you review the steps carefully you can verify that each operator is paired with the right expressions as you intended. Use extra parentheses around your expressions both to improve readability and assure that your intent is clear.

The conditional operator also has some interesting uses when working with user text variables (T# variables). For example, the scan:

SET(T#1, CL >= MA ? "Above" : "Below")

will set the text variable T#1 to one of two strings depending on the expression CL >= MA.

In a Signal employed in a trading system, it is sometimes desirable to include NOTE tokens in the signal formula to output textual data to the backtest detail report. Sometimes, different NOTE annotations are needed under different conditions. A conditional expression such as:

(POS_STATE = 0 ? NOTE_A : NOTE_B)

references two NOTE tokens with differing setups. When the trading system is out of the market (POS_STATE is zero) the NOTE_A annotation text will be output; NOTE_B will be output when the trading system is either long or short. Since a signal must be a true false expression, and since the conditional expression above is considered a numeric expression, you can append this expression to other signal criteria like this:

... AND (POS_STATE = 1 ? NOTE_A : NOTE_B) > 0

using AND to append it and adding the > 0 to make the appended expression a true false expression.