Java
Verified against the Rust reference. Every one of Wickra's 514 indicators is replayed through all 10 languages and checked bit-for-bit against the Rust core's golden fixtures in CI — the math here is provably identical to every other binding (how).
The Java binding is a language shim on the C ABI hub built on the Java Foreign Function & Memory API (Panama). It ships on Maven Central as org.wickra:wickra with the native library prebuilt for every supported platform; there is nothing to compile.
<dependency>
<groupId>org.wickra</groupId>
<artifactId>wickra</artifactId>
<version>0.9.9</version>
</dependency>- Distribution: Maven Central (
org.wickra:wickra), native libraries bundled per platform (win/linux/osx × x64/arm64). - Requirements: Java 22+ (the FFM API is final since Java 22). Run with
--enable-native-access=ALL-UNNAMED. - Built on: the C ABI hub via the Java FFM API (
java.lang.foreign), generated fromwickra.h— not JNI, not jextract. - Memory model: opaque handles are
MemorySegments freed by ajava.lang.ref.Cleaner; try-with-resources for deterministic cleanup.
The class shape
Every indicator is an AutoCloseable class with update / batch / warmupPeriod / isReady / reset. Prefer try-with-resources so the native handle is freed deterministically.
import org.wickra.Sma;
try (Sma sma = new Sma(14)) { // throws IllegalArgumentException on invalid params
int w = sma.warmupPeriod(); // updates until ready: 14
double v = sma.update(42.0); // NaN while warming up
boolean ready = sma.isReady(); // false until warmed up
sma.reset();
} // freed at the end of the try-with-resources scopeThe alt-chart bar builders (RenkoBars, KagiBars, …) have no warmupPeriod / isReady — a candle can complete 0..n bars, so they have no warmup.
Streaming
try (Rsi rsi = new Rsi(14)) {
for (double price : feed) {
double v = rsi.update(price);
if (Double.isFinite(v) && v > 70.0) {
System.out.printf("overbought %.2f%n", v);
}
}
}Batch (one call over a whole series)
try (Ema ema = new Ema(20)) {
double[] values = ema.batch(prices); // NaN at warmup positions
}Multi-output indicators
Indicators with several outputs return a record — null while warming up:
try (MacdIndicator macd = new MacdIndicator(12, 26, 9)) {
for (double price : feed) {
MacdOutput m = macd.update(price);
if (m != null) {
System.out.printf("macd=%.4f signal=%.4f hist=%.4f%n",
m.macd(), m.signal(), m.histogram());
}
}
}Candle-input indicators take OHLCV plus a timestamp, e.g. atr.update(open, high, low, close, volume, timestamp).