Stream Indexing
Brief
The section briefly describes how to access to the price stream data
Details
The index of the period
The prices and indicator results are accessed by the "index of bar". The index of bar
is an integer number. 0
means the oldest bar in the price collection currently
displayed on the chart. The size() - 1
bar means the newest bar in the price
collection currently displayed on the chart.
For Marketscope application, this index is related to the time axis. The 0 means the
leftmost available position at this scale, the size() - 1
means the rightmost position
at this scale.
The indicator outputs is synchronized
for the scale, so, it is expected that
the indicator value for the Nth bar on the chart is located by the Nth index
in the indicator output stream. The indicator core handles synchronization, so, before the
Update
method of the indicator is called, the core extends/reduces the
indicator outputs, so the outputs have appropriate size and the data previously
calculated for the source bars are located on the proper positions, even if the position
of these bars in the source are changed.
By default, the indicator output has the same size as the indicator source. However,
the indicator can make the source shorter or longer than the source using extent
parameter of the output.
The first()
value of the stream
While the prices are usually defined for every index of the source, the indicator can be not defined for a number of bars at the beginning of the output. For example, the simple moving average (an average price of previous N bars) cannot be calculate for the for the first N-1 bars, there is just no enough data to calculate it.
Therefore, the indicator can define the firstPeriod
parameter of the output stream.
This value means the index of the oldest bar of the source for which the indicator
value is defined. This value is extremely important for both the indicator usage and
the indicator calculation, so the developers must handle it extremely carefully.
1) Handling the first()
value of the stream during the indicator usage.
When you use the indicator in another indicator or in an strategy, you must not
access to the data by the index smaller than the value returned by first()
method of the stream. The data is just not defined for these bars. Please, also, pay attention
that many of methods requires the data defined in the bar, earlier than the bar referenced.
For example core.crosses(stream, 0, P)
(check whether the stream crossed the 0-level
at the period P) requires the values defined at indexes P and
P - 1
(previous bar), so
P must be greater than stream:first()
.
Another example is core.sum(stream, core.rangeTo(P, 10))
(calculate a sum of the values
for 10 periods before P (including P itself)), requires the data defined starting at P - 9
period, so P must be greater than stream:first() - 10
2) Handling the first()
value of the stream during the indicator development.
It's not easy to recognize problems, related to incorrect handling of the firstPeriod
value in the indicator output. If you specify 0 in that parameter and just skip filling the
first N values, the indicator will look on the chart exactly the same as the indicator which
specifies N in the firstPeriod
parameter of the output stream. So, during displaying
it looks good enough. But when you try to apply another indicator on the results of such
indicator, this indicator can produce wrong values. This happens because the applied indicator
tries to use the data which aren't defined. For example the EMA indicator applied on such wrong
output will try to account these unfilled value and since EMA depends on it's previous value, the
whole indicator result will be affected. So, to let the indicators which use our result work
properly you must exactly declare the index of the oldest result you can provide.
Also, because for most of the indicators the source can be any source - prices or result of another indicator, you must always calculate the first available value for against the first value of the source.
However, please do not forget that the indicator's Update
function is called for
each bar of the source, starting at 0 bar, even if the source or the indicator output
is not defined. So, you have to check whether the currently updating bar is after the first bar every time
when the Update
function is called.