Files
wickra/examples/csharp/fetch_btcusdt/Program.cs
T
kingchenc 91f6f67257 Add C# (.NET) binding over the C ABI hub (#226)
The first language stecker on the C ABI hub: a .NET binding exposing all 514
indicators as idiomatic `IDisposable` classes, generated from `wickra.h`.

## What's here

- **`bindings/csharp/`** — the `Wickra` .NET 8 package. `[LibraryImport]`
  source-generated P/Invoke (`NativeMethods.g.cs`) plus idiomatic wrappers
  (`Indicators.g.cs`), both generated from the committed `bindings/c/include/wickra.h`.
  The binding owns no indicator maths — it only marshals types across the C ABI.
- **Marshalling, verified end-to-end against the native library.** Opaque handles
  cross as `nint` kept alive per call via a `SafeHandle`; `bool` as
  `[MarshalAs(U1)]` (Rust `bool` is one byte); a self-correcting
  `DllImportResolver` validates the loaded library actually exports the Wickra
  ABI. Tests cover one representative per FFI archetype (scalar, candle, pairwise,
  multi-output, bars, profile, values-profile, order-book / array-input) plus
  exact Sma reference values.
- **NuGet packaging** — `dotnet pack` produces `Wickra.<version>.nupkg`; the
  release pipeline stages prebuilt native libraries under `runtimes/<rid>/native/`
  for six target triples (win/linux/osx × x64/arm64).
- **`examples/csharp/`** — nine examples mirroring `examples/c/`: streaming,
  backtest, multi_timeframe, parallel_assets, three strategies, and
  fetch_btcusdt + live_binance.
- **CI** — a `csharp` job on the three OSes builds the C ABI, tests the binding,
  and runs the offline examples. **Release** — a gated `csharp-publish` job packs
  and pushes to NuGet (gated on `NUGET_API_KEY`, independent of the GitHub-release
  job so a C# hiccup never blocks the C/C++ asset release).
- **Docs consistency wave** — README, CONTRIBUTING, CHANGELOG, examples/README,
  the issue / PR templates, `sync-about.yml`, and `.gitattributes`.

The native Python / Node / WASM bindings and the C ABI are untouched; this is
additive. Publishing to NuGet stays gated behind the release tag and the secret.
2026-06-09 14:32:05 +02:00

34 lines
1.2 KiB
C#

using System.Globalization;
using System.Text.Json;
// Download real BTCUSDT hourly klines from the Binance REST API into a CSV that the
// other examples can consume. Requires network access (build-only in CI).
const string url = "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=1h&limit=500";
using var http = new HttpClient();
Console.WriteLine($"Fetching {url}");
var json = await http.GetStringAsync(url);
using var doc = JsonDocument.Parse(json);
var dir = Path.Combine(AppContext.BaseDirectory, "data");
Directory.CreateDirectory(dir);
var path = Path.Combine(dir, "btcusdt_1h.csv");
using var writer = new StreamWriter(path);
writer.WriteLine("timestamp,open,high,low,close,volume");
var count = 0;
foreach (var kline in doc.RootElement.EnumerateArray())
{
// Binance kline array: [openTime, open, high, low, close, volume, ...]
var ts = kline[0].GetInt64();
var o = kline[1].GetString();
var h = kline[2].GetString();
var l = kline[3].GetString();
var c = kline[4].GetString();
var v = kline[5].GetString();
writer.WriteLine(string.Create(CultureInfo.InvariantCulture, $"{ts},{o},{h},{l},{c},{v}"));
count++;
}
Console.WriteLine($"Wrote {count} klines to {path}");