feat(data): expose CandleReader (CSV) natively in all 10 languages (#311)

Add the data-layer CSV candle reader to every binding so loading OHLCV
candles from a CSV no longer needs a per-language CSV/dataframe dependency.

- C ABI: wickra_candle_reader_new(bytes, len) / _count / _read / _free over
  an opaque CandleReader handle (parse the whole buffer up front, then drain).
- Native: Node/WASM CandleReader.read() -> Candle[], Python read() -> list[tuple].
- C-ABI languages: Go Read() []Candle, C# Candle[] Read(), Java Candle[] read(),
  R read() S3 generic (n x 6 matrix); C / C++ call the C ABI directly.
- Cross-language golden testdata/golden/data_csv*.csv pins the parsed candles
  bit-for-bit across every binding.

Verified locally across Rust (test+clippy+fmt), Node, WASM, Python, C#, Go,
Java, R, and the C/C++ cmake parity suite.
This commit is contained in:
kingchenc
2026-06-16 00:10:58 +02:00
committed by GitHub
parent cb6da4d737
commit d362ae26a3
31 changed files with 867 additions and 6 deletions
+30
View File
@@ -2,6 +2,7 @@ package wickra
import (
"math"
"os"
"strconv"
"testing"
)
@@ -51,6 +52,35 @@ func TestResamplerGolden(t *testing.T) {
}
}
func TestCandleReaderGolden(t *testing.T) {
csv, err := os.ReadFile("../../testdata/golden/data_csv.csv")
if err != nil {
t.Fatalf("read data_csv.csv: %v", err)
}
r, err := NewCandleReader(string(csv))
if err != nil {
t.Fatalf("new: %v", err)
}
defer r.Close()
candles := r.Read()
got := make([][6]float64, len(candles))
for i, c := range candles {
got[i] = [6]float64{c.Open, c.High, c.Low, c.Close, c.Volume, float64(c.Timestamp)}
}
want := readGolden(t, "data_csv_candles")
if len(got) != len(want) {
t.Fatalf("candle reader: %d candles vs %d", len(got), len(want))
}
for i := range got {
for j := 0; j < 6; j++ {
w := dataParseF(t, want[i][j])
if math.Abs(got[i][j]-w) > 1e-9*math.Max(1, math.Abs(w)) {
t.Errorf("candle reader row %d col %d: %v vs %v", i, j, got[i][j], w)
}
}
}
}
func TestTickAggregatorGolden(t *testing.T) {
ticks := readGolden(t, "data_ticks")
cases := []struct {