summaryrefslogtreecommitdiffstats
path: root/README.md
blob: fe8a3e23eef35316bd40b358e358f6bc85987cce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# ts — Time Series Analysis Library

C11 library of 354 financial and mathematical time-series indicators.

The library provides 354 indicators covering moving averages, oscillators,
volatility measures, statistical functions, and more. See the source files
in `lib/` for the complete list.

**Requirements:** Any C11-compatible compiler, libm, Python 3 (for code generation).

**Platform:** Little-endian only (x86, x86_64, AArch64). Big-endian is not supported.

**Note:** Generated files (`ts_generated.h`, `lib/ts_flat_generated.c`,
`lib/ts_registry_generated.c`) are regenerated automatically by the Makefile.
If you modify indicator sources, run `make` to regenerate.

## Quick Start

```bash
make          # Build example binary
make test     # Run all tests
make lib      # Build static library (libts.a)
make shared   # Build shared library (libts.so)
make install  # Install to /usr/local (PREFIX overrideable)
make check    # Clean build with -Werror + tests
make sanitize-test  # ASAN + UBSan
make uninstall # Remove installed files
```

## Usage

```c
#define TS_IMPLEMENTATION
#include "ts.h"

// Types: fp_t == double, ts_uint_t == uint64_t

// Simple moving average (period=10)
uint_t period = 10;
fp_t input[100];
ts_fill(input, 100, 0, 100);  // fill with 0..100
fp_t output[100];
fp_t * const y[1] = { output };
fp_t const * const x[1] = { input };

ts_constant_t c;
memset(&c, 0, sizeof(c));
*(uint_t *)c.data = period;

int ret = ts_average(y, 1, x, 1, 100, &c);
if (ret == -1) { /* error: invalid params or insufficient data */ }

// Valid output starts at index ts_average_offset(&c) == period - 1
uint_t offset = ts_average_offset(&c);
for (uint_t i = offset; i < 100; i++) {
    // output[i] contains valid SMA values
}
```

## API

Every indicator shares the same signature:

```c
int ts_<name>(
    fp_t * const *y,        // output arrays
    uint_t y_n,             // number of output arrays
    fp_t const * const *x,  // input arrays
    uint_t x_n,             // number of input arrays
    uint_t n,               // number of data points
    ts_constant_t const *c  // parameters (opaque buffer)
);
```

**Return values:** `0` on success, `-1` on error (invalid parameters, insufficient data).

**Offsets:** Each indicator has a `ts_<name>_offset(c)` function. Output values before the offset are undefined. Valid output starts at index `offset`.

**Parameters:** Pass a struct matching the indicator's expected layout. For simple indicators, a raw `uint_t` period works:
```c
uint_t k = 14;
ts_rsi(y, 1, x, 1, n, &k);  // k is read as ts_rsi_params_t{k}
```

**OHLCV access:** Multi-input functions use macros:
- `ts_o(x, i)` — open
- `ts_h(x, i)` — high
- `ts_l(x, i)` — low
- `ts_c(x, i)` — close
- `ts_v(x, i)` — volume

## Thread Safety

The library is **thread-safe for concurrent reads** but has the following constraints:

- Each indicator function is stateless and does not use global mutable state.
- Multiple threads can safely call different indicator functions simultaneously.
- The same indicator function can be called from multiple threads as long as each thread uses its own `x`, `y`, and `c` buffers.
- `ts_constant()` allocates heap memory — `ts_constant_free()` must be called by the owning thread.
- The function registry (`ts_registry_get`, `ts_fn_name_get`) returns pointers to static read-only data and is thread-safe.

## Building

| Target | Description |
|--------|-------------|
| `make` | Build example binary |
| `make lib` | Static library |
| `make shared` | Shared library |
| `make test` | Run test suite |
| `make test-one TEST=rsi` | Run single test |
| `make check` | Clean build with `-Werror` + tests |
| `make valgrind` | Memory leak check |
| `make sanitize-test` | ASAN + UBSan (requires libasan) |
| `make clean` | Remove build artifacts |
| `make distclean` | Remove build + generated files |

## Install

```bash
make install                  # /usr/local
make install PREFIX=/opt/ts   # custom prefix
```

Installs header, static library, shared library, and pkg-config file. Use with:

```bash
pkg-config --cflags --libs ts
```

## License

MIT — Copyright (c) 2025-2026 Ethan Werner