Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,21 @@ ws.on("message", (tick) => {
## Examples

Real-world entry points live in `examples/`:
- `examples/rsi-strategy.ts`
- `examples/vwap-session.ts`
- `examples/funding-arbitrage.ts`
- `examples/rsi-strategy.mjs`
- `examples/vwap-session.mjs`
- `examples/funding-arbitrage.mjs`
- `examples/rsi-technicalindicators-check.mjs` (external reference check)

If you're using ta-crypto in production or experiments, feel free to add your example here.

Run examples:

```bash
npm run example:all
```

Detailed commands and expected outputs: `examples/README.md`

## Compatibility

`ta-crypto` now ships golden tests (`test/fixtures/golden.json`) to lock behavior across releases.
Expand Down Expand Up @@ -295,6 +304,10 @@ npm run version:patch
npm run release
```

## Trust and Verification

For release integrity, compatibility policy, and verification workflow, see `docs/trust.md`.

## License

MIT
58 changes: 58 additions & 0 deletions docs/trust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Trust and Verification

This page summarizes how to verify `ta-crypto` behavior and release integrity.

## What is verified before release

- Build and tests across Node versions (CI matrix).
- Golden parity checks for core indicators.
- Compatibility checks against external references.
- Typed API contracts and input validation behavior.

Primary workflow:
- `.github/workflows/ci.yml`

## Compatibility trust model

Policy source:
- `scripts/compat-policy.json`

Rules:
- Reference series are aligned to equal length before comparison.
- Indicator-specific burn-in is applied before measuring differences.
- Blocking references: `TA-Lib`, `technicalindicators`.
- Non-blocking telemetry: `pandas-ta` (environment dependent).

Related scripts:
- `scripts/export-compat-vectors.js`
- `scripts/compare-technicalindicators.js`
- `scripts/compare-python-refs.py`

## How to verify locally

```bash
npm ci
npm run build
npm test
npm run test:golden
npm run test:compat:technicalindicators
# python deps: pip install -r scripts/requirements-compat.txt
npm run test:compat:python
```

## Release traceability

- Changelog history: `CHANGELOG.md`
- Git tags and releases: GitHub Releases page
- Current stable line: `v0.3.0`

Recommended verification checks:
1. Confirm release tag exists and matches expected commit.
2. Confirm CI run on `main` is green for the release commit.
3. Confirm compatibility scripts pass in CI logs.

## Limitations and transparency

- Some reference libraries differ in warmup semantics; comparisons use overlapping non-null windows.
- Python reference checks depend on environment packages (`TA-Lib`, `pandas-ta`).
- Crypto orderflow proxies are candle-derived and not equivalent to L2/L3 order book signals.
33 changes: 33 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Examples

All examples are runnable from the repository root and use local `dist/` outputs.

## Run commands

```bash
npm run example:rsi
npm run example:vwap
npm run example:funding
npm run example:rsi:compat
npm run example:all
```

## Expected outputs

- `example:rsi`
- Prints a table with recent rows containing `index`, `close`, `rsi`, and `signal`.
- Warmup rows appear first as `signal: "warmup"`.
- `example:vwap`
- Prints `Batch VWAP session` and `Streaming VWAP session`.
- Both arrays should match index by index.
- `example:funding`
- Prints funding series, cumulative values, and annualized APR values.
- Cumulative is running sum; APR is scaled by `periodsPerYear * 100`.
- `example:rsi:compat`
- Compares `rsi(14)` against `technicalindicators` RSI reference.
- Prints max diff, tolerance, and `PASS`/`FAIL`.

## Notes

- These examples are smoke-entry points for contributors and docs users.
- For reproducibility, run `npm ci` once before running examples.
12 changes: 12 additions & 0 deletions examples/funding-arbitrage.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { fundingRateAPR, fundingRateCumulative } from "../dist/index.js";

const funding = [0.0001, 0.0002, -0.00005, 0.00015, 0.00008, -0.00002];
const periodsPerYear = 1095;

const cumulative = fundingRateCumulative(funding);
const apr = fundingRateAPR(funding, periodsPerYear);

console.log("Funding series:", funding);
console.log("Cumulative funding:", cumulative);
console.log("Annualized funding APR (%):", apr);
console.log("Expected: cumulative is running sum; APR scales each point by periodsPerYear * 100.");
17 changes: 17 additions & 0 deletions examples/rsi-strategy.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { rsi } from "../dist/index.js";

const close = [
100, 101, 102, 100, 98, 97, 99, 101, 103, 104, 103, 102, 101, 99, 98, 97, 99, 102, 104, 105
];

const rsi14 = rsi(close, 14);

const signals = rsi14.map((value, index) => {
if (value === null) return { index, close: close[index], rsi: null, signal: "warmup" };
if (value < 30) return { index, close: close[index], rsi: value, signal: "buy" };
if (value > 70) return { index, close: close[index], rsi: value, signal: "sell" };
return { index, close: close[index], rsi: value, signal: "hold" };
});

console.table(signals.slice(-8));
console.log("Expected: warmup rows first, then hold/buy/sell decisions based on RSI thresholds.");
26 changes: 26 additions & 0 deletions examples/rsi-technicalindicators-check.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { RSI } from "technicalindicators";
import { rsi } from "../dist/index.js";

const close = Array.from({ length: 240 }, (_, i) => 100 + i * 0.04 + Math.sin(i / 9) * 1.2 + Math.cos(i / 17) * 0.7);
const ours = rsi(close, 14);

const padFront = (values, totalLength) =>
Array.from({ length: totalLength - values.length }, () => null).concat(values);

const ref = padFront(RSI.calculate({ period: 14, values: close }), close.length);

let maxDiff = 0;
for (let i = 28; i < ours.length; i++) {
if (ours[i] === null || ref[i] === null) continue;
const diff = Math.abs(ours[i] - ref[i]);
if (diff > maxDiff) maxDiff = diff;
}

const tolerance = 5e-2;
const ok = maxDiff <= tolerance;

console.log(`RSI(14) maxDiff vs technicalindicators: ${maxDiff}`);
console.log(`Tolerance: ${tolerance}`);
console.log(`Result: ${ok ? "PASS" : "FAIL"}`);

if (!ok) process.exit(1);
24 changes: 24 additions & 0 deletions examples/vwap-session.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { createVWAPSession, vwapSession } from "../dist/index.js";

const high = [101, 103, 104, 102, 99, 101, 103, 105];
const low = [99, 100, 101, 99, 96, 98, 100, 102];
const close = [100, 102, 103, 100, 98, 100, 102, 104];
const volume = [10, 15, 13, 20, 11, 14, 16, 19];
const session = ["asia", "asia", "asia", "asia", "eu", "eu", "eu", "eu"];

const batch = vwapSession(high, low, close, volume, session);

const stateful = createVWAPSession();
const streaming = close.map((_, i) =>
stateful.next({
high: high[i],
low: low[i],
close: close[i],
volume: volume[i],
sessionId: session[i]
})
);

console.log("Batch VWAP session:", batch);
console.log("Streaming VWAP session:", streaming);
console.log("Expected: batch and streaming arrays must match exactly for each index.");
7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@
"test:golden": "npm run build && node --test test/golden.test.mjs",
"test:compat:technicalindicators": "npm run generate:compat && node ./scripts/compare-technicalindicators.js",
"test:compat:python": "npm run generate:compat && python ./scripts/compare-python-refs.py",
"test:compat": "npm run test:compat:technicalindicators && npm run test:compat:python"
"test:compat": "npm run test:compat:technicalindicators && npm run test:compat:python",
"example:rsi": "npm run build && node ./examples/rsi-strategy.mjs",
"example:vwap": "npm run build && node ./examples/vwap-session.mjs",
"example:funding": "npm run build && node ./examples/funding-arbitrage.mjs",
"example:rsi:compat": "npm run build && node ./examples/rsi-technicalindicators-check.mjs",
"example:all": "npm run example:rsi && npm run example:vwap && npm run example:funding && npm run example:rsi:compat"
},
"devDependencies": {
"rimraf": "^5.0.5",
Expand Down