RealCode Classes, Manual Looping Overview. (Volume Weighted Price Take 2)
As requested by reader Paul Stiles this article will explore a RealCode Class that performs it’s own looping (instead of using the default AutoLoop property of RealCode).
As you know (you have read all the posts on my blog right?), RealCode performs a loop over the current symbol’s price history and calls your code once for each value that should plot on a chart (or pass for a condition). Sometimes this will make your code perform the same calculation more than once (look-back calculations like max/min and moving averages). While the speed of modern computers is so blazing fast that you probably won’t notice the difference, over multiple iterations (say in a scan or BackScan) you might be able to pick up some noticeable speed by performing your own looping.
Let me say, this is an intermediate to advanced programming topic (for the non-programmer. For a professional developer you should have no problem understanding this). You should be comfortable with arrays, loops and functions before attempting to understand the code here.
As before, lets start with a new RealCode indicator. Switch to the Class tab. In the class body, add the following lines of code:
1: Sub New
2: AutoLoop = false
3: end Sub
This creates a new class constructor. In the body of the constructor we tell the base class not to perform the autolooping functions. Changing this one property changes the way your class is run in context of the calculation. Instead of calling Plot once for every bar on the chart, plot will be called once and it’s your job to fill in the dates and values that you want to display.
When you have AutoLoop disabled, you need to call one of two methods to return your output:
AddToOutput(date,value)
AddToOutput(date,Open,High,Low,Close)
The first AddToOutput call is used when you only want to return one value for each date (like a moving average). The second one is to return bar data.
The other big change when AutoLoop is disabled is that you can no longer use the Price and Volume lookback notation (ala Price.High(10)). The reason should be obvious, you’re not executing in the context of a “current” bar. Instead, you need to access the raw data arrays in the Price and volume indicators.
Price data (and any referenced indicator from the chart) can be accessed using the Price.bar property. The data arrays are as follows:
Price.bar.OpenValue(index)
Price.bar.HighValue(index)
Price.bar.LowValue(index)
Price.bar.Value(index) - (same as close/last)
Price.bar.DateValue(index)
Price.bar.Count - (data length)
Volume has the following methods:
mVolume.Value(index)
mVolume.DateValue(index)
mVolume.Count(index) – should always match the Price.bar.Count variable
If you were to import and indicator via drag and drop like so: ‘# CustomPlot = indicator.MyCustomCode.1. You would have the following available to you:
CustomPlot.IsBar
CustomPlot.Bar
CustomPlot.Line
CustomPlot.Bar will have the exact same calls as the Price.Bar class above and CustomPlot.Line would have the same as mVolume above. You can call IsBar to determine if there is bar data available (Open,High,Low,Close) if you are not sure.
Now that the background is out of the way, lets post the converted code sample. Replace the Body of your new RealCode class with the code below.
1:
2: ‘#period = userinput.integer = 20
3: sub New
4: AutoLoop = False
5: End Sub
6: Public Overrides Function Plot() As System.Single
7: Dim sum As Double = 0
8: Dim VolSum As Double = 0
9:
10: For x As Integer = 0 To Period - 1
11: sum += Price.Bar.Value(x) * mVolume.Value(x)
12: volSum += mVolume.Value(x)
13: Next
14:
15: AddToOutput(Price.bar.DateValue(Period -1),CSng(sum / volsum))
16:
17: For x As Integer = Period To Price.Bar.Count - 1
18: Dim newVal As Double = (Price.Bar.Value(x) * mVolume.Value(x))
19: Dim oldVal As Double = Price.Bar.Value(x - Period) * mVolume.Value(x - period)
20: Dim delta As Double = newval - oldval
21: Dim volDelta = mvolume.value(x) - mvolume.value(x - period)
22:
23: sum += delta
24: volSum += volDelta
25:
26: AddToOutput(Price.Bar.DateValue(x),CSng(sum / volSum))
27: Next
28: End Function
I have modified a few of the variable types from the previous example. I’m using doubles when dealing with the Price and volume calculations to hold larger values due to the “lop off” averaging method. Because of this there might be some minor rounding differences from the previous example.