Skip to content

Quickstart: C# ​

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).

A five-minute tour of the Wickra C# binding — the first language shim on the C ABI hub. By the end you will have streamed an RSI, run a batch SMA, and read a multi-output MACD, all as idiomatic C#.

Install ​

The binding ships on NuGet as Wickra with the native library prebuilt for every supported platform (Linux, macOS, Windows — x64 and arm64); there is nothing to compile.

bash
dotnet add package Wickra

It targets .NET 8 and later.

The class shape ​

Every indicator is an IDisposable class over an opaque native handle, with the same operations as the C ABI underneath:

csharp
using Wickra;

using var sma = new Sma(14);     // throws ArgumentException on invalid params
int w = sma.WarmupPeriod();      // updates until ready: 14
double v = sma.Update(42.0);     // NaN while warming up
bool ready = sma.IsReady();      // false until warmed up
sma.Reset();                     // back to a fresh state
// disposed (freed) at the end of the using scope

The alt-chart bar builders (RenkoBars, KagiBars, …) have no WarmupPeriod / IsReady — a candle can complete 0..n bars, so they have no warmup.

Update never revisits the history behind the tick. Prefer using for deterministic cleanup; a SafeHandle also frees the handle from the finalizer, so a missed Dispose never leaks permanently.

Streaming and batch side by side ​

csharp
using Wickra;

// 1. Streaming: feed Wilder's textbook example into RSI(14).
using var rsi = new Rsi(14);
double[] prices =
{
    44.34, 44.09, 44.15, 43.61, 44.33, 44.83, 45.10, 45.42,
    45.84, 46.08, 45.89, 46.03, 45.61, 46.28, 46.28, 46.00,
};
for (var i = 0; i < prices.Length; i++)
{
    var r = rsi.Update(prices[i]);
    if (double.IsFinite(r)) // NaN during the 15-bar warmup
    {
        Console.WriteLine($"tick {i + 1,2}  rsi={r:F4}");
    }
}

// 2. Batch: one SMA(3) call over five prices writes NaN at warmup.
using var sma = new Sma(3);
double[] outValues = sma.Batch(new double[] { 1, 2, 3, 4, 5 });
// outValues -> { NaN, NaN, 2.0, 3.0, 4.0 }

The first RSI value lands on tick 15. Batch output is bit-for-bit identical to feeding the same inputs through Update one at a time.

The opt-in fast batch ​

Every single-output Batch has a Span<double> overload that writes into a buffer you reuse, and a BatchFast twin in both forms; MACD, MacdFix and Bollinger Bands have a record-array BatchFast:

csharp
var output = new double[prices.Length];
using var sma = new Sma(20);
sma.Batch(prices, output);               // exact, no allocation

using var ema = new Ema(20);
double[] fast = ema.BatchFast(prices);   // or ema.BatchFast(prices, output)

The fast batch runs a SIMD kernel where the indicator has one (moving averages, RSI, ATR, MACD and MACDFIX, Bollinger Bands, the Chaikin oscillator, skewness, Pearson correlation and more). The kernel reassociates the arithmetic, so each value agrees with the exact batch to within a few units in the last place rather than bit for bit; NaN placement and length are identical, and the result is the same on every platform. Where an indicator has no kernel, the fast batch is the exact batch. Keep the exact batch wherever you compare against streaming bit for bit; reach for the fast one when throughput is the point. See Streaming vs Batch.

Multi-output indicators ​

Indicators with several outputs (MACD, Bollinger, ADX, …) return a nullable record struct — null while warming up, a value once one is ready:

csharp
using var macd = new MacdIndicator(12, 26, 9);
foreach (var price in feed)
{
    if (macd.Update(price) is { } m)
    {
        Console.WriteLine($"macd={m.Macd:F4} signal={m.Signal:F4} hist={m.Histogram:F4}");
    }
}

Candle-input indicators (ATR, ADX, OBV, …) take the OHLCV fields plus a timestamp, e.g. atr.Update(open, high, low, close, volume, timestamp).

A deeper example ​

examples/csharp/backtest runs a basket of indicators over an OHLCV series; the examples/csharp/ directory also has a multi-indicator streaming demo, multi-timeframe resampling, a Parallel.For fan-out, three strategy examples, and Binance fetch/live examples. Build the C ABI once, then run any of them:

bash
cargo build -p wickra-c --release
dotnet run --project examples/csharp/streaming

See also ​