Streaming
Part of TA-Lib's exhaustive specifications, intended for precise AI-agent-driven integration with TA-Lib, to minimize errors.
A stream is defined as the batch call over every bar fed to it: the same values, bit for bit up to the sign of a zero, and the same range (H1); a bar counted with Advance enters the range only. This page owns that definition and the error rules of the stream calls. How to call each language's stream API is on that language's streaming page.
Calls
Every function streams (H10): Open or OpenAndFill once, then Update per closed bar and Peek per forming bar; Value, OutRange, Advance and Clone at any time; Close in C only. Calls, examples and per-language shapes: C/C++, Rust, Java, C#. Rules use C's verbs (TA_<N>_Open and so on); each language's spelling is in names, and how each code reaches the caller in failures.
Definition
H1 Open a stream on bars 0 to k, then Update it with bars k+1 to t, with no Advance. At every bar the stream reported (Open's value for bar k, each Update's for its bar), the value is bit-identical to what batch(0, t) writes for that bar, and OutRange equals the range batch(0, t) reports. This holds under the same parameters and settings, with no setting changed since Open (T7). One exception: a zero output may differ in sign, +0.0 against -0.0, which compare equal (current behaviour: seen in functions that take a rolling maximum or minimum, such as MAX, MIN and MIDPOINT).
H2 The history given to Open defines bar 0. State is carried forward from bar to bar and never re-seeded, so a stream opened on a later start equals the batch call over that shorter series. Which functions' values depend on the start: /functions/stability.
Opening
For Open and OpenAndFill, the history is the first declared input and historyLen its length (a C argument). Rows are in evaluation order (R2).
| Rule | Condition, in evaluation order | Code | Not checked in |
|---|---|---|---|
| S1 | The history is empty (historyLen < 1) | TA_OUT_OF_RANGE_START_INDEX | |
| S2 | The history holds more than TA_INDEX_MAX + 1 bars | TA_OUT_OF_RANGE_END_INDEX | |
| S3 | An optional parameter is outside its accepted values, or the parameters form a combination the function rejects (I3) | TA_BAD_PARAM | |
| S4 | A required argument is absent: an input, an output, or C's outBegIdx or outNBElement | TA_BAD_PARAM | Rust, C#: cannot be absent |
| S5 | An input's length differs from historyLen (I2), or an OpenAndFill output holds fewer than historyLen - lookback values | TA_BAD_PARAM | C: undefined (B5) |
| S6 | OpenAndFill: an output aliases an input or another output (N8) | TA_BAD_PARAM | Rust: cannot alias |
| S6a | OpenAndFill: an output that is not declinable is declined (O5) | TA_BAD_PARAM | Rust: cannot decline. C#: no check of its own (current behaviour) |
| S7 | The history holds fewer than lookback + 1 bars | TA_INSUFFICIENT_HISTORY |
- One check precedes S1. C: the
streamargument itself, NULL answeringTA_BAD_PARAMwith nothing written. Java: a null first input, answeringTA_BAD_PARAM. Rust and C# have none. - S6a: C and Java decline with
NULLornull, which S4 reports first. C# declines with an empty span, which only S5 bounds: when the history holdslookbackbars or fewer, S5 requires no values and S7 answersTA_INSUFFICIENT_HISTORY, where C and Java answerTA_BAD_PARAM. TA_INSUFFICIENT_HISTORYis the one recoverable code: send more bars rather than fix the call. An empty history is S1, not S7, so a loop that waits for enough history starts at one bar.- On S7, a C
OpenAndFillsets*outBegIdxand*outNBElementto 0 and writes no output (current behaviour, an exception to R4). - Non-finite history values: I5.
H3 OpenAndFill writes what batch(0, historyLen - 1) writes, zero signs aside (H1): historyLen - lookback values per output from index 0, the first for bar lookback, and the same range. The handle it opens is the one Open opens on the same history. It takes no startIdx.
Advancing
Update, Peek and Advance.
| Rule | Condition, in evaluation order | Code | Calls | Not checked in |
|---|---|---|---|---|
| U1 | The handle is absent | TA_BAD_PARAM | all | Rust, Java, C#: cannot be absent |
| U4 | The bar this call would count leaves the index domain: begIdx + count > TA_INDEX_MAX | TA_OUT_OF_RANGE_END_INDEX | Update, Advance | |
| U2 | A required output is absent: a C out-pointer, a Java multi-output sink | TA_BAD_PARAM | Update, Peek | Rust, C#: value returned |
| U6a | An output that is not declinable is declined (O5) | TA_BAD_PARAM | Update, Peek | Rust, Java, C#: nothing to decline |
| U3 | A bar value is NaN, +Inf or -Inf (I5) | TA_BAD_PARAM | Update, Peek |
- Outside both tables: B8 from an opener, and in C from some functions'
UpdateandPeek; B7 in C fromOpen,OpenAndFill,Clone, and MAVP'sUpdateandPeek. Peekis exempt from U4: it counts no bar, so it keeps answering at the ceiling.- N7
Peeknever advances the stream and never writes the handle, whatever its outcome and however often it is called. Its value is bit-identical to what the nextUpdatewith the same bar returns. - H4 A rejected
UpdateorPeekchanges nothing: no state, no value, no range, no output variable written. Answer a rejected bar by re-feeding it with a corrected value, or by counting it withAdvance(H5); doing neither leaves the handle one bar behind the feed. U4 never clears: open a new handle on a shorter history. B7, B8 and O7 are outside this rule. - H5
Advancecounts one bar the handle was not fed: the range grows by one and nothing else moves. That bar's output is the previous one, held, andValueanswers it. Later Updates compute over the bars fed, as if the counted bar did not exist; only the range includes it. - A declination binds only its own call: the set an
UpdateorPeekdeclines may differ from the opener's and from the previous call's. - An accepted bar whose output is not finite (O6, such as LN on 0) is a success: the state advances,
Valueanswers that value, and the range grows by one.
Accessors
H6 Value returns the value(s) at the last counted bar, the bar the range ends on, without recomputing: after Open the last history bar's, after an accepted Update that bar's, after Advance the held value. OutRange is [begIdx, begIdx + count) in the input series' coordinates: the batch range over the same bars, Advance-counted bars included. begIdx + count never exceeds TA_INDEX_MAX + 1.
H7 Clone is a deep, independent fork at the same bar: the same state, value and range, and updating either never affects the other.
The C accessors' error surface:
| C call | TA_BAD_PARAM when | Other codes |
|---|---|---|
Value | the stream is NULL, or a required output pointer is NULL; a declinable one may be NULL and is not written | none |
OutRange | the stream or either out-pointer is NULL | none |
Advance | the stream is NULL | U4 |
Clone | the stream or clone is NULL | TA_ALLOC_ERR |
Close | never | none |
In Rust, Java and C#, only Advance (U4) and Java's multi-output value(out) (TA_BAD_PARAM for a null sink) reject anything.
Lifetime
- C ownership. Close every handle that
Open,OpenAndFillorClonereturns, exactly once;Closefrees it. When one of them fails, it sets its handle out-parameter (*stream,*clone) to NULL unless that argument is itself NULL (B7 aside), so never open or clone into a variable that holds a live handle. A failedCloneleaves the original untouched. - X1
Close(NULL)is a success no-op. Only C has a release call; Rust drops a handle and Java and C# collect it. - H8 A handle is not serializable and is valid only within the library version that opened it. To checkpoint, keep the history, the bars fed since and the number of bars counted with
Advance; reopen on the bars and callAdvancethat many times (H1, H5). - Threads on one handle: T4. A setting changed while a stream is open: T7.
Index outputs
H9 In a stream, the index outputs of MININDEX, MAXINDEX and MINMAXINDEX count the bars fed to the handle: the history, then each accepted Update. A bar counted by Advance is not fed, so after an Advance an index no longer equals that bar's position in the range. Example in C, MININDEX at period 3: open on 6 bars, Advance, then Update with a new low; the stream answers 6, where batch over all 8 bars, the skipped one included, answers 7.
Discovery
H10 Every function streams, in every language. The metadata flag is TA_FUNC_FLG_STREAM: Rust FuncFlags::STREAM, Java FuncFlags.STREAMING, C# FuncFlags.Stream. A stream is opened by its typed Open; the abstraction layer binds batch calls only.