|
The RTL Language has been improved by the addition of a
new 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 new 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 of course be used in scans and signals as
well. 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. |