|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Investor/RT
Tutorials |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
This post is designed to provide a very basic tutorial on using RTL. RTL stands for Real-Time Language and is the language used to write signals, custom indicators, or scans in Investor/RT. RTL really is quite simple in comparison to other languages and does not require previous programming experience (although that certainly helps). If any aspect of this tutorial is not clear or causes confusion, please email cpayne@linnsoft.com or post a comment below the blog post. I will continue to add to this post in the coming days. Once the post is complete, I intend to create a video which covers all aspects of the post visually. This tutorial will focus primarily on RTL syntax and how to code a variety of examples, but if you'd to find out how to create a signal or custom indicator and how to add them easily to charts, watch the Signal Markers and Custom Indicators video (5 minutes long).
Boolean
vs Numerical Results
On each bar, that condition is either true or false.
Internally, true is represented by 1 and false is represented by 0 (zero).
Again, all signals and scans have boolean results.
The result of this custom indicator might be 12.26 on
one bar, 1.12 on the next, and 321.12 on the next.
In the boolean expression mentioned earlier, CL > MA,
would read "the closing price of the bar is greater than the moving average
value of the bar". Similarly, the expression MA <= HI reads "the moving
average value of the bar is below or equal to the high price of the bar".
This expression reads "the closing price of the prior bars is less than the moving average value two bars prior". The period is optional when qualifying. This expression could have also been written as CL1 < MA2. I prefer to use the use the periods to make the expression easier to read.
Compound Operators: AND and OR
Notice the presence of the AND operator forces both conditions to be true in order for the overall result to be true. If either condition is false (or if both are false), the result is false. Let's consider another situation where we are looking for price to be making a higher high OR a lower low. This could be expressed with: HI > HI.1 OR LO <> HI.1 AND LO < LO.1 We would not get a true result unless we made both a higher high and a lower low on the same bar.
Arithmetic
in RTL
The last two operators will rarely be used and not discussed in this basic tutorial. The following custom indicator expression demonstrates the use of arithmetic in RTL:
This expression involves three arithmetic operators and divides twice the volume (2 * VO) by the high/low range of the bar (HI - LO). Notice the use of parentheses in this expression to ensure that the arithmetic operators are processed in the order desired by the user. Parenthesis will be covered in more detail in the following section.
Parentheses - Grouping
Expressions
But placing the parentheses around the two expressions, we've instructed the program to first multiple the volume by 2, then subtract the low from the high, and then take the quotient of the two results. If we had instead omitted the parentheses and instead used the following expression:
Then expression would be evaluated as follows, first multiplying the volume by two, then dividing the result by the high, and THEN subtracting the low from that result. This obviously would have effected a very different outcome. The order in which Investor/RT evaluates any given expression can be seen by simply clicking on the "Check" button at the bottom of the RTL window. Another example that underscores the importance of using parentheses, this time with a boolean expression:
This expression will look for the closing price crossing the moving average in either direction (either crossing above, or crossing below). Notice the two ANDed expressions are grouped and processed first, with their results being ORed together for the final result. If the parentheses had been omitted as follows:
Then Investor/RT would have evaluated the expression in the following manner:
And resulting in quite a different outcome. It is not always necessary to use parenthesis, however, it is important to use the "Check" button to ensure Investor/RT is evaluating your expression in the desired order. It never hurts to use extra parentheses even when not completely necessary as it will not slow down the calculation of the expression.
Special Functions
Below is a complete list of the functions available along with descriptions and some examples.
SLOPE(exp, n) - Change-based slope of
exp over past n bars: (exp - exp.n)/n
Indicator Names,
Syntax, and Preferences
and then click the "Save" button. When the Save button is clicked, Investor/RT will recognize that MA has not yet been added to the list at the upper left, and that it's preferences (type, period, etc) have not yet been specified. The Moving Average preference window will automatically appear, allowing the user to enter the Moving Average period, type, etc. Once the user provides these settings and clicks "OK", another box will popup asking for the name of the Custom Indicator. Each RTL object, including custom indicators, must be identified with a unique name. At this point, the MA preferences can still be edited by double-clicking on the token name (MA) in the list on the upper right of the custom indicator window.
Same Indicator
Token - Multiple Instances
and then when you save the RTL object, you will be asked for the settings for MA (13 period) and then the preferences for MA_B (26 period). You are not restricted to using single letters, MA_TWENTYSIX would have worked equally well as MA_B, but you cannot end your token with a number as that will be interpreted as a qualifier (see qualifier section above).
Indicator of
an Indicator
In this instance, the moving average will operate on the CCI results as opposed to the "Price" that is specified in the moving average preferences. This same format can be used to with any two or more technical indicator tokens.
Multi-Line
Expressions (Backtesting Only)
First, notice that each line ends with a semi-colon. After typing the semi-colon, simply hit the enter key to move to the next line. For each bar, the expression will be evaluated one line at a time, starting with the top line. The net result of the expression will be the result of the last line. Any lines prior to the last line are generally used for maintaining values of user variables (V#), stops, targets, etc. Let's look at the example above line by line. The POS token represents the Position Indicator, which in this example, is setup with "Bars from start of session" (in the indicator preferences). Therefore, the first line reads "if this bar is the first bar of the session, then set V#2 to the high of that first bar. This line will only have an effect on the first bar of each session, initializing V#2 to the high of that bar. The second line reads "if the high of this bar is greater than V#2, then set V#2 to the high of this bar". This allows us to keep track of the high of the session with V#2. Notice the last line is simply "HI = V#2", so the signal will be true on bars we're making a new high, and false otherwise. Again, this multi-line method is commonly used in backtesting for two reasons. It's very convenient to be able to do multiple lines of user variable and stop/target maintenance within a single expression. Secondly (and this is very important), backtests run through the data sequentially, from the oldest bar first, to the most recent bar last. This allows the syntax above using the Position Indicator to work properly. However, for signals or custom indicators added directly to charts, the data is evaluated the reverse order, with the most recent bar being computed first. Therefore, you would not get the results you expected if you added the signal above directly to a chart as a signal marker. For those interested in backtesting, please view the Video Series on Trading Systems and Backtesting. You'll find examples like this and many more.
Efficiency
Sessions and Periodicity in RTL
Bars
Loaded
RTL Objects embedded within
Technical Indicators
Key Indicators in
RTL / Examples
Position
Indicator (POS) Example
(
Additional
Information ) Solution: The Position Indicator (POS) helps us with the "after the 30 minutes" aspect of this requirement. The syntax for this signal follows:
This expression would read "high of this bar is equal to the high of the session AND we are more than 30 minutes from the start of the session". In order for this to work properly, POS must be setup as "minutes from start of session" and the chart to which the signal is added must be set to the day session (session 0 or 2). In addition, SESST (Session Statistics) token must be set to "Highest Price: High: All Bars of the Session".
Signal Statistics
(SSTAT) Example
(
Additional
Information ) Solution: This can be achieved with a combination of Signal Statistics (SSTAT), the REF function, and the TIME token. The syntax of the custom indicator follows:
This statement reads "reference the SSTAT_Begin value x bars back, where x gets it's value from SSTAT_End. SSTAT_End gives us the number of bars back of the 14:50 bar. This is achieved by setting up SSTAT_End with "bars since last signal" using a signal (created and saved seperately) with syntax:
This signal is true only on the bar that ends at 14:50. Furthermore, the SSTAT_Begin token is setup with "Highest Price Since Signal" and "Price: High" and is built upon the following signal:
Again, this signal is created and saved seperately. By referencing that value on the 14:50 bar, we get the high from 14:20 to 14:50 using our original custom indicator above. This implementation will work between any two times, just change the times in the two respective signals appropriately. Two important notes on this custom indicator. First, there is no need to recalculate this indicator frequently. Setting up the indicator to recalculate every 1 minute should be quite sufficient for this moderately inefficient indicator. In addition, within the custom indicator syntax window, specify a value of "Bars: 1000". This will ensure that the custom indicator is considering a sufficient number of bars when recalculating within the chart. When the SSTAT token is involved, it is difficult for Investor/RT to automatically compute how many bars need to be loaded. More Examples
Divergence We'll look at each of these four requirements independently. Different users have different definitions of "divergence", but armed with the information and expressions below, users should be able to formulate their own divergence signals and indicators. This logic will work for divergence with any indicator. Just substitute the desired indicator token in place of the RSI token in each of the expressions below. In addition, this logic can be used to find divergence not only between price and an indicator, but also between any two indicators. This will be discussed below. What was that low value? This one is pretty
straightforward using the MIN operator:
which reads "the minimum RSI value over the past 20 bars". For each bar, this includes that bar AND the previous 19 bars (NOT the previous 20 bars). What's the highest RSI value since that low? This one is a bit
more complicated, but the syntax is actually quite simple:
The key is how STAT (Statistics Indicator) is setup. It should be setup as "Minimum Low for the last 20 Bars" (substitute your required period in place of 20) and with "Resulting Value" of "Bars Since the Minimum Value". Setting up STAT in this fashion, and operating it on RSI in this manner, STAT(RSI), gives us the number of bars back that RSI reached it's low over the past 20 bars. We need to add 1 to this result in order to include the current bar and the low-RSI bar. Therefore, the complete expression will return the maximum RSI value since the low RSI was created, which is exactly what we wanted. The expression would read "Maximum RSI value since the RSI made it's low, including the current bar and the bar which made the RSI low". What was the low price of the instrument on the bar where the RSI made it's low?
Building off what we just explained:
This reads "reference the low price on the bar where the lowest RSI occurred over the previous 20 bars". You can substitute LO with CL or OP if you need the closing or opening price of the instrument on the bar that created the low RSI value. And if you're looking for divergence between two indicators, you can substitute LO with the token for the respective indicator, such as CCI. What's the highest high price of the instrument since the RSI made that low?
Again, building upon the logic we've already discussed:
Which reads "maximum high price achieved since the lowest RSI occurred over the previous 20 bars". Again, if you're looking for divergence between two indicators, just substitute HI with the your respective indicator token, such as CCI.
How can I access the maximum/minimum value between
two events/signals? For example, how I would access the highest high from
the point the CCI turned negative until it turned back positive?
(reads: The CCI of the current bar is
less than zero and the CCI of the previous bar was greater than or equal to
zero).
(reads: The CCI of the current bar is
greater than zero and the CCI of the previous bar was less than or equal to
zero).
Where SSTAT_NEG is setup as "bars since
last signal" referencing signal CCI_NEG, and SSTAT_POS is setup as "bars
since last signal" referencing signal CCI_POS.
To change the starting signal/event, simply change the underlying signal of SSTAT_NEG. To change the ending signal/event, change the underlying signal of SSTAT_POS.
Swing High / Swing Low In these examples, we're defining a Swing High as a bar which has a higher high than the two bars preceding it and following it. How do I write a signal that
will identify Swing Highs and Lows?
With FRACU setup with "Bars Involved: 5". Let's call this signal "SwingHighBar". The FRACU token will give us a 1 on Up Fractals and a 0 otherwise. With FRACU setup for 5 bars, it will identify the Swing Highs involving 5 bars (including itself, the 2 bars before it and 2 bars after it).
Similarly, the Swing Low would be identified with:
Again, with FRACD being setup with "Bars Involved: 5". Let's call this signal "SwingLowBar". FRACD identifies the down fractals or the bars whose low is lower than the 2 bars before and 2 bar after it. If your definition of a Swing High involves 1 or 3 bars before and after (instead of the 2 assumed above), simply adjusting the settings in the Fractal indicator accordingly in the signals.
How would I plot the price of the last Swing High or
Swing Low?
Where SSTAT is setup with "Signal: SwingHighBar" (from above) and "Result: Price At Last Signal" and "Price: High". The price of the last swing low would be identified using the same syntax, but this time, SSTAT would be setup with "Signal: SwingLowBar" (from above), "Result: Price At Last Signal", and "Price: Low".
How would I plot the retracement levels between the
last Swing High and Swing Low?
Where SSTAT_LO is setup to access the
price of last Swing Low as described immediately above, and SSTAT_HI is
setup to access the price of the last Swing High. To plot the 61.8 and
38.2 retracement levels as well:
and...
Users may consider a much easier alternative to the multiple custom indicators above: the Zig Zag Indicator setup with "Draw Fib Levels" checked. This will automatically draw fib retracement levels between key high/low Zig Zag pivots. That method would not only easier, but also more efficient. However, it would use pivots based on price movement and not necessarily identify Swing Highs and Swing Lows. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||