The Java library is a native port of TA-Lib in the io.github.talib package — no JNI, pure Java. Every indicator is a method on a Core instance, operates on double[] arrays (or float[], see 4.4), and is bit-identical to the reference C library over the same inputs, with one exception beyond TA-Lib's control: where a calculation calls a transcendental math function (such as exp, log, sin or atan), Java's math library can round the result differently from the C library in the last bit (rD1).
The settings each Core carries: unstable period and candlestick settings. Multiple Core instances can safely co-exist (say for different settings).
Every TA function, each processing a whole array of data at once.
An optional Abstract API for calling those functions dynamically.
To process a live feed one bar at a time instead, see the companion Java Streaming API.
There is no initialization step and nothing to shut down. Where C requires TA_Initialize before any call and TA_Shutdown at exit, Java has Core.DEFAULT (or a configured Core.builder()...build()) ready immediately, and an unreferenced Core is simply garbage-collected.
Every function follows the same simple pattern: it reads its inputs from arrays you pass in and writes its results into arrays you allocate.
A function never writes more elements than you request, so the output array only needs to cover the startIdx-to-endIdx range.
As an example, let's walk through SMA, a method to calculate a moving average.
public OutRange sma( int startIdx,int endIdx,double[] inReal,int optInTimePeriod,double[] outReal )
All TA methods use the same calling pattern, divided into four groups:
The output will be calculated only for the range specified by startIdx and endIdx. These are zero-based indices into the input arrays.
One or more input arrays are then specified. Typically, these are the "price" data. In this example there is only one input. All input parameter names start with "in".
Zero or more optional inputs are then specified. In this example there is one optional input. These parameters give finer control specific to each function. If you do not care about a particular optIn, just pass Core.INTEGER_DEFAULT or Core.REAL_DEFAULT (depending on the type). For a moving-average type, use MAType.DEFAULT.
One or more output arrays come last. In this example there is only one output (outReal). Where the values landed is the return value, not a parameter: on success you get an OutRange.
This calling pattern takes some getting used to, but it lets your app spend time and memory only on the data it actually needs.
For example, here is how to calculate a 30-day simple moving average (SMA) of daily closing prices:
import io.github.talib.Core;
import io.github.talib.OutRange;
double[] close = /* ...your closing prices... */;
double[] out = new double[close.length];
OutRange r = Core.DEFAULT.sma(
0, close.length - 1,
close,
30,
out );
// out[0 .. r.count() - 1] holds the SMA; out[i] is input bar r.begIdx() + i.
for (int i = 0; i < r.count(); i++) {
System.out.println("bar " + (r.begIdx() + i) + " = " + out[i]);
}
After the call, read r to learn what was produced. Even though we requested the whole range (0 to close.length - 1), a 30-day average is not defined until the 30th day. Consequently r.begIdx() will be 29 (zero-based) and r.count() will be close.length - 29. In other words, only that many elements of out are written, corresponding to input elements 29 through the end.
If you do not provide enough data to calculate even one value, the call still succeeds and r.count() is 0 (r.isEmpty()).
OutRange is an immutable record with two components, begIdx() and count() (C's outBegIdx and outNBElement), plus the conveniences isEmpty() and EMPTY.
Size the output array to at least endIdx - startIdx + 1, or exactly with the lookback (see the three sizing methods):
int lookback = Core.DEFAULT.smaLookback(30); // 29 for a 30-period SMA
Each TA method has a matching <name>Lookback method, taking the same optional parameters as the method itself. The lookback is how many inputs are consumed before the first output.
A few indicators are conventionally drawn at another bar than the one that computes them. The values are never moved: the matching <name>DisplayShift method gives the number of bars to shift one output when charting it, positive ahead and negative behind. It is 0 for almost every function.
int shift = Core.DEFAULT.dpoDisplayShift(20, 0); // period 20, first output: -11
Misuse throws rather than returning a return code:
Mistake
Exception
startIdx/endIdx negative, above Core.INDEX_MAX, or endIdx < startIdx
TALibIndexException
Optional parameter outside its documented range
TALibArgumentException
Two outputs sharing one array
TALibArgumentException
An array too short for the range requested, including an endIdx past the end of the input
TALibArgumentException
A null array
TALibArgumentException
Each extends the platform type you would reach for — TALibIndexException an IndexOutOfBoundsException, the rest an IllegalArgumentException — so catching either shape works, and every one carries its RetCode.
A rejected call leaves every array untouched.
A NaN or ±Inf inside an input series is not detected. Clean the series before calling.
The io.github.talib.metadata package describes every function at run time and calls it without naming it at compile time. Useful for a UI, a scripting bridge, or anything that enumerates indicators. See the Abstract API page.
Your value changed when you fed the same bar more history? That is by design: recursive functions converge as history accumulates. See Unstable Period for how to mitigate that.
Rounding is a separate axis: floating-point error accumulates over a very long series, which is one reason a call is capped at Core.INDEX_MAX.
Every function documentation page carries a numerical-stability property: how much the value at a given bar depends on where the series you passed in begins.
The CDL* pattern methods judge each candle against tunable thresholds. See candlestick settings for the full list and defaults; the builder sets them the same way:
Every indicator is overloaded for float[] inputs as well as double[]. The float overload converts each element to double when read, so both produce the same output, bit-for-bit. Use it to feed price data already stored as float without a conversion copy.
Core.INDEX_MAX is the largest value startIdx or endIdx may take: 100,000,000. It's a sanity bound. Past it, a call is more likely a caller bug than a real need, and it's also untested territory for overflow and rounding error.
Core is immutable, so one instance is safe to share across any number of threads with no synchronization.
Use Core.DEFAULT for the all-defaults instance. There are no setters: to change a setting, derive a new instance with core.toBuilder(). Read a configured unstable period back with core.unstablePeriod(FuncUnstId.EMA), a candle setting with core.candleSetting(CandleSettingType.BODY_DOJI).
Every function has Javadoc, published to Maven Central as the artifact's javadoc jar, which an IDE fetches alongside the library.
You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.