From 986458de699c00697b3694c565a5a8f7fe55f8c3 Mon Sep 17 00:00:00 2001 From: islam Date: Wed, 5 Aug 2026 16:48:37 +0300 Subject: [PATCH 1/2] Release camelCase contract surface for 0.12.0 --- README.md | 6 +- docs.json | 6394 +++++---- package-lock.json | 4 +- package.json | 4 +- scripts/clean.mjs | 12 + scripts/gen-docs.mjs | 9 + scripts/sync.mjs | 70 + src/_registry.ts | 196 +- src/_shared/momentum.ts | 8 +- src/_shared/reversal.ts | 220 - src/_shared/volume.ts | 10 +- .../reversal-structures/double-bottom/impl.ts | 221 +- .../double-bottom/index.ts | 6 +- .../reversal-structures/double-top/impl.ts | 221 +- .../reversal-structures/double-top/index.ts | 6 +- .../head-and-shoulders/impl.ts | 221 +- .../head-and-shoulders/index.ts | 6 +- .../inverse-head-and-shoulders/impl.ts | 221 +- .../inverse-head-and-shoulders/index.ts | 6 +- .../reversal-structures/triple-bottom/impl.ts | 221 +- .../triple-bottom/index.ts | 6 +- .../reversal-structures/triple-top/impl.ts | 221 +- .../reversal-structures/triple-top/index.ts | 6 +- .../momentum/connors-rsi/index.ts | 6 +- .../momentum/stochastic-rsi/index.ts | 6 +- .../momentum/ultimate-oscillator/index.ts | 6 +- .../momentum/williams-r/index.ts | 6 +- .../trend-systems/adx/impl.ts | 4 +- .../directional-movement/impl.ts | 2 +- .../directional-movement/index.ts | 6 +- .../trend-systems/parabolic-sar/impl.ts | 2 +- .../trend-systems/parabolic-sar/index.ts | 6 +- .../volatility-and-channels/atr/impl.ts | 4 +- .../volatility-and-channels/atr/index.ts | 6 +- .../bollinger-bands/impl.ts | 2 +- .../bollinger-bands/index.ts | 6 +- .../bollinger-bandwidth/impl.ts | 4 +- .../bollinger-bandwidth/index.ts | 6 +- .../donchian-channels/impl.ts | 2 +- .../donchian-channels/index.ts | 6 +- .../keltner-channels/impl.ts | 6 +- .../keltner-channels/index.ts | 6 +- .../true-range/impl.ts | 2 +- .../true-range/index.ts | 6 +- .../accumulation-distribution-line/index.ts | 6 +- .../chaikin-money-flow/index.ts | 6 +- .../volume-indicators/force-index/index.ts | 6 +- .../money-flow-index/index.ts | 6 +- .../volume-price-trend/index.ts | 6 +- test/_examples.json | 145 +- test/_manifest.json | 509 +- test/conformance.test.ts | 61 +- test/fixtures/D01-F01-A01.json | 76 + test/fixtures/D01-F01-A02.json | 20 + test/fixtures/D01-F01-A03.json | 19 + test/fixtures/D01-F01-A04.json | 52 + test/fixtures/D01-F01-A05.json | 41 + test/fixtures/D01-F01-A06.json | 70 + test/fixtures/D01-F01-A07.json | 26 + test/fixtures/D02-F01-A02.json | 136 +- test/fixtures/D02-F01-A03.json | 230 +- test/fixtures/D02-F01-A04.json | 205 +- test/fixtures/D02-F01-A05.json | 135 +- test/fixtures/D02-F02-A01.json | 99 +- test/fixtures/D02-F02-A02.json | 178 +- test/fixtures/D02-F02-A03.json | 192 +- test/fixtures/D02-F02-A04.json | 124 + test/fixtures/D02-F02-A05.json | 109 +- test/fixtures/D02-F03-A01.json | 161 +- test/fixtures/D02-F03-A02.json | 218 +- test/fixtures/D02-F03-A03.json | 807 +- test/fixtures/D02-F03-A04.json | 322 +- test/fixtures/D02-F03-A05.json | 202 +- test/fixtures/D02-F04-A01.json | 264 +- test/fixtures/D02-F04-A02.json | 195 +- test/fixtures/D02-F04-A03.json | 272 +- test/fixtures/D02-F04-A04.json | 107 +- test/fixtures/D04-F01-A01.json | 44 +- test/fixtures/D04-F01-A02.json | 40 +- test/fixtures/D04-F01-A03.json | 57 + test/fixtures/D04-F01-A04.json | 46 + test/fixtures/D04-F01-A05.json | 32 +- test/fixtures/D04-F02-A01.json | 17 +- test/fixtures/D04-F02-A02.json | 38 +- test/fixtures/D04-F02-A03.json | 38 +- test/fixtures/D04-F02-A04.json | 38 +- test/fixtures/D04-F02-A05.json | 38 +- test/fixtures/D04-F02-A06.json | 38 +- test/fixtures/D04-F03-A01.json | 30 +- test/fixtures/D04-F03-A02.json | 30 +- test/fixtures/D04-F03-A03.json | 147 +- test/fixtures/D04-F03-A04.json | 28 +- test/fixtures/D04-F03-A05.json | 28 +- test/fixtures/D04-F03-A06.json | 28 +- test/fixtures/D06-F01-A01.json | 36 +- test/fixtures/D06-F01-A02.json | 38 +- test/fixtures/D07-F01-A01.json | 3 +- test/fixtures/D07-F01-A02.json | 4 +- test/fixtures/D07-F01-A03.json | 3 +- test/fixtures/D07-F01-A04.json | 4 +- test/fixtures/D07-F01-A05.json | 9 +- test/fixtures/D07-F01-A06.json | 9 +- test/fixtures/D07-F01-A07.json | 77 +- test/fixtures/D07-F01-A08.json | 84 +- test/fixtures/D07-F01-A09.json | 11266 +++++++++++++++- test/fixtures/D07-F02-A01.json | 9 + test/fixtures/D08-F01-A01.json | 24 +- test/fixtures/D08-F01-A02.json | 25 +- test/fixtures/D08-F01-A03.json | 30 +- test/fixtures/D08-F01-A04.json | 26 +- test/fixtures/D09-F02-A01.json | 9 +- test/fixtures/D09-F02-A02.json | 10 +- test/fixtures/D09-F02-A03.json | 11 +- test/fixtures/D09-F02-A04.json | 18 +- test/fixtures/D09-F02-A05.json | 14 +- test/fixtures/D09-F02-A06.json | 8 +- test/fixtures/D09-F04-A01.json | 19 +- test/fixtures/D09-F04-A02.json | 21 +- test/fixtures/D09-F04-A03.json | 22 +- test/fixtures/D09-F04-A04.json | 17 +- test/fixtures/D09-F04-A05.json | 20 +- test/fixtures/D09-F04-A06.json | 17 +- test/registry.test.ts | 67 +- 123 files changed, 21668 insertions(+), 4349 deletions(-) create mode 100644 scripts/clean.mjs delete mode 100644 src/_shared/reversal.ts diff --git a/README.md b/README.md index fb4dec9..c9387cf 100644 --- a/README.md +++ b/README.md @@ -83,9 +83,9 @@ Requires Node ≥ 22. ## Verified against published worked examples -**88 of 324 topics** are verified against the catalog's own published numbers -(50 via `{ input, expected }`, 11 via row fixtures, 27 via bar/checkpoint fixtures). -The remaining 236 are proven to load and expose a callable entry point, but their +**158 of 324 topics** are verified against the catalog's own published numbers +(117 via `{ input, expected }`, 11 via row fixtures, 30 via bar/checkpoint fixtures). +The remaining 166 are proven to load and expose a callable entry point, but their arithmetic is not asserted here — those topics ship no machine-readable expected values in the catalog. diff --git a/docs.json b/docs.json index 8309194..a165ad9 100644 --- a/docs.json +++ b/docs.json @@ -2,17 +2,17 @@ "schemaVersion": "1.0.0", "package": { "name": "fintech-algorithms", - "version": "0.11.0", + "version": "0.12.0", "homepage": "https://docs.thefintechbuilder.com" }, "counts": { "topics": 324, "domains": 13, "families": 54, - "verified": 88, - "withExample": 323, + "verified": 158, + "withExample": 324, "withDiagram": 324, - "withApiContract": 280 + "withApiContract": 324 }, "domains": [ { @@ -448,56 +448,55 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"intervalSeconds\":60,\"sessionStarts\":{\"2026-01-05\":\"2026-01-05T14:30:00.000Z\",\"2026-01-06\":\"2026-01-06T14:30:00.000Z\"},\"emptyBarPolicy\":\"omit\"})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A01.json", + "call": "constructBars([{\"tradeId\":\"W1\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":10,\"currency\":\"USD\"},{\"tradeId\":\"W2\",\"timestamp\":\"2026-01-05T14:30:59.999Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":101,\"volume\":5,\"currency\":\"USD\"},{\"tradeId\":\"W3\",\"timestamp\":\"2026-01-05T14:31:00.000Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":99,\"volume\":8,\"currency\":\"USD\"}], {\"intervalSeconds\":60,\"sessionStarts\":{\"S1\":\"2026-01-05T14:30:00.000Z\"},\"emptyBarPolicy\":\"omit\",\"closePartial\":true})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W1", "timestamp": "2026-01-05T14:30:00.000Z", - "session": "2026-01-05", + "session": "S1", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 10, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", - "session": "2026-01-05", + "tradeId": "W2", + "timestamp": "2026-01-05T14:30:59.999Z", + "session": "S1", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 101, + "volume": 5, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", - "session": "2026-01-05", + "tradeId": "W3", + "timestamp": "2026-01-05T14:31:00.000Z", + "session": "S1", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 99, + "volume": 8, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 4 } }, { "value": { - "closePartial": true, "intervalSeconds": 60, "sessionStarts": { - "2026-01-05": "2026-01-05T14:30:00.000Z", - "2026-01-06": "2026-01-06T14:30:00.000Z" + "S1": "2026-01-05T14:30:00.000Z" }, - "emptyBarPolicy": "omit" + "emptyBarPolicy": "omit", + "closePartial": true }, "elided": null } @@ -505,63 +504,59 @@ "output": [ { "barIndex": 0, - "session": "2026-01-05", + "session": "S1", "intervalIndex": 0, "startTime": "2026-01-05T14:30:00.000Z", "endTime": "2026-01-05T14:31:00.000Z", "firstTradeTime": "2026-01-05T14:30:00.000Z", - "lastTradeTime": "2026-01-05T14:30:54.000Z", - "open": 99.99, - "high": 100.06, - "low": 99.98, - "close": 100.05, - "volume": 1531, - "dollarValue": 153130.02, - "tickCount": 14 + "lastTradeTime": "2026-01-05T14:30:59.999Z", + "open": 100, + "high": 101, + "low": 100, + "close": 101, + "volume": 15, + "dollarValue": 1505, + "tickCount": 2 }, { "barIndex": 1, - "session": "2026-01-05", + "session": "S1", "intervalIndex": 1, "startTime": "2026-01-05T14:31:00.000Z", "endTime": "2026-01-05T14:32:00.000Z", - "firstTradeTime": "2026-01-05T14:31:01.000Z", - "lastTradeTime": "2026-01-05T14:31:58.000Z", - "open": 100.06, - "high": 100.13, - "low": 100.04, - "close": 100.13, - "volume": 1935, - "dollarValue": 193681.33, - "tickCount": 15 + "firstTradeTime": "2026-01-05T14:31:00.000Z", + "lastTradeTime": "2026-01-05T14:31:00.000Z", + "open": 99, + "high": 99, + "low": 99, + "close": 99, + "volume": 8, + "dollarValue": 792, + "tickCount": 1 }, { "barIndex": 2, - "session": "2026-01-05", - "intervalIndex": 2, - "startTime": "2026-01-05T14:32:00.000Z", - "endTime": "2026-01-05T14:33:00.000Z", - "firstTradeTime": "2026-01-05T14:32:06.000Z", - "lastTradeTime": "2026-01-05T14:32:55.000Z", - "open": 100.15, - "high": 100.18, - "low": 100.13, - "close": 100.16, - "volume": 1444, - "dollarValue": 144624.75, - "tickCount": 11 + "session": "S1", + "intervalIndex": 3, + "startTime": "2026-01-05T14:33:00.000Z", + "endTime": "2026-01-05T14:34:00.000Z", + "firstTradeTime": "2026-01-05T14:33:15.000Z", + "lastTradeTime": "2026-01-05T14:33:15.000Z", + "open": 102, + "high": 102, + "low": 102, + "close": 102, + "volume": 2, + "dollarValue": 204, + "tickCount": 1 } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 18 - }, - "outputShape": "array of 18 objects" + "outputElided": null, + "outputShape": "array of 3 objects" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -695,51 +690,51 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"targetTicks\":12})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A02.json", + "call": "constructBars([{\"tradeId\":\"E01\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":10,\"currency\":\"USD\"},{\"tradeId\":\"E02\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":101,\"volume\":20,\"currency\":\"USD\"},{\"tradeId\":\"E03\",\"timestamp\":\"2026-01-05T14:30:02.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99,\"volume\":15,\"currency\":\"USD\"}], {\"targetTicks\":3,\"closePartial\":true})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "E01", "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 10, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", + "tradeId": "E02", + "timestamp": "2026-01-05T14:30:01.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 101, + "volume": 20, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", + "tradeId": "E03", + "timestamp": "2026-01-05T14:30:02.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 99, + "volume": 15, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 7 } }, { "value": { - "closePartial": true, - "targetTicks": 12 + "targetTicks": 3, + "closePartial": true }, "elided": null } @@ -749,61 +744,57 @@ "barIndex": 0, "session": "2026-01-05", "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:30:45.000Z", - "lastTradeTime": "2026-01-05T14:30:45.000Z", - "open": 99.99, - "high": 100.06, - "low": 99.98, - "close": 100.06, - "volume": 1254, - "dollarValue": 125416.17, - "tickCount": 12, - "firstTradeId": "T0001", - "lastTradeId": "T0012" + "endTime": "2026-01-05T14:30:02.000Z", + "lastTradeTime": "2026-01-05T14:30:02.000Z", + "open": 100, + "high": 101, + "low": 99, + "close": 99, + "volume": 45, + "dollarValue": 4505, + "tickCount": 3, + "firstTradeId": "E01", + "lastTradeId": "E03" }, { "barIndex": 1, "session": "2026-01-05", - "startTime": "2026-01-05T14:30:46.000Z", - "endTime": "2026-01-05T14:31:43.000Z", - "lastTradeTime": "2026-01-05T14:31:43.000Z", - "open": 100.05, - "high": 100.12, - "low": 100.04, - "close": 100.12, - "volume": 1542, - "dollarValue": 154318.41, - "tickCount": 12, - "firstTradeId": "T0013", - "lastTradeId": "T0024" + "startTime": "2026-01-05T14:30:03.000Z", + "endTime": "2026-01-05T14:30:05.000Z", + "lastTradeTime": "2026-01-05T14:30:05.000Z", + "open": 100, + "high": 102, + "low": 100, + "close": 101, + "volume": 65, + "dollarValue": 6550, + "tickCount": 3, + "firstTradeId": "E04", + "lastTradeId": "E06" }, { "barIndex": 2, "session": "2026-01-05", - "startTime": "2026-01-05T14:31:48.000Z", - "endTime": "2026-01-05T14:32:33.000Z", - "lastTradeTime": "2026-01-05T14:32:33.000Z", - "open": 100.11, - "high": 100.18, - "low": 100.1, - "close": 100.18, - "volume": 1640, - "dollarValue": 164219.51, - "tickCount": 12, - "firstTradeId": "T0025", - "lastTradeId": "T0036" + "startTime": "2026-01-05T14:30:06.000Z", + "endTime": "2026-01-05T14:30:06.000Z", + "lastTradeTime": "2026-01-05T14:30:06.000Z", + "open": 103, + "high": 103, + "low": 103, + "close": 103, + "volume": 5, + "dollarValue": 515, + "tickCount": 1, + "firstTradeId": "E07", + "lastTradeId": "E07" } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 20 - }, - "outputShape": "array of 20 objects" + "outputElided": null, + "outputShape": "array of 3 objects" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -937,51 +928,51 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"targetVolume\":1300})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A03.json", + "call": "constructBars([{\"tradeId\":\"W001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":400,\"currency\":\"USD\"},{\"tradeId\":\"W002\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":101,\"volume\":350,\"currency\":\"USD\"},{\"tradeId\":\"W003\",\"timestamp\":\"2026-01-05T14:30:02.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99,\"volume\":500,\"currency\":\"USD\"}], {\"targetVolume\":1000,\"closePartial\":true})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W001", "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 400, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", + "tradeId": "W002", + "timestamp": "2026-01-05T14:30:01.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 101, + "volume": 350, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", + "tradeId": "W003", + "timestamp": "2026-01-05T14:30:02.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 99, + "volume": 500, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 6 } }, { "value": { - "closePartial": true, - "targetVolume": 1300 + "targetVolume": 1000, + "closePartial": true }, "elided": null } @@ -991,61 +982,57 @@ "barIndex": 0, "session": "2026-01-05", "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:30:46.000Z", - "lastTradeTime": "2026-01-05T14:30:46.000Z", - "open": 99.99, - "high": 100.06, - "low": 99.98, - "close": 100.05, - "volume": 1374, - "dollarValue": 137422.17, - "tickCount": 13, - "firstTradeId": "T0001", - "lastTradeId": "T0013" + "endTime": "2026-01-05T14:30:02.000Z", + "lastTradeTime": "2026-01-05T14:30:02.000Z", + "open": 100, + "high": 101, + "low": 99, + "close": 99, + "volume": 1250, + "dollarValue": 124850, + "tickCount": 3, + "firstTradeId": "W001", + "lastTradeId": "W003" }, { "barIndex": 1, "session": "2026-01-05", - "startTime": "2026-01-05T14:30:54.000Z", - "endTime": "2026-01-05T14:31:43.000Z", - "lastTradeTime": "2026-01-05T14:31:43.000Z", - "open": 100.05, - "high": 100.12, - "low": 100.04, - "close": 100.12, - "volume": 1422, - "dollarValue": 142312.41, - "tickCount": 11, - "firstTradeId": "T0014", - "lastTradeId": "T0024" + "startTime": "2026-01-05T14:30:03.000Z", + "endTime": "2026-01-05T14:30:04.000Z", + "lastTradeTime": "2026-01-05T14:30:04.000Z", + "open": 99.5, + "high": 100.5, + "low": 99.5, + "close": 100.5, + "volume": 1000, + "dollarValue": 99900, + "tickCount": 2, + "firstTradeId": "W004", + "lastTradeId": "W005" }, { "barIndex": 2, "session": "2026-01-05", - "startTime": "2026-01-05T14:31:48.000Z", - "endTime": "2026-01-05T14:32:24.000Z", - "lastTradeTime": "2026-01-05T14:32:24.000Z", - "open": 100.11, - "high": 100.15, - "low": 100.1, - "close": 100.15, - "volume": 1358, - "dollarValue": 135978.28, - "tickCount": 9, - "firstTradeId": "T0025", - "lastTradeId": "T0033" + "startTime": "2026-01-05T14:30:05.000Z", + "endTime": "2026-01-05T14:30:05.000Z", + "lastTradeTime": "2026-01-05T14:30:05.000Z", + "open": 101, + "high": 101, + "low": 101, + "close": 101, + "volume": 250, + "dollarValue": 25250, + "tickCount": 1, + "firstTradeId": "W006", + "lastTradeId": "W006" } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 22 - }, - "outputShape": "array of 22 objects" + "outputElided": null, + "outputShape": "array of 3 objects" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -1183,54 +1170,41 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"targetDollar\":140000,\"currency\":\"USD\",\"priceDecimals\":2,\"quantityDecimals\":0})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A04.json", + "call": "constructBars([{\"tradeId\":\"W1\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":40,\"currency\":\"USD\"},{\"tradeId\":\"W2\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":90,\"volume\":70,\"currency\":\"USD\"}], {\"targetDollar\":10000,\"currency\":\"USD\",\"priceDecimals\":2,\"quantityDecimals\":0,\"closePartial\":true})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W1", "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, - "currency": "USD" - }, - { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", - "session": "2026-01-05", - "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 100, + "volume": 40, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", + "tradeId": "W2", + "timestamp": "2026-01-05T14:30:01.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 90, + "volume": 70, "currency": "USD" } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 240 - } + "elided": null }, { "value": { - "closePartial": true, - "targetDollar": 140000, + "targetDollar": 10000, "currency": "USD", "priceDecimals": 2, - "quantityDecimals": 0 + "quantityDecimals": 0, + "closePartial": true }, "elided": null } @@ -1242,59 +1216,23 @@ "symbol": "SYNTH", "currency": "USD", "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:30:54.000Z", - "lastTradeTime": "2026-01-05T14:30:54.000Z", - "open": 99.99, - "high": 100.06, - "low": 99.98, - "close": 100.05, - "volume": 1531, - "dollarValue": 153130.02, - "targetDollar": 140000 - }, - { - "barIndex": 1, - "session": "2026-01-05", - "symbol": "SYNTH", - "currency": "USD", - "startTime": "2026-01-05T14:31:01.000Z", - "endTime": "2026-01-05T14:31:48.000Z", - "lastTradeTime": "2026-01-05T14:31:48.000Z", - "open": 100.06, - "high": 100.12, - "low": 100.04, - "close": 100.11, - "volume": 1469, - "dollarValue": 147027, - "targetDollar": 140000 - }, - { - "barIndex": 2, - "session": "2026-01-05", - "symbol": "SYNTH", - "currency": "USD", - "startTime": "2026-01-05T14:31:52.000Z", - "endTime": "2026-01-05T14:32:33.000Z", - "lastTradeTime": "2026-01-05T14:32:33.000Z", - "open": 100.11, - "high": 100.18, - "low": 100.1, - "close": 100.18, - "volume": 1436, - "dollarValue": 143797.07, - "targetDollar": 140000 + "endTime": "2026-01-05T14:30:01.000Z", + "lastTradeTime": "2026-01-05T14:30:01.000Z", + "open": 100, + "high": 100, + "low": 90, + "close": 90, + "volume": 110, + "dollarValue": 10300, + "targetDollar": 10000 } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 21 - }, - "outputShape": "array of 21 objects" + "outputElided": null, + "outputShape": "array of 1 object" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -1428,56 +1366,56 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":24,\"initialExpectedTickImbalance\":0.25,\"alphaTicks\":0.2,\"alphaTickImbalance\":0.2,\"thresholdFloor\":4,\"thresholdMultiplier\":1})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A05.json", + "call": "constructBars([{\"tradeId\":\"W1\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":10,\"currency\":\"USD\"},{\"tradeId\":\"W2\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":10,\"currency\":\"USD\"},{\"tradeId\":\"W3\",\"timestamp\":\"2026-01-05T14:30:02.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100.1,\"volume\":10,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":8,\"initialExpectedTickImbalance\":0.5,\"alphaTicks\":0.25,\"alphaTickImbalance\":0.5,\"thresholdFloor\":3,\"thresholdMultiplier\":1})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W1", "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 10, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", + "tradeId": "W2", + "timestamp": "2026-01-05T14:30:01.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 100, + "volume": 10, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", + "tradeId": "W3", + "timestamp": "2026-01-05T14:30:02.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 100.1, + "volume": 10, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 6 } }, { "value": { "closePartial": true, "initialTickSign": 1, - "initialExpectedTicks": 24, - "initialExpectedTickImbalance": 0.25, - "alphaTicks": 0.2, - "alphaTickImbalance": 0.2, - "thresholdFloor": 4, + "initialExpectedTicks": 8, + "initialExpectedTickImbalance": 0.5, + "alphaTicks": 0.25, + "alphaTickImbalance": 0.5, + "thresholdFloor": 3, "thresholdMultiplier": 1 }, "elided": null @@ -1488,61 +1426,25 @@ "barIndex": 0, "session": "2026-01-05", "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:33:18.000Z", - "lastTradeTime": "2026-01-05T14:33:18.000Z", - "open": 99.99, - "high": 100.23, - "low": 99.98, - "close": 100.23, - "volume": 5561, - "dollarValue": 556664.98, - "tickCount": 46, - "firstTradeId": "T0001", - "lastTradeId": "T0046" - }, - { - "barIndex": 1, - "session": "2026-01-05", - "startTime": "2026-01-05T14:33:25.000Z", - "endTime": "2026-01-05T14:34:12.000Z", - "lastTradeTime": "2026-01-05T14:34:12.000Z", - "open": 100.22, - "high": 100.35, - "low": 100.22, - "close": 100.35, - "volume": 1353, - "dollarValue": 135695.7, - "tickCount": 11, - "firstTradeId": "T0047", - "lastTradeId": "T0057" - }, - { - "barIndex": 2, - "session": "2026-01-05", - "startTime": "2026-01-05T14:34:16.000Z", - "endTime": "2026-01-05T14:34:58.000Z", - "lastTradeTime": "2026-01-05T14:34:58.000Z", - "open": 100.37, - "high": 100.49, - "low": 100.36, - "close": 100.49, - "volume": 1712, - "dollarValue": 171902.93, - "tickCount": 12, - "firstTradeId": "T0058", - "lastTradeId": "T0069" + "endTime": "2026-01-05T14:30:05.000Z", + "lastTradeTime": "2026-01-05T14:30:05.000Z", + "open": 100, + "high": 100.15, + "low": 100, + "close": 100.15, + "volume": 60, + "dollarValue": 6004, + "tickCount": 6, + "firstTradeId": "W1", + "lastTradeId": "W6" } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 12 - }, - "outputShape": "array of 12 objects" + "outputElided": null, + "outputShape": "array of 1 object" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -1676,56 +1578,56 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":16,\"initialExpectedSignedVolume\":35,\"alphaTicks\":0.2,\"alphaSignedVolume\":0.2,\"thresholdFloorShares\":300,\"thresholdScale\":1})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A06.json", + "call": "constructBars([{\"tradeId\":\"W01\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":60,\"currency\":\"USD\"},{\"tradeId\":\"W02\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":40,\"currency\":\"USD\"},{\"tradeId\":\"W03\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":70,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":4,\"initialExpectedSignedVolume\":50,\"alphaTicks\":0.25,\"alphaSignedVolume\":0.25,\"thresholdFloorShares\":120,\"thresholdScale\":1})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W01", "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 60, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", + "tradeId": "W02", + "timestamp": "2026-01-05T14:30:00.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 100, + "volume": 40, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", + "tradeId": "W03", + "timestamp": "2026-01-05T14:30:01.000Z", "session": "2026-01-05", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 99.99, + "volume": 70, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 8 } }, { "value": { "closePartial": true, "initialTickSign": 1, - "initialExpectedTicks": 16, - "initialExpectedSignedVolume": 35, - "alphaTicks": 0.2, - "alphaSignedVolume": 0.2, - "thresholdFloorShares": 300, + "initialExpectedTicks": 4, + "initialExpectedSignedVolume": 50, + "alphaTicks": 0.25, + "alphaSignedVolume": 0.25, + "thresholdFloorShares": 120, "thresholdScale": 1 }, "elided": null @@ -1736,61 +1638,41 @@ "barIndex": 0, "session": "2026-01-05", "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:33:09.000Z", - "open": 99.99, - "high": 100.21, - "low": 99.98, - "close": 100.21, - "volume": 5436, - "dollarValue": 544137.11, - "tickCount": 44, - "firstTradeId": "T0001", - "lastTradeId": "T0044", + "endTime": "2026-01-05T14:30:04.000Z", + "open": 100, + "high": 100, + "low": 99.97, + "close": 99.97, + "volume": 405, + "dollarValue": 40493.65, + "tickCount": 6, + "firstTradeId": "W01", + "lastTradeId": "W06", "closeReason": "threshold" }, { "barIndex": 1, "session": "2026-01-05", - "startTime": "2026-01-05T14:33:10.000Z", - "endTime": "2026-01-05T14:34:01.000Z", - "open": 100.21, - "high": 100.34, - "low": 100.21, - "close": 100.34, - "volume": 1259, - "dollarValue": 126246.92, - "tickCount": 11, - "firstTradeId": "T0045", - "lastTradeId": "T0055", - "closeReason": "threshold" - }, - { - "barIndex": 2, - "session": "2026-01-05", - "startTime": "2026-01-05T14:34:07.000Z", - "endTime": "2026-01-05T14:35:06.000Z", - "open": 100.35, - "high": 100.51, - "low": 100.35, - "close": 100.51, - "volume": 2000, - "dollarValue": 200814.77, - "tickCount": 15, - "firstTradeId": "T0056", - "lastTradeId": "T0070", + "startTime": "2026-01-05T14:30:05.000Z", + "endTime": "2026-01-05T14:30:06.000Z", + "open": 99.98, + "high": 99.99, + "low": 99.98, + "close": 99.99, + "volume": 135, + "dollarValue": 13497.85, + "tickCount": 2, + "firstTradeId": "W07", + "lastTradeId": "W08", "closeReason": "threshold" } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 18 - }, - "outputShape": "array of 18 objects" + "outputElided": null, + "outputShape": "array of 2 objects" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -1924,56 +1806,56 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "constructBars([{\"tradeId\":\"T0001\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":36,\"currency\":\"USD\"},{\"tradeId\":\"T0002\",\"timestamp\":\"2026-01-05T14:30:04.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":99.99,\"volume\":73,\"currency\":\"USD\"},{\"tradeId\":\"T0003\",\"timestamp\":\"2026-01-05T14:30:07.000Z\",\"session\":\"2026-01-05\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":110,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":20,\"initialBuyProbability\":0.6,\"alphaTicks\":0.2,\"alphaBuyProbability\":0.2,\"thresholdFloorTicks\":4,\"thresholdMultiplier\":1})", + "origin": "fixture", + "verified": true, + "source": "fixture:D01-F01-A07.json", + "call": "constructBars([{\"tradeId\":\"W01\",\"timestamp\":\"2026-01-05T14:30:00.000Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":10,\"currency\":\"USD\"},{\"tradeId\":\"W02\",\"timestamp\":\"2026-01-05T14:30:01.000Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":100,\"volume\":20,\"currency\":\"USD\"},{\"tradeId\":\"W03\",\"timestamp\":\"2026-01-05T14:30:02.000Z\",\"session\":\"S1\",\"symbol\":\"SYNTH\",\"price\":99.9,\"volume\":15,\"currency\":\"USD\"}], {\"closePartial\":true,\"initialTickSign\":1,\"initialExpectedTicks\":4,\"initialBuyProbability\":0.625,\"alphaTicks\":0.5,\"alphaBuyProbability\":0.5,\"thresholdFloorTicks\":2,\"thresholdMultiplier\":1})", "args": [ { "value": [ { - "tradeId": "T0001", + "tradeId": "W01", "timestamp": "2026-01-05T14:30:00.000Z", - "session": "2026-01-05", + "session": "S1", "symbol": "SYNTH", - "price": 99.99, - "volume": 36, + "price": 100, + "volume": 10, "currency": "USD" }, { - "tradeId": "T0002", - "timestamp": "2026-01-05T14:30:04.000Z", - "session": "2026-01-05", + "tradeId": "W02", + "timestamp": "2026-01-05T14:30:01.000Z", + "session": "S1", "symbol": "SYNTH", - "price": 99.99, - "volume": 73, + "price": 100, + "volume": 20, "currency": "USD" }, { - "tradeId": "T0003", - "timestamp": "2026-01-05T14:30:07.000Z", - "session": "2026-01-05", + "tradeId": "W03", + "timestamp": "2026-01-05T14:30:02.000Z", + "session": "S1", "symbol": "SYNTH", - "price": 100, - "volume": 110, + "price": 99.9, + "volume": 15, "currency": "USD" } ], "elided": { "kind": "array", "shown": 3, - "total": 240 + "total": 8 } }, { "value": { "closePartial": true, "initialTickSign": 1, - "initialExpectedTicks": 20, - "initialBuyProbability": 0.6, - "alphaTicks": 0.2, - "alphaBuyProbability": 0.2, - "thresholdFloorTicks": 4, + "initialExpectedTicks": 4, + "initialBuyProbability": 0.625, + "alphaTicks": 0.5, + "alphaBuyProbability": 0.5, + "thresholdFloorTicks": 2, "thresholdMultiplier": 1 }, "elided": null @@ -1981,64 +1863,34 @@ ], "output": [ { - "barIndex": 0, - "session": "2026-01-05", - "startTime": "2026-01-05T14:30:00.000Z", - "endTime": "2026-01-05T14:31:22.000Z", - "lastTradeTime": "2026-01-05T14:31:22.000Z", - "open": 99.99, - "high": 100.09, - "low": 99.98, - "close": 100.09, - "volume": 2406, - "dollarValue": 240695.03, - "tickCount": 21, - "firstTradeId": "T0001", - "lastTradeId": "T0021" - }, - { - "barIndex": 1, - "session": "2026-01-05", - "startTime": "2026-01-05T14:31:30.000Z", - "endTime": "2026-01-05T14:33:10.000Z", - "lastTradeTime": "2026-01-05T14:33:10.000Z", - "open": 100.07, - "high": 100.21, - "low": 100.07, - "close": 100.21, - "volume": 3074, - "dollarValue": 307851.32, - "tickCount": 24, - "firstTradeId": "T0022", - "lastTradeId": "T0045" + "firstTradeId": "W01", + "lastTradeId": "W04", + "tickCount": 4, + "buyTicks": 3, + "sellTicks": 1, + "dominantSide": "buy", + "thresholdTicks": 2.5, + "overshootTicks": 0.5, + "closeReason": "threshold" }, { - "barIndex": 2, - "session": "2026-01-05", - "startTime": "2026-01-05T14:33:18.000Z", - "endTime": "2026-01-05T14:34:22.000Z", - "lastTradeTime": "2026-01-05T14:34:22.000Z", - "open": 100.23, - "high": 100.41, - "low": 100.22, - "close": 100.41, - "volume": 2306, - "dollarValue": 231336.47, - "tickCount": 16, - "firstTradeId": "T0046", - "lastTradeId": "T0061" + "firstTradeId": "W05", + "lastTradeId": "W08", + "tickCount": 4, + "buyTicks": 1, + "sellTicks": 3, + "dominantSide": "sell", + "thresholdTicks": 2.75, + "overshootTicks": 0.25, + "closeReason": "threshold" } ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 14 - }, - "outputShape": "array of 14 objects" + "outputElided": null, + "outputShape": "array of 2 objects" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -8630,9 +8482,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F01-A02.json", "call": "calculate({\"targetBasisAt\":\"2020-08-30T23:59:59Z\",\"knowledgeAt\":\"2020-09-02T00:00:00Z\",\"roundDecimalPlaces\":6,\"observations\":[{\"timestamp\":\"2020-08-28T20:00:00Z\",\"price\":120,\"volume\":1000,\"sharesOutstanding\":1000000},{\"timestamp\":\"2020-08-31T00:00:00Z\",\"price\":30,\"volume\":4000,\"sharesOutstanding\":4000000},{\"timestamp\":\"2020-09-01T00:00:00Z\",\"price\":31,\"volume\":3600,\"sharesOutstanding\":4000000}],\"eventRevisions\":[{\"eventId\":\"SYNTH-SPLIT-2020\",\"revisionId\":\"SYNTH-SPLIT-2020-R1\",\"supersedesRevisionId\":null,\"publishedAt\":\"2020-07-30T20:30:00Z\",\"effectiveAt\":\"2020-08-31T00:00:00Z\",\"newShares\":4,\"oldShares\":1,\"status\":\"active\",\"sourceId\":\"synthetic-fixture\"}]})", "args": [ { @@ -8750,8 +8602,8 @@ "outputShape": "object with 4 fields: basis, selectedRevisions, observations, warnings" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -8885,9 +8737,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F01-A03.json", "call": "calculate({\"asOf\":\"2026-01-09T23:00:00Z\",\"returnVariant\":\"gross\",\"priceCurrency\":\"USD\",\"anchorBasis\":\"latest_raw_close\",\"specialDistributionPolicy\":\"exclude\",\"observations\":[{\"date\":\"2026-01-02\",\"close\":100,\"availableAt\":\"2026-01-02T21:01:00Z\"},{\"date\":\"2026-01-05\",\"close\":102,\"availableAt\":\"2026-01-05T21:01:00Z\"},{\"date\":\"2026-01-06\",\"close\":99,\"availableAt\":\"2026-01-06T21:01:00Z\"}],\"eventRevisions\":[{\"eventId\":\"SYNTH-DIV-A\",\"revision\":1,\"status\":\"confirmed\",\"classification\":\"ordinary\",\"exDate\":\"2026-01-06\",\"grossDividend\":2.5,\"dividendCurrency\":\"USD\",\"withholdingRate\":0.15,\"fxRateToPriceCurrency\":1,\"fxObservedAt\":null,\"availableAt\":\"2026-01-05T15:00:00Z\",\"sourceId\":\"SYNTHETIC-ACTION-FEED\"},{\"eventId\":\"SYNTH-DIV-A\",\"revision\":2,\"status\":\"confirmed\",\"classification\":\"ordinary\",\"exDate\":\"2026-01-06\",\"grossDividend\":3,\"dividendCurrency\":\"USD\",\"withholdingRate\":0.15,\"fxRateToPriceCurrency\":1,\"fxObservedAt\":null,\"availableAt\":\"2026-01-05T18:00:00Z\",\"sourceId\":\"SYNTHETIC-ACTION-FEED\"},{\"eventId\":\"SYNTH-SPECIAL-B\",\"revision\":1,\"status\":\"confirmed\",\"classification\":\"special\",\"exDate\":\"2026-01-08\",\"grossDividend\":3,\"dividendCurrency\":\"USD\",\"withholdingRate\":0.15,\"fxRateToPriceCurrency\":1,\"fxObservedAt\":null,\"availableAt\":\"2026-01-07T18:00:00Z\",\"sourceId\":\"SYNTHETIC-ACTION-FEED\"}]})", "args": [ { @@ -9051,8 +8903,8 @@ "outputShape": "object with 11 fields: methodology, returnVariant, priceCurrency, asOf, anchor, adjustedPrices, cumulativeFactors, eventAdjustments, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -9186,9 +9038,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F01-A04.json", "call": "calculate({\"crspConvention\":\"CRSPAccess-ts_print-cumfacpr-archived\",\"crspSourceVersion\":\"Archived CRSP Stock and Index Data Description Guide convention; synthetic extract v1\",\"packageSecurityKey\":\"SYNTHETIC-SECURITY-001\",\"crspBaseDate\":\"2024-06-10\",\"crspGapPolicy\":\"stop-at-unknown-exchange\",\"roundingDecimals\":6,\"crspFactorEvents\":[{\"crspExdt\":\"2024-06-10\",\"crspFacpr\":1,\"syntheticLabel\":\"Synthetic 2-for-1 split-like CRSP event\"}],\"records\":[{\"date\":\"2024-06-06\",\"crspPrc\":120,\"crspCumfacpr\":0.5,\"crspPriceKind\":\"trade\",\"coverageStatus\":\"observed\"},{\"date\":\"2024-06-07\",\"crspPrc\":-123,\"crspCumfacpr\":0.5,\"crspPriceKind\":\"bid_ask_average\",\"coverageStatus\":\"observed\"},{\"date\":\"2024-06-10\",\"crspPrc\":60,\"crspCumfacpr\":1,\"crspPriceKind\":\"trade\",\"coverageStatus\":\"observed\"}]})", "args": [ { @@ -9291,8 +9143,8 @@ "outputShape": "object with 10 fields: crspConvention, crspSourceVersion, packageSecurityKey, crspBaseDate, crspGapPolicy, crspPriceFormula, crspFactorEvents, crspFactorChangeDates, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -9420,9 +9272,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F01-A05.json", "call": "calculate({\"schemaVersion\":\"CRSP_US_STOCK_CIZ_2_0\",\"sourceRelease\":\"synthetic-ciz-2.0-fixture-v1\",\"crspBasisDate\":\"2024-09-05\",\"extractCoverage\":\"full_history\",\"records\":[{\"packageSecurityKey\":\"SYNTHETIC-CRSP-CIZ-001\",\"date\":\"2024-08-28\",\"frequency\":\"daily\",\"crspFactorField\":\"DlyCumFacShr\",\"crspCumulativeShareFactor\":4,\"crspFactorStatus\":\"observed\",\"rawSharesOutstandingThousands\":250,\"rawVolumeShares\":100},{\"packageSecurityKey\":\"SYNTHETIC-CRSP-CIZ-001\",\"date\":\"2024-08-29\",\"frequency\":\"daily\",\"crspFactorField\":\"DlyCumFacShr\",\"crspCumulativeShareFactor\":4,\"crspFactorStatus\":\"observed\",\"rawSharesOutstandingThousands\":250,\"rawVolumeShares\":125},{\"packageSecurityKey\":\"SYNTHETIC-CRSP-CIZ-001\",\"date\":\"2024-08-30\",\"frequency\":\"daily\",\"crspFactorField\":\"DlyCumFacShr\",\"crspCumulativeShareFactor\":1,\"crspFactorStatus\":\"observed\",\"rawSharesOutstandingThousands\":1000,\"rawVolumeShares\":460}]})", "args": [ { @@ -9468,69 +9320,27 @@ } ], "output": { - "schemaVersion": "CRSP_US_STOCK_CIZ_2_0", - "sourceRelease": "synthetic-ciz-2.0-fixture-v1", - "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", - "crspBasisDate": "2024-09-05", - "extractCoverage": "full_history", - "roundingDigits": 12, "rows": [ { - "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", - "date": "2024-08-28", - "frequency": "daily", - "crspFactorField": "DlyCumFacShr", - "crspCumulativeShareFactor": 4, - "crspFactorStatus": "observed", - "crspMthFacShrFlg": null, - "crspMonthlyShareFactorState": null, - "crspSharesStatus": "computed_crsp", "crspAdjustedSharesOutstandingThousands": 1000, - "crspSharesRoundTripResidual": 0, - "crspVolumeStatus": "computed_crsp", - "crspAdjustedVolumeShares": 400, - "crspVolumeRoundTripResidual": 0 + "crspAdjustedVolumeShares": 400 }, { - "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", - "date": "2024-08-29", - "frequency": "daily", - "crspFactorField": "DlyCumFacShr", - "crspCumulativeShareFactor": 4, - "crspFactorStatus": "observed", - "crspMthFacShrFlg": null, - "crspMonthlyShareFactorState": null, - "crspSharesStatus": "computed_crsp", "crspAdjustedSharesOutstandingThousands": 1000, - "crspSharesRoundTripResidual": 0, - "crspVolumeStatus": "computed_crsp", - "crspAdjustedVolumeShares": 500, - "crspVolumeRoundTripResidual": 0 + "crspAdjustedVolumeShares": 500 }, { - "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", - "date": "2024-08-30", - "frequency": "daily", - "crspFactorField": "DlyCumFacShr", - "crspCumulativeShareFactor": 1, - "crspFactorStatus": "observed", - "crspMthFacShrFlg": null, - "crspMonthlyShareFactorState": null, - "crspSharesStatus": "computed_crsp", "crspAdjustedSharesOutstandingThousands": 1000, - "crspSharesRoundTripResidual": 0, - "crspVolumeStatus": "computed_crsp", - "crspAdjustedVolumeShares": 460, - "crspVolumeRoundTripResidual": 0 + "crspAdjustedVolumeShares": 460 } ] }, "outputElided": null, - "outputShape": "object with 7 fields: schemaVersion, sourceRelease, packageSecurityKey, crspBasisDate, extractCoverage, roundingDigits, rows" + "outputShape": "object with 1 field: rows" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -9662,9 +9472,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F02-A01.json", "call": "calculate({\"asOf\":\"2024-05-24T00:00:00Z\",\"revisions\":[{\"eventId\":\"NG-2024-RIGHTS\",\"revisionId\":\"NG-PROSPECTUS-2024-05-23\",\"revisionSequence\":1,\"availableAt\":\"2024-05-23T23:59:59Z\",\"status\":\"confirmed\",\"recordAt\":\"2024-05-20T18:00:00+01:00\",\"exAt\":\"2024-05-24T08:00:00+01:00\",\"rightsTradingStartAt\":\"2024-05-24T08:00:00+01:00\",\"paymentDeadlineAt\":\"2024-06-10T11:00:00+01:00\",\"newSharesTradeAt\":\"2024-06-12T08:00:00+01:00\",\"terms\":{\"oldShares\":24,\"newShares\":7,\"rawCumRightsPrice\":1127.5,\"cashDisadvantage\":39.12,\"quoteCurrency\":\"GBp\",\"subscriptionPrice\":645,\"subscriptionCurrency\":\"GBp\",\"fxQuotePerSubscription\":1,\"feesPerNewShareQuote\":0,\"taxesPerNewShareQuote\":0,\"holdingOldShares\":100,\"outOfMoneyPolicy\":\"reject\",\"priceSourceId\":\"NG-PROSPECTUS-P52-LSE-DOL-QUOTE\",\"priceDate\":\"2024-05-22\"}}]})", "args": [ { @@ -9732,8 +9542,8 @@ "outputShape": "object with 15 fields: eventId, revisionId, availableAt, quoteCurrency, referencePrice, subscriptionCashQuote, terp, valuePerOldShare, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -9874,9 +9684,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F02-A02.json", "call": "calculate({\"asOf\":\"2026-06-02T20:00:00Z\",\"revisions\":[{\"eventId\":\"SYNTH-SPIN-2026\",\"revisionId\":\"SYNTH-SPIN-2026-R1\",\"revisionSequence\":1,\"availableAt\":\"2026-05-21T12:00:00Z\",\"status\":\"confirmed\",\"quoteCurrency\":\"USD\",\"recordAt\":\"2026-05-20T20:00:00Z\",\"whenIssuedStartAt\":\"2026-05-27T13:30:00Z\",\"distributionAt\":\"2026-06-01T12:00:00Z\",\"parentExAt\":\"2026-06-01T13:30:00Z\",\"childRegularWayAt\":\"2026-06-01T13:30:00Z\",\"unavailableChildPricePolicy\":\"pending\",\"parentCumObservation\":{\"price\":120,\"currency\":\"USD\",\"priceType\":\"regular_way_cum_distribution\",\"observedAt\":\"2026-05-29T20:00:00Z\",\"availableAt\":\"2026-05-29T20:00:05Z\",\"sourceId\":\"SYNTH-PARENT-CLOSE\"},\"parentExObservation\":{\"price\":108,\"currency\":\"USD\",\"priceType\":\"regular_way_ex_distribution\",\"observedAt\":\"2026-06-01T20:00:00Z\",\"availableAt\":\"2026-06-01T20:00:05Z\",\"sourceId\":\"SYNTH-PARENT-EX-CLOSE\"}}]})", "args": [ { @@ -9983,8 +9793,8 @@ "outputShape": "object with 16 fields: eventId, revisionId, availableAt, status, quoteCurrency, parentCumPrice, distributedValuePerParent, theoreticalParentExReference, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -10120,9 +9930,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F02-A03.json", "call": "calculate({\"method\":\"backward_post_event_same_class\",\"securityId\":\"SYNTH-CLASS-A\",\"asOf\":\"2026-02-04T12:00:00Z\",\"anchorAt\":\"2026-02-03T21:00:00Z\",\"volumePolicy\":\"adjust_to_anchor_basis\",\"events\":[{\"eventId\":\"SD-001\",\"subjectSecurityId\":\"SYNTH-CLASS-A\",\"distributedSecurityId\":\"SYNTH-CLASS-A\",\"exAt\":\"2026-01-15T14:30:00Z\",\"recordDate\":\"2026-01-15\",\"payableDate\":\"2026-01-20\",\"revisions\":[{\"publishedAt\":\"2026-01-05T18:00:00Z\",\"status\":\"confirmed\",\"rateNewSharesPerOld\":0.1,\"sourceId\":\"SYNTH-NOTICE-1\"}]},{\"eventId\":\"SD-002\",\"subjectSecurityId\":\"SYNTH-CLASS-A\",\"distributedSecurityId\":\"SYNTH-CLASS-A\",\"exAt\":\"2026-02-03T14:30:00Z\",\"recordDate\":\"2026-01-30\",\"payableDate\":\"2026-02-02\",\"revisions\":[{\"publishedAt\":\"2026-01-20T18:00:00Z\",\"status\":\"confirmed\",\"rateNewSharesPerOld\":0.15,\"sourceId\":\"SYNTH-NOTICE-2-R1\"},{\"publishedAt\":\"2026-01-25T18:00:00Z\",\"status\":\"confirmed\",\"rateNewSharesPerOld\":0.2,\"sourceId\":\"SYNTH-NOTICE-2-R2\"}]}],\"observations\":[{\"at\":\"2026-01-02T21:00:00Z\",\"availableAt\":\"2026-01-02T21:00:05Z\",\"sourceId\":\"SYNTH-CLOSES-V1\",\"price\":50,\"shares\":200,\"volume\":80},{\"at\":\"2026-02-02T21:00:00Z\",\"availableAt\":\"2026-02-02T21:00:05Z\",\"sourceId\":\"SYNTH-CLOSES-V1\",\"price\":55,\"shares\":220,\"volume\":90},{\"at\":\"2026-02-03T14:30:00Z\",\"availableAt\":\"2026-02-03T14:30:05Z\",\"sourceId\":\"SYNTH-CLOSES-V1\",\"price\":46,\"shares\":264,\"volume\":100}]})", "args": [ { @@ -10283,8 +10093,8 @@ "outputShape": "object with 9 fields: method, securityId, asOf, anchorAt, volumePolicy, appliedEvents, unavailableEventIds, cancelledEventIds, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -10423,10 +10233,134 @@ "space": "O(1)" } }, - "example": null, + "example": { + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F02-A04.json", + "call": "calculate({\"securityId\":\"SYNTHETIC-SECURITY-004\",\"eventId\":\"SYNTHETIC-SPECIAL-DIVIDEND-2026-01\",\"asOf\":\"2026-03-16T20:10:00Z\",\"methodology\":{\"id\":\"SYNTHETIC-NET-RETURN-POLICY\",\"version\":\"1.0\",\"sourceId\":\"SYNTHETIC-METHODOLOGY-NOTE\",\"classificationMode\":\"source-designated\",\"priceAdjustmentCashBasis\":\"net\",\"referenceAnchor\":\"previous-session-official-close\",\"outputDecimals\":8},\"eventRevisions\":[{\"revisionId\":\"R1\",\"securityId\":\"SYNTHETIC-SECURITY-004\",\"eventId\":\"SYNTHETIC-SPECIAL-DIVIDEND-2026-01\",\"status\":\"announced\",\"issuerClassification\":\"special\",\"grossAmount\":15,\"currency\":\"EUR\",\"announcedAt\":\"2026-02-02T12:00:00Z\",\"availableAt\":\"2026-02-02T12:05:00Z\",\"exAt\":\"2026-03-16T13:30:00Z\",\"paymentAt\":\"2026-03-20T12:00:00Z\",\"actionOrder\":20,\"amountBasisOrder\":0,\"sourceId\":\"SYNTHETIC-ISSUER-NOTICE-R1\"},{\"revisionId\":\"R2\",\"securityId\":\"SYNTHETIC-SECURITY-004\",\"eventId\":\"SYNTHETIC-SPECIAL-DIVIDEND-2026-01\",\"status\":\"announced\",\"issuerClassification\":\"special\",\"grossAmount\":16,\"currency\":\"EUR\",\"announcedAt\":\"2026-02-05T14:00:00Z\",\"availableAt\":\"2026-02-05T14:10:00Z\",\"exAt\":\"2026-03-16T13:30:00Z\",\"paymentAt\":\"2026-03-20T12:00:00Z\",\"actionOrder\":20,\"amountBasisOrder\":0,\"sourceId\":\"SYNTHETIC-ISSUER-NOTICE-R2\"}],\"referencePrice\":{\"value\":100,\"currency\":\"USD\",\"anchorType\":\"previous-session-official-close\",\"anchorAt\":\"2026-03-13T20:00:00Z\",\"observedAt\":\"2026-03-13T20:00:00Z\",\"availableAt\":\"2026-03-13T20:00:05Z\",\"sourceId\":\"SYNTHETIC-OFFICIAL-CLOSE\"},\"precedingActions\":[{\"actionId\":\"SYNTHETIC-2-FOR-1-SPLIT\",\"actionOrder\":10,\"priceFactor\":0.5,\"perShareAmountFactor\":0.5,\"effectiveAt\":\"2026-03-16T13:30:00Z\",\"observedAt\":\"2026-02-01T10:00:00Z\",\"availableAt\":\"2026-02-01T10:05:00Z\",\"sourceId\":\"SYNTHETIC-ACTION-SOURCE\"}],\"fxRate\":{\"baseCurrency\":\"EUR\",\"quoteCurrency\":\"USD\",\"rate\":1.1,\"observedAt\":\"2026-03-13T20:00:00Z\",\"availableAt\":\"2026-03-13T20:00:05Z\",\"sourceId\":\"SYNTHETIC-FX-CLOSE\"},\"taxProfile\":{\"withholdingRate\":0.25,\"jurisdiction\":\"SYNTHETIC-JURISDICTION\",\"investorCategory\":\"SYNTHETIC-NONRESIDENT\",\"observedAt\":\"2026-01-05T09:00:00Z\",\"availableAt\":\"2026-01-05T09:05:00Z\",\"sourceId\":\"SYNTHETIC-TAX-RULE\"},\"exPriceObservation\":{\"value\":43.75,\"currency\":\"USD\",\"observedAt\":\"2026-03-16T20:00:00Z\",\"availableAt\":\"2026-03-16T20:00:05Z\",\"sourceId\":\"SYNTHETIC-EX-CLOSE\"}})", + "args": [ + { + "value": { + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "asOf": "2026-03-16T20:10:00Z", + "methodology": { + "id": "SYNTHETIC-NET-RETURN-POLICY", + "version": "1.0", + "sourceId": "SYNTHETIC-METHODOLOGY-NOTE", + "classificationMode": "source-designated", + "priceAdjustmentCashBasis": "net", + "referenceAnchor": "previous-session-official-close", + "outputDecimals": 8 + }, + "eventRevisions": [ + { + "revisionId": "R1", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 15, + "currency": "EUR", + "announcedAt": "2026-02-02T12:00:00Z", + "availableAt": "2026-02-02T12:05:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R1" + }, + { + "revisionId": "R2", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 16, + "currency": "EUR", + "announcedAt": "2026-02-05T14:00:00Z", + "availableAt": "2026-02-05T14:10:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R2" + } + ], + "referencePrice": { + "value": 100, + "currency": "USD", + "anchorType": "previous-session-official-close", + "anchorAt": "2026-03-13T20:00:00Z", + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-OFFICIAL-CLOSE" + }, + "precedingActions": [ + { + "actionId": "SYNTHETIC-2-FOR-1-SPLIT", + "actionOrder": 10, + "priceFactor": 0.5, + "perShareAmountFactor": 0.5, + "effectiveAt": "2026-03-16T13:30:00Z", + "observedAt": "2026-02-01T10:00:00Z", + "availableAt": "2026-02-01T10:05:00Z", + "sourceId": "SYNTHETIC-ACTION-SOURCE" + } + ], + "fxRate": { + "baseCurrency": "EUR", + "quoteCurrency": "USD", + "rate": 1.1, + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-FX-CLOSE" + }, + "taxProfile": { + "withholdingRate": 0.25, + "jurisdiction": "SYNTHETIC-JURISDICTION", + "investorCategory": "SYNTHETIC-NONRESIDENT", + "observedAt": "2026-01-05T09:00:00Z", + "availableAt": "2026-01-05T09:05:00Z", + "sourceId": "SYNTHETIC-TAX-RULE" + }, + "exPriceObservation": { + "value": 43.75, + "currency": "USD", + "observedAt": "2026-03-16T20:00:00Z", + "availableAt": "2026-03-16T20:00:05Z", + "sourceId": "SYNTHETIC-EX-CLOSE" + } + }, + "elided": null + } + ], + "output": { + "eventState": "effective", + "selectedRevisionId": "R2", + "classificationDecision": "special", + "classificationReason": "source designation: special", + "adjustmentApplied": true, + "referencePriceOnEventBasis": 50, + "grossDividendOnEventBasis": 8.8, + "netDividendOnEventBasis": 6.6, + "adjustmentCashAmount": 6.6, + "theoreticalExPrice": 43.4, + "adjustmentFactor": 0.868, + "grossDistributionYield": 0.176, + "methodologyId": "SYNTHETIC-NET-RETURN-POLICY", + "methodologyVersion": "1.0" + }, + "outputElided": { + "kind": "object", + "shown": 14, + "total": 16 + }, + "outputShape": "object with 16 fields: eventState, selectedRevisionId, classificationDecision, classificationReason, adjustmentApplied, referencePriceOnEventBasis, grossDividendOnEventBasis, netDividendOnEventBasis, …" + }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -10548,9 +10482,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F02-A05.json", "call": "calculate({\"asOf\":\"2025-02-03T21:05:00Z\",\"revisions\":[{\"eventId\":\"SYN-ROC-2025-001\",\"revisionId\":\"SYN-ANNOUNCEMENT-R1\",\"revisionSequence\":1,\"observedAt\":\"2025-01-20T14:00:00Z\",\"availableAt\":\"2025-01-20T14:02:00Z\",\"sourceId\":\"SYN-ISSUER-NOTICE\",\"status\":\"confirmed\",\"exAt\":\"2025-02-03T14:30:00Z\",\"sameDayOrdering\":{\"sequence\":1,\"priorEventIds\":[]},\"terms\":{\"eventCurrency\":\"USD\",\"grossCapitalReturnPerShare\":\"2.00000000\",\"withholdingPerShare\":\"0.10000000\",\"feesPerShare\":\"0.02000000\"}}],\"referenceObservation\":{\"price\":\"25.00000000\",\"currency\":\"USD\",\"observedAt\":\"2025-01-31T21:00:00Z\",\"availableAt\":\"2025-01-31T21:00:05Z\",\"sourceId\":\"SYN-OFFICIAL-CLOSE\"},\"fxObservation\":{\"priceCurrencyPerEventCurrency\":\"1.00000000\",\"pair\":\"USD/USD\",\"anchorPolicy\":\"ON_OR_BEFORE_REFERENCE_OBSERVATION\",\"observedAt\":\"2025-01-31T21:00:00Z\",\"availableAt\":\"2025-01-31T21:00:00Z\",\"sourceId\":\"IDENTITY-FX\"},\"exObservation\":{\"price\":\"23.15000000\",\"currency\":\"USD\",\"observedAt\":\"2025-02-03T21:00:00Z\",\"availableAt\":\"2025-02-03T21:00:04Z\",\"sourceId\":\"SYN-OFFICIAL-CLOSE\"},\"taxIllustration\":{\"jurisdiction\":\"US_FEDERAL_INDIVIDUAL_TAXABLE_2025\",\"currency\":\"USD\",\"basisPerShareBefore\":\"1.50000000\",\"confirmedReturnOfCapitalPerShare\":\"1.20000000\",\"sourceId\":\"SYN-FINAL-ISSUER-TAX-CLASSIFICATION\",\"observedAt\":\"2025-02-03T20:00:00Z\",\"availableAt\":\"2025-02-03T20:05:00Z\"}})", "args": [ { @@ -10643,8 +10577,8 @@ "outputShape": "object with 8 fields: eventId, revisionId, state, applied, priceCurrency, marketDataAdjustment, investorReturnDiagnostics, usFederalTaxIllustration" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -10772,9 +10706,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F03-A01.json", "call": "resolveIdentifier({\"query\":{\"source\":{\"scheme\":\"TICKER\",\"value\":\"alp\",\"entityLevel\":\"trading_line\",\"venueMic\":\"xnas\"},\"validAt\":\"2024-06-15T14:30:00Z\",\"knowledgeAt\":\"2024-06-20T12:00:00Z\"},\"assertions\":[{\"assertionId\":\"SYN-MAP-001\",\"revision\":1,\"source\":{\"scheme\":\"TICKER\",\"value\":\"ALP\",\"entityLevel\":\"trading_line\",\"venueMic\":\"XNAS\"},\"target\":{\"canonicalId\":\"SYN-LINE-ALPHA-XNAS-USD\",\"entityLevel\":\"trading_line\"},\"validFrom\":\"2024-01-02T14:30:00Z\",\"validTo\":\"2024-07-01T13:30:00Z\",\"observedAt\":\"2023-12-20T18:00:00Z\",\"availableAt\":\"2023-12-20T18:05:00Z\",\"status\":\"active\",\"confidence\":\"authoritative\",\"checkDigitStatus\":\"not_applicable\",\"assignmentAuthority\":\"SYNTHETIC EXCHANGE NOTICE SERVICE\",\"sourceDocumentId\":\"SYN-NOTICE-100-R1\"},{\"assertionId\":\"SYN-MAP-001\",\"revision\":2,\"source\":{\"scheme\":\"TICKER\",\"value\":\"ALP\",\"entityLevel\":\"trading_line\",\"venueMic\":\"XNAS\"},\"target\":{\"canonicalId\":\"SYN-LINE-BETA-XNAS-USD\",\"entityLevel\":\"trading_line\"},\"validFrom\":\"2024-01-02T14:30:00Z\",\"validTo\":\"2024-07-01T13:30:00Z\",\"observedAt\":\"2024-06-25T09:00:00Z\",\"availableAt\":\"2024-06-25T09:05:00Z\",\"status\":\"active\",\"confidence\":\"authoritative\",\"checkDigitStatus\":\"not_applicable\",\"assignmentAuthority\":\"SYNTHETIC EXCHANGE NOTICE SERVICE\",\"sourceDocumentId\":\"SYN-CORRECTION-100-R2\"},{\"assertionId\":\"SYN-MAP-002\",\"revision\":1,\"source\":{\"scheme\":\"TICKER\",\"value\":\"ALP\",\"entityLevel\":\"trading_line\",\"venueMic\":\"XNAS\"},\"target\":{\"canonicalId\":\"SYN-LINE-GAMMA-XNAS-USD\",\"entityLevel\":\"trading_line\"},\"validFrom\":\"2024-07-01T13:30:00Z\",\"validTo\":null,\"observedAt\":\"2024-06-10T16:00:00Z\",\"availableAt\":\"2024-06-10T16:03:00Z\",\"status\":\"active\",\"confidence\":\"authoritative\",\"checkDigitStatus\":\"not_applicable\",\"assignmentAuthority\":\"SYNTHETIC EXCHANGE NOTICE SERVICE\",\"sourceDocumentId\":\"SYN-NOTICE-101-R1\"}]})", "args": [ { @@ -10896,8 +10830,8 @@ "outputShape": "object with 9 fields: status, source, validAt, knowledgeAt, canonicalId, candidateCanonicalIds, confidence, evidence, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -11055,10 +10989,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "resolveTickerChain({\"issuers\":[{\"issuerId\":\"SYN-ISS-001\"},{\"issuerId\":\"SYN-ISS-002\"}],\"instruments\":[{\"instrumentId\":\"SYN-INS-001\",\"issuerId\":\"SYN-ISS-001\",\"shareClassId\":\"SYN-CLS-A\"},{\"instrumentId\":\"SYN-INS-002\",\"issuerId\":\"SYN-ISS-002\",\"shareClassId\":\"SYN-CLS-COM\"}],\"listings\":[{\"listingId\":\"SYN-LST-001\",\"instrumentId\":\"SYN-INS-001\",\"venueMic\":\"XNAS\",\"currency\":\"USD\"},{\"listingId\":\"SYN-LST-002\",\"instrumentId\":\"SYN-INS-001\",\"venueMic\":\"XLON\",\"currency\":\"GBP\"},{\"listingId\":\"SYN-LST-099\",\"instrumentId\":\"SYN-INS-002\",\"venueMic\":\"XNAS\",\"currency\":\"USD\"}],\"assignments\":[{\"assignmentId\":\"SYN-ASG-100\",\"revision\":1,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"ALP\",\"effectiveAt\":\"2020-01-02T14:30:00Z\",\"validTo\":\"2024-06-10T13:30:00Z\",\"announcedAt\":\"2019-12-18T15:00:00Z\",\"availableAt\":\"2019-12-18T15:05:00Z\",\"changeKind\":\"initial_listing\",\"sourceId\":\"SYN-SRC-XNAS-100\"},{\"assignmentId\":\"SYN-ASG-200\",\"revision\":1,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"NXT\",\"effectiveAt\":\"2024-06-10T13:30:00Z\",\"validTo\":\"2025-01-10T14:30:00Z\",\"announcedAt\":\"2024-05-15T12:00:00Z\",\"availableAt\":\"2024-05-15T12:07:00Z\",\"changeKind\":\"administrative\",\"sourceId\":\"SYN-SRC-XNAS-200-R1\"},{\"assignmentId\":\"SYN-ASG-200\",\"revision\":2,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"NXT\",\"effectiveAt\":\"2024-06-10T13:30:00Z\",\"validTo\":\"2025-01-15T14:30:00Z\",\"announcedAt\":\"2024-05-15T12:00:00Z\",\"availableAt\":\"2024-12-20T16:10:00Z\",\"changeKind\":\"administrative\",\"sourceId\":\"SYN-SRC-XNAS-200-R2\"}],\"query\":{\"direction\":\"symbol_to_listing\",\"symbol\":\"NXT\",\"venueMic\":\"XNAS\",\"queryAt\":\"2024-07-01T15:00:00Z\",\"asOf\":\"2024-08-01T12:00:00Z\"}})", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F03-A02.json", + "call": "resolveTickerChain({\"issuers\":[{\"issuerId\":\"SYN-ISS-001\"},{\"issuerId\":\"SYN-ISS-002\"}],\"instruments\":[{\"instrumentId\":\"SYN-INS-001\",\"issuerId\":\"SYN-ISS-001\",\"shareClassId\":\"SYN-CLS-A\"},{\"instrumentId\":\"SYN-INS-002\",\"issuerId\":\"SYN-ISS-002\",\"shareClassId\":\"SYN-CLS-COM\"}],\"listings\":[{\"listingId\":\"SYN-LST-001\",\"instrumentId\":\"SYN-INS-001\",\"venueMic\":\"XNAS\",\"currency\":\"USD\"},{\"listingId\":\"SYN-LST-002\",\"instrumentId\":\"SYN-INS-001\",\"venueMic\":\"XLON\",\"currency\":\"GBP\"},{\"listingId\":\"SYN-LST-099\",\"instrumentId\":\"SYN-INS-002\",\"venueMic\":\"XNAS\",\"currency\":\"USD\"}],\"assignments\":[{\"assignmentId\":\"SYN-ASG-100\",\"revision\":1,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"ALP\",\"effectiveAt\":\"2020-01-02T14:30:00Z\",\"validTo\":\"2024-06-10T13:30:00Z\",\"announcedAt\":\"2019-12-18T15:00:00Z\",\"availableAt\":\"2019-12-18T15:05:00Z\",\"changeKind\":\"initial_listing\",\"sourceId\":\"SYN-SRC-XNAS-100\"},{\"assignmentId\":\"SYN-ASG-200\",\"revision\":1,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"NXT\",\"effectiveAt\":\"2024-06-10T13:30:00Z\",\"validTo\":\"2025-01-10T14:30:00Z\",\"announcedAt\":\"2024-05-15T12:00:00Z\",\"availableAt\":\"2024-05-15T12:07:00Z\",\"changeKind\":\"administrative\",\"sourceId\":\"SYN-SRC-XNAS-200-R1\"},{\"assignmentId\":\"SYN-ASG-200\",\"revision\":2,\"status\":\"active\",\"listingId\":\"SYN-LST-001\",\"symbol\":\"NXT\",\"effectiveAt\":\"2024-06-10T13:30:00Z\",\"validTo\":\"2025-01-15T14:30:00Z\",\"announcedAt\":\"2024-05-15T12:00:00Z\",\"availableAt\":\"2024-12-20T16:10:00Z\",\"changeKind\":\"administrative\",\"sourceId\":\"SYN-SRC-XNAS-200-R2\"}],\"query\":{\"direction\":\"listing_to_symbol\",\"listingId\":\"SYN-LST-001\",\"queryAt\":\"2024-07-01T15:00:00Z\",\"asOf\":\"2024-08-01T12:00:00Z\"}})", "args": [ { "value": { @@ -11144,9 +11078,8 @@ } ], "query": { - "direction": "symbol_to_listing", - "symbol": "NXT", - "venueMic": "XNAS", + "direction": "listing_to_symbol", + "listingId": "SYN-LST-001", "queryAt": "2024-07-01T15:00:00Z", "asOf": "2024-08-01T12:00:00Z" } @@ -11156,7 +11089,7 @@ ], "output": { "status": "resolved", - "direction": "symbol_to_listing", + "direction": "listing_to_symbol", "queryAt": "2024-07-01T15:00:00Z", "asOf": "2024-08-01T12:00:00Z", "symbol": "NXT", @@ -11178,8 +11111,8 @@ "outputShape": "object with 21 fields: status, direction, queryAt, asOf, symbol, listingId, instrumentId, issuerId, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -11325,9 +11258,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F03-A03.json", "call": "calculate({\"query\":{\"rootEntityId\":\"SYN-CLASS-FOUNDER\",\"validAt\":\"2026-03-01T12:00:00Z\",\"knownAt\":\"2026-03-05T12:00:00Z\",\"compareShareClassIds\":[\"SYN-CLASS-FOUNDER\",\"SYN-CLASS-PUBLIC\"]},\"entities\":[{\"entityId\":\"SYN-ISSUER-ALPHA\",\"entityType\":\"ISSUER\",\"label\":\"Synthetic Alpha Holdings\"},{\"entityId\":\"SYN-INSTRUMENT-COMMON\",\"entityType\":\"LEGAL_INSTRUMENT\",\"label\":\"Synthetic Alpha Common Equity\"},{\"entityId\":\"SYN-INSTRUMENT-PREFERRED\",\"entityType\":\"LEGAL_INSTRUMENT\",\"label\":\"Synthetic Alpha Preferred Equity\"}],\"relationships\":[{\"assertionId\":\"R-ISSUE-COMMON\",\"revisionNumber\":1,\"status\":\"ACTIVE\",\"relationshipType\":\"ISSUED_BY\",\"sourceEntityId\":\"SYN-INSTRUMENT-COMMON\",\"targetEntityId\":\"SYN-ISSUER-ALPHA\",\"effectiveFrom\":\"2026-01-01T00:00:00Z\",\"effectiveTo\":null,\"observedAt\":\"2025-12-15T09:00:00Z\",\"availableAt\":\"2025-12-15T10:00:00Z\",\"source\":{\"sourceId\":\"SYN-CHARTER-1\",\"sourceType\":\"synthetic_charter\",\"documentDate\":\"2025-12-15\",\"locator\":\"Article IV\"},\"terms\":{\"basis\":\"legal-issuer\"},\"unsupportedTerms\":[]},{\"assertionId\":\"R-ISSUE-PREF\",\"revisionNumber\":1,\"status\":\"ACTIVE\",\"relationshipType\":\"ISSUED_BY\",\"sourceEntityId\":\"SYN-INSTRUMENT-PREFERRED\",\"targetEntityId\":\"SYN-ISSUER-ALPHA\",\"effectiveFrom\":\"2026-01-01T00:00:00Z\",\"effectiveTo\":null,\"observedAt\":\"2025-12-15T09:00:00Z\",\"availableAt\":\"2025-12-15T10:00:00Z\",\"source\":{\"sourceId\":\"SYN-CHARTER-1\",\"sourceType\":\"synthetic_charter\",\"documentDate\":\"2025-12-15\",\"locator\":\"Article IV\"},\"terms\":{\"basis\":\"legal-issuer\"},\"unsupportedTerms\":[]},{\"assertionId\":\"R-CLASS-FOUNDER\",\"revisionNumber\":1,\"status\":\"ACTIVE\",\"relationshipType\":\"CLASS_OF\",\"sourceEntityId\":\"SYN-CLASS-FOUNDER\",\"targetEntityId\":\"SYN-INSTRUMENT-COMMON\",\"effectiveFrom\":\"2026-01-01T00:00:00Z\",\"effectiveTo\":null,\"observedAt\":\"2025-12-15T09:00:00Z\",\"availableAt\":\"2025-12-15T10:00:00Z\",\"source\":{\"sourceId\":\"SYN-CHARTER-1\",\"sourceType\":\"synthetic_charter\",\"documentDate\":\"2025-12-15\",\"locator\":\"Article IV.1\"},\"terms\":{\"classCode\":\"F\"},\"unsupportedTerms\":[]}]})", "args": [ { @@ -11431,15 +11364,6 @@ } ], "output": { - "query": { - "rootEntityId": "SYN-CLASS-FOUNDER", - "validAt": "2026-03-01T12:00:00Z", - "knownAt": "2026-03-05T12:00:00Z" - }, - "root": { - "entityId": "SYN-CLASS-FOUNDER", - "entityType": "SHARE_CLASS" - }, "state": "RESOLVED", "sameIssuerShareClassIds": [ "SYN-CLASS-FOUNDER", @@ -11447,8 +11371,6 @@ "SYN-CLASS-PUBLIC" ], "comparison": { - "leftShareClassId": "SYN-CLASS-FOUNDER", - "rightShareClassId": "SYN-CLASS-PUBLIC", "votingRightsRatioLeftToRight": { "status": "ESTABLISHED", "numerator": 10, @@ -11480,102 +11402,19 @@ }, "priceConvertibility": "NOT_ESTABLISHED" }, - "resolvedRelationships": [ - { - "assertionId": "R-CLASS-FOUNDER", - "revisionNumber": 1, - "relationshipType": "CLASS_OF", - "sourceEntityId": "SYN-CLASS-FOUNDER", - "targetEntityId": "SYN-INSTRUMENT-COMMON", - "effectiveFrom": "2026-01-01T00:00:00Z", - "effectiveTo": null, - "observedAt": "2025-12-15T09:00:00Z", - "availableAt": "2025-12-15T10:00:00Z", - "source": { - "sourceId": "SYN-CHARTER-1", - "sourceType": "synthetic_charter", - "documentDate": "2025-12-15", - "locator": "Article IV.1" - }, - "terms": { - "classCode": "F" - }, - "unsupportedTerms": [] - }, - { - "assertionId": "R-CLASS-PREF", - "revisionNumber": 1, - "relationshipType": "CLASS_OF", - "sourceEntityId": "SYN-CLASS-PREFERRED", - "targetEntityId": "SYN-INSTRUMENT-PREFERRED", - "effectiveFrom": "2026-01-01T00:00:00Z", - "effectiveTo": null, - "observedAt": "2025-12-15T09:00:00Z", - "availableAt": "2025-12-15T10:00:00Z", - "source": { - "sourceId": "SYN-CHARTER-1", - "sourceType": "synthetic_charter", - "documentDate": "2025-12-15", - "locator": "Article IV.3" - }, - "terms": { - "classCode": "PR" - }, - "unsupportedTerms": [] - }, - { - "assertionId": "R-CLASS-PUBLIC", - "revisionNumber": 1, - "relationshipType": "CLASS_OF", - "sourceEntityId": "SYN-CLASS-PUBLIC", - "targetEntityId": "SYN-INSTRUMENT-COMMON", - "effectiveFrom": "2026-01-01T00:00:00Z", - "effectiveTo": null, - "observedAt": "2025-12-15T09:00:00Z", - "availableAt": "2025-12-15T10:00:00Z", - "source": { - "sourceId": "SYN-CHARTER-1", - "sourceType": "synthetic_charter", - "documentDate": "2025-12-15", - "locator": "Article IV.2" - }, - "terms": { - "classCode": "P" - }, - "unsupportedTerms": [] - } - ], "diagnostics": { - "selectedRevisionByAssertion": { - "R-CLASS-FOUNDER": 1, - "R-CLASS-PREF": 1, - "R-CLASS-PUBLIC": 1, - "R-CONVERT-FOUNDER": 1, - "R-DIV-PREF": 1, - "R-ECON-FOUNDER": 1, - "R-ECON-PUBLIC": 1, - "R-FUNGIBLE-LINES": 1, - "R-ISSUE-COMMON": 1, - "R-ISSUE-PREF": 1, - "R-LINE-EU": 1, - "R-LINE-US": 1, - "R-LIST-EU": 1, - "R-LIST-OLD": 1 - }, "excludedFutureRevisionCount": 1, "cancelledAssertionIds": [ "R-LIST-OLD" - ], - "conflicts": [], - "unsupportedTerms": [] + ] } }, "outputElided": null, - "outputShape": "object with 7 fields: query, root, state, sameIssuerShareClassIds, comparison, resolvedRelationships, diagnostics" + "outputShape": "object with 4 fields: state, sameIssuerShareClassIds, comparison, diagnostics" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -11703,9 +11542,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F03-A04.json", "call": "resolveMerger({\"asOf\":\"2026-07-02T12:00:00Z\",\"position\":{\"predecessorQuantity\":\"101\",\"electedOptionId\":\"stock-election\",\"appraisalQuantity\":\"0\"},\"eventVersions\":[{\"eventId\":\"SYNTH-MERGER-001\",\"revision\":1,\"status\":\"confirmed\",\"availableAt\":\"2026-05-01T12:00:00Z\",\"announcedAt\":\"2026-04-15T12:00:00Z\",\"closingAt\":\"2026-06-30T20:00:00Z\",\"effectiveAt\":\"2026-06-30T20:00:00Z\",\"delistingAt\":\"2026-07-01T13:30:00Z\",\"sourceIds\":[\"SYNTH-DEFINITIVE-AGREEMENT-R1\",\"SYNTH-CLOSING-NOTICE\"],\"predecessor\":{\"issuerId\":\"ISSUER-TARGET\",\"instrumentId\":\"INSTR-TARGET-COMMON\",\"shareClassId\":\"CLASS-TARGET-A\",\"listingId\":\"LIST-TARGET-XNAS\",\"identifiers\":[{\"scheme\":\"PACKAGE_SECURITY_KEY\",\"value\":\"SYNTH-TARGET-A\",\"sourceId\":\"SYNTH-SECURITY-MASTER\"}]},\"options\":[{\"optionId\":\"stock-election\",\"stockLegs\":[{\"legId\":\"STOCK-LEG-1\",\"ratioPerAllocatedPredecessorShare\":\"0.6\",\"sourceId\":\"SYNTH-DEFINITIVE-AGREEMENT-R1\",\"successor\":{\"issuerId\":\"ISSUER-SUCCESSOR\",\"instrumentId\":\"INSTR-SUCCESSOR-COMMON\",\"shareClassId\":\"CLASS-SUCCESSOR-A\",\"listingId\":\"LIST-SUCCESSOR-XNYS\",\"identifiers\":[{\"scheme\":\"PACKAGE_SECURITY_KEY\",\"value\":\"SYNTH-SUCCESSOR-A\",\"sourceId\":\"SYNTH-SECURITY-MASTER\"}]},\"fractionalPolicy\":{\"mode\":\"cash_in_lieu\",\"lotSize\":\"1\",\"pricePerShare\":\"40\",\"currency\":\"USD\",\"observedAt\":\"2026-06-30T20:00:00Z\",\"availableAt\":\"2026-06-30T20:01:00Z\",\"sourceId\":\"SYNTH-CIL-PRICE\"}}],\"cashLegs\":[{\"legId\":\"CASH-1\",\"kind\":\"consideration\",\"amountPerAllocatedPredecessorShare\":\"5\",\"currency\":\"USD\",\"sourceId\":\"SYNTH-DEFINITIVE-AGREEMENT-R1\"},{\"legId\":\"TAX-1\",\"kind\":\"withholding\",\"amountPerAllocatedPredecessorShare\":\"0.2\",\"currency\":\"USD\",\"sourceId\":\"SYNTH-TAX-INSTRUCTION\"},{\"legId\":\"FEE-1\",\"kind\":\"fee\",\"amountPerAllocatedPredecessorShare\":\"0.05\",\"currency\":\"USD\",\"sourceId\":\"SYNTH-AGENT-INSTRUCTION\"}]},{\"optionId\":\"cash-election\",\"stockLegs\":[],\"cashLegs\":[{\"legId\":\"CASH-2\",\"kind\":\"consideration\",\"amountPerAllocatedPredecessorShare\":\"35\",\"currency\":\"USD\",\"sourceId\":\"SYNTH-DEFINITIVE-AGREEMENT-R1\"},{\"legId\":\"FEE-2\",\"kind\":\"fee\",\"amountPerAllocatedPredecessorShare\":\"0.05\",\"currency\":\"USD\",\"sourceId\":\"SYNTH-AGENT-INSTRUCTION\"}]}],\"electionRules\":{\"fallbackOptionId\":\"cash-election\",\"fulfilledFractions\":{\"stock-election\":\"0.75\",\"cash-election\":\"1\"}},\"termsSupported\":true}]})", "args": [ { @@ -11931,8 +11770,8 @@ "outputShape": "object with 13 fields: state, eventId, selectedRevision, effectiveAt, predecessor, allocations, successorPositions, cashByCurrency, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -12078,9 +11917,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F03-A05.json", "call": "calculate({\"asOf\":\"2026-04-17T12:00:00Z\",\"baseCurrency\":\"USD\",\"previousRegularObservation\":{\"securityId\":\"SYNTH-OLD-A\",\"price\":\"48\",\"currency\":\"USD\",\"tradingAt\":\"2026-04-10T20:00:00Z\",\"observedAt\":\"2026-04-10T20:00:00Z\",\"sourceAt\":\"2026-04-10T20:01:00Z\",\"availableAt\":\"2026-04-10T20:05:00Z\",\"sourceId\":\"SYNTH-PRICES\"},\"lastRegularObservation\":{\"securityId\":\"SYNTH-OLD-A\",\"price\":\"50\",\"currency\":\"USD\",\"tradingAt\":\"2026-04-14T20:00:00Z\",\"observedAt\":\"2026-04-14T20:00:00Z\",\"sourceAt\":\"2026-04-14T20:01:00Z\",\"availableAt\":\"2026-04-14T20:05:00Z\",\"sourceId\":\"SYNTH-PRICES\"},\"event\":{\"eventId\":\"SYNTH-EVENT-001\",\"reason\":\"merger\",\"effectiveAt\":\"2026-04-15T13:30:00Z\",\"observedAt\":\"2026-04-01T14:00:00Z\",\"sourceAt\":\"2026-04-01T14:01:00Z\",\"availableAt\":\"2026-04-01T14:05:00Z\",\"sourceId\":\"SYNTH-EVENTS\"},\"proceedsStatus\":\"complete\",\"proceeds\":[{\"kind\":\"cash\",\"amountPerOldShare\":\"10\",\"currency\":\"EUR\",\"effectiveAt\":\"2026-04-15T13:30:00Z\",\"observedAt\":\"2026-04-15T15:00:00Z\",\"sourceAt\":\"2026-04-15T15:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-PAYMENTS\",\"fxToBase\":{\"fromCurrency\":\"EUR\",\"toCurrency\":\"USD\",\"rate\":\"1.1\",\"rateAt\":\"2026-04-15T20:00:00Z\",\"observedAt\":\"2026-04-15T20:00:00Z\",\"sourceAt\":\"2026-04-15T20:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-FX\"}},{\"kind\":\"stock\",\"quantityPerOldShare\":\"0.8\",\"successorSecurityId\":\"SYNTH-NEW-B\",\"valuationPrice\":\"52.5\",\"priceCurrency\":\"USD\",\"valuationAt\":\"2026-04-15T20:00:00Z\",\"observedAt\":\"2026-04-15T20:00:00Z\",\"sourceAt\":\"2026-04-15T20:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-SUCCESSOR-PRICE\",\"fxToBase\":{\"fromCurrency\":\"USD\",\"toCurrency\":\"USD\",\"rate\":\"1\",\"rateAt\":\"2026-04-15T20:00:00Z\",\"observedAt\":\"2026-04-15T20:00:00Z\",\"sourceAt\":\"2026-04-15T20:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-FX-IDENTITY\"}}],\"deductions\":[{\"kind\":\"fee\",\"amountPerOldShare\":\"0.2\",\"currency\":\"USD\",\"effectiveAt\":\"2026-04-15T13:30:00Z\",\"observedAt\":\"2026-04-15T21:00:00Z\",\"sourceAt\":\"2026-04-15T21:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-FEES\",\"fxToBase\":{\"fromCurrency\":\"USD\",\"toCurrency\":\"USD\",\"rate\":\"1\",\"rateAt\":\"2026-04-15T20:00:00Z\",\"observedAt\":\"2026-04-15T20:00:00Z\",\"sourceAt\":\"2026-04-15T20:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-FX-IDENTITY\"}},{\"kind\":\"withholding\",\"amountPerOldShare\":\"0.3\",\"currency\":\"USD\",\"effectiveAt\":\"2026-04-15T13:30:00Z\",\"observedAt\":\"2026-04-15T21:00:00Z\",\"sourceAt\":\"2026-04-15T21:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-WITHHOLDING\",\"fxToBase\":{\"fromCurrency\":\"USD\",\"toCurrency\":\"USD\",\"rate\":\"1\",\"rateAt\":\"2026-04-15T20:00:00Z\",\"observedAt\":\"2026-04-15T20:00:00Z\",\"sourceAt\":\"2026-04-15T20:01:00Z\",\"availableAt\":\"2026-04-16T00:00:00Z\",\"sourceId\":\"SYNTH-FX-IDENTITY\"}}],\"researchImputation\":null})", "args": [ { @@ -12247,8 +12086,8 @@ "outputShape": "object with 3 fields: observed, researchEstimate, diagnostics" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -12382,9 +12221,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F04-A01.json", "call": "calculate({\"indexId\":\"IDX:SYNTH:ALPHA\",\"effectiveAt\":\"2024-08-15T00:00:00Z\",\"knownAt\":\"2024-08-15T12:00:00Z\",\"snapshots\":[{\"snapshotId\":\"BASE-2024\",\"indexId\":\"IDX:SYNTH:ALPHA\",\"revision\":1,\"effectiveAt\":\"2024-01-01T00:00:00Z\",\"availableAt\":\"2024-01-02T09:00:00Z\",\"lastSequence\":0,\"status\":\"active\",\"securityIds\":[\"SEC:A\",\"SEC:B\",\"SEC:C\",\"SEC:D\"],\"sourceId\":\"SYNTH-BASE\"}],\"events\":[{\"eventId\":\"EV-001\",\"indexId\":\"IDX:SYNTH:ALPHA\",\"revision\":1,\"sequence\":1,\"eventType\":\"add\",\"effectiveOrder\":0,\"effectiveAt\":\"2024-02-01T00:00:00Z\",\"announcedAt\":\"2024-01-15T12:00:00Z\",\"availableAt\":\"2024-01-15T12:05:00Z\",\"status\":\"active\",\"changes\":[{\"action\":\"add\",\"securityId\":\"SEC:E\"}],\"sourceId\":\"SYNTH-NOTICE-001\"},{\"eventId\":\"EV-002\",\"indexId\":\"IDX:SYNTH:ALPHA\",\"revision\":1,\"sequence\":2,\"eventType\":\"replace\",\"effectiveOrder\":0,\"effectiveAt\":\"2024-03-01T00:00:00Z\",\"announcedAt\":\"2024-02-20T16:00:00Z\",\"availableAt\":\"2024-02-20T16:03:00Z\",\"status\":\"active\",\"changes\":[{\"action\":\"delete\",\"securityId\":\"SEC:B\"},{\"action\":\"add\",\"securityId\":\"SEC:F\"}],\"sourceId\":\"SYNTH-NOTICE-002\"},{\"eventId\":\"EV-003\",\"indexId\":\"IDX:SYNTH:ALPHA\",\"revision\":1,\"sequence\":3,\"eventType\":\"rebalance\",\"effectiveOrder\":0,\"effectiveAt\":\"2024-04-01T00:00:00Z\",\"announcedAt\":\"2024-03-20T15:00:00Z\",\"availableAt\":\"2024-03-20T15:04:00Z\",\"status\":\"active\",\"changes\":[],\"sourceId\":\"SYNTH-NOTICE-003\"}]})", "args": [ { @@ -12474,11 +12313,6 @@ ], "output": { "status": "resolved", - "indexId": "IDX:SYNTH:ALPHA", - "effectiveAt": "2024-08-15T00:00:00Z", - "knownAt": "2024-08-15T12:00:00Z", - "baseSnapshotId": "BASE-2024", - "baseRevision": 1, "securityIds": [ "SEC:E", "SEC:F", @@ -12487,23 +12321,6 @@ "SEC:I", "SEC:J" ], - "membershipIntervals": [ - { - "securityId": "SEC:A", - "validFrom": "2024-01-01T00:00:00Z", - "validTo": "2024-07-01T00:00:00Z" - }, - { - "securityId": "SEC:B", - "validFrom": "2024-01-01T00:00:00Z", - "validTo": "2024-03-01T00:00:00Z" - }, - { - "securityId": "SEC:C", - "validFrom": "2024-01-01T00:00:00Z", - "validTo": "2024-04-15T00:00:00Z" - } - ], "appliedEventVersions": [ "EV-001@1", "EV-002@1", @@ -12512,15 +12329,14 @@ "EV-005@1", "EV-006@1" ], - "cancelledEventIds": [], - "diagnostics": [] + "cancelledEventIds": [] }, "outputElided": null, - "outputShape": "object with 11 fields: status, indexId, effectiveAt, knownAt, baseSnapshotId, baseRevision, securityIds, membershipIntervals, …" + "outputShape": "object with 4 fields: status, securityIds, appliedEventVersions, cancelledEventIds" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -12655,9 +12471,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F04-A02.json", "call": "guardSurvivorship({\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"definitionId\":\"DEF:SYNTH:CORE\",\"effectiveAt\":\"2023-12-31T23:59:59Z\",\"knownAt\":\"2024-01-02T12:00:00Z\",\"candidateUniverse\":{\"construction\":\"historical_membership_ledger\",\"asOf\":\"2023-12-31T23:59:59Z\",\"availableAt\":\"2024-01-02T10:00:00Z\",\"securityIds\":[\"SEC:A\",\"SEC:B\",\"SEC:C\",\"SEC:D\"],\"sourceId\":\"SYNTH-CANDIDATE-LEDGER\"},\"universeDefinitions\":[{\"definitionId\":\"DEF:SYNTH:CORE\",\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"revision\":1,\"effectiveFrom\":\"2020-01-01T00:00:00Z\",\"effectiveTo\":null,\"announcedAt\":\"2019-12-15T12:00:00Z\",\"availableAt\":\"2019-12-15T12:05:00Z\",\"status\":\"active\",\"baseType\":\"named_research_universe\",\"baseId\":\"BASE:SYNTH:001\",\"ruleSummary\":\"Synthetic members documented by effective-dated membership evidence.\",\"sourceId\":\"SYNTH-DEFINITION-R1\"},{\"definitionId\":\"DEF:SYNTH:CORE\",\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"revision\":2,\"effectiveFrom\":\"2020-01-01T00:00:00Z\",\"effectiveTo\":null,\"announcedAt\":\"2024-02-01T09:00:00Z\",\"availableAt\":\"2024-02-01T09:05:00Z\",\"status\":\"active\",\"baseType\":\"named_research_universe\",\"baseId\":\"BASE:SYNTH:001\",\"ruleSummary\":\"Later documentation revision; unavailable to the canonical query.\",\"sourceId\":\"SYNTH-DEFINITION-R2\"}],\"membershipRecords\":[{\"membershipId\":\"MEM-A\",\"revision\":1,\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"securityId\":\"SEC:A\",\"validFrom\":\"2020-01-01T00:00:00Z\",\"validTo\":null,\"announcedAt\":\"2019-12-15T12:00:00Z\",\"availableAt\":\"2019-12-15T12:05:00Z\",\"status\":\"active\",\"changeType\":\"entry\",\"eventId\":\"EVENT-A-ENTRY\",\"sourceId\":\"SYNTH-MEM-A\"},{\"membershipId\":\"MEM-B\",\"revision\":1,\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"securityId\":\"SEC:B\",\"validFrom\":\"2020-01-01T00:00:00Z\",\"validTo\":\"2024-06-01T00:00:00Z\",\"announcedAt\":\"2023-12-20T10:00:00Z\",\"availableAt\":\"2023-12-20T10:05:00Z\",\"status\":\"active\",\"changeType\":\"exit\",\"eventId\":\"EVENT-B-EXIT\",\"sourceId\":\"SYNTH-MEM-B-R1\"},{\"membershipId\":\"MEM-B\",\"revision\":2,\"universeId\":\"UNIVERSE:SYNTH:CORE\",\"securityId\":\"SEC:B\",\"validFrom\":\"2020-01-01T00:00:00Z\",\"validTo\":\"2023-12-15T00:00:00Z\",\"announcedAt\":\"2024-01-10T08:00:00Z\",\"availableAt\":\"2024-01-10T08:05:00Z\",\"status\":\"active\",\"changeType\":\"revision\",\"eventId\":\"EVENT-B-CORRECTION\",\"sourceId\":\"SYNTH-MEM-B-R2\"}],\"comparisonRoster\":{\"observedAt\":\"2025-01-02T00:00:00Z\",\"availableAt\":\"2025-01-02T12:00:00Z\",\"securityIds\":[\"SEC:A\",\"SEC:C\",\"SEC:D\"],\"sourceId\":\"SYNTH-CURRENT-ROSTER\"}})", "args": [ { @@ -12768,39 +12584,7 @@ ], "output": { "status": "resolved", - "universeId": "UNIVERSE:SYNTH:CORE", - "definitionId": "DEF:SYNTH:CORE", "definitionVersion": "DEF:SYNTH:CORE@1", - "effectiveAt": "2023-12-31T23:59:59Z", - "knownAt": "2024-01-02T12:00:00Z", - "candidateUniverseSourceId": "SYNTH-CANDIDATE-LEDGER", - "candidateUniverseAsOf": "2023-12-31T23:59:59Z", - "classifications": [ - { - "securityId": "SEC:A", - "state": "eligible", - "evidenceVersions": [ - "MEM-A@1" - ], - "diagnostic": "one known active membership interval covers effectiveAt" - }, - { - "securityId": "SEC:B", - "state": "eligible", - "evidenceVersions": [ - "MEM-B@1" - ], - "diagnostic": "one known active membership interval covers effectiveAt" - }, - { - "securityId": "SEC:C", - "state": "eligible", - "evidenceVersions": [ - "MEM-C@1" - ], - "diagnostic": "one known active membership interval covers effectiveAt" - } - ], "eligibleSecurityIds": [ "SEC:A", "SEC:B", @@ -12811,23 +12595,22 @@ ], "unknownSecurityIds": [], "ambiguousSecurityIds": [], - "membershipEventVersionsUsed": [ - "MEM-A@1", - "MEM-B@1", - "MEM-C@1", - "MEM-D@1" - ] - }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 16 + "hindsightDiagnostics": { + "historicallyEligibleMissingFromCurrent": [ + "SEC:B" + ], + "currentRosterNotHistoricallyEligible": [ + "SEC:D" + ], + "retentionRatio": 0.666667 + } }, - "outputShape": "object with 16 fields: status, universeId, definitionId, definitionVersion, effectiveAt, knownAt, candidateUniverseSourceId, candidateUniverseAsOf, …" + "outputElided": null, + "outputShape": "object with 7 fields: status, definitionVersion, eligibleSecurityIds, ineligibleSecurityIds, unknownSecurityIds, ambiguousSecurityIds, hindsightDiagnostics" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -12973,10 +12756,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate({\"query\":{\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"effectiveAt\":\"2025-05-13T13:36:10Z\",\"knownAt\":\"2025-05-13T13:35:30Z\",\"policyId\":\"POLICY-SYN-IPO-RESEARCH\"},\"policies\":[{\"policyId\":\"POLICY-SYN-IPO-RESEARCH\",\"revision\":1,\"state\":\"active\",\"effectiveAt\":\"2025-05-01T00:00:00Z\",\"availableAt\":\"2025-05-01T00:05:00Z\",\"sourceId\":\"SYN-RESEARCH-GOVERNANCE\",\"context\":\"traditional_ipo\",\"marketPhase\":\"regular\",\"requiredEventTypes\":[\"registration_effective\",\"listing_notice\",\"first_eligible_session\",\"first_observed_trade\",\"vendor_release\",\"local_ingestion\"]},{\"policyId\":\"POLICY-SYN-IPO-RESEARCH\",\"revision\":2,\"state\":\"active\",\"effectiveAt\":\"2025-05-01T00:00:00Z\",\"availableAt\":\"2025-05-14T09:00:00Z\",\"sourceId\":\"SYN-RESEARCH-GOVERNANCE\",\"context\":\"traditional_ipo\",\"marketPhase\":\"regular\",\"requiredEventTypes\":[\"registration_effective\",\"listing_notice\",\"first_eligible_session\",\"first_observed_quote\",\"first_observed_trade\",\"vendor_release\"]}],\"records\":[{\"eventId\":\"EV-FILING\",\"revision\":1,\"state\":\"active\",\"eventType\":\"issuer_filing\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-05T14:00:00Z\",\"availableAt\":\"2025-05-05T14:03:00Z\",\"clockOwner\":\"regulator\",\"sourceId\":\"SYN-REGULATOR-FILING\"},{\"eventId\":\"EV-EFFECT\",\"revision\":1,\"state\":\"active\",\"eventType\":\"registration_effective\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-08T12:00:00Z\",\"availableAt\":\"2025-05-08T12:02:00Z\",\"clockOwner\":\"regulator\",\"sourceId\":\"SYN-REGULATOR-EFFECT\"},{\"eventId\":\"EV-LIST\",\"revision\":1,\"state\":\"active\",\"eventType\":\"listing_notice\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-13T13:30:00Z\",\"availableAt\":\"2025-05-08T15:10:00Z\",\"clockOwner\":\"exchange\",\"sourceId\":\"SYN-EXCHANGE-NOTICE\"}]})", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F04-A03.json", + "call": "calculate({\"query\":{\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"effectiveAt\":\"2025-05-13T13:36:10Z\",\"knownAt\":\"2025-05-13T13:36:10Z\",\"policyId\":\"POLICY-SYN-IPO-RESEARCH\"},\"policies\":[{\"policyId\":\"POLICY-SYN-IPO-RESEARCH\",\"revision\":1,\"state\":\"active\",\"effectiveAt\":\"2025-05-01T00:00:00Z\",\"availableAt\":\"2025-05-01T00:05:00Z\",\"sourceId\":\"SYN-RESEARCH-GOVERNANCE\",\"context\":\"traditional_ipo\",\"marketPhase\":\"regular\",\"requiredEventTypes\":[\"registration_effective\",\"listing_notice\",\"first_eligible_session\",\"first_observed_trade\",\"vendor_release\",\"local_ingestion\"]},{\"policyId\":\"POLICY-SYN-IPO-RESEARCH\",\"revision\":2,\"state\":\"active\",\"effectiveAt\":\"2025-05-01T00:00:00Z\",\"availableAt\":\"2025-05-14T09:00:00Z\",\"sourceId\":\"SYN-RESEARCH-GOVERNANCE\",\"context\":\"traditional_ipo\",\"marketPhase\":\"regular\",\"requiredEventTypes\":[\"registration_effective\",\"listing_notice\",\"first_eligible_session\",\"first_observed_quote\",\"first_observed_trade\",\"vendor_release\"]}],\"records\":[{\"eventId\":\"EV-FILING\",\"revision\":1,\"state\":\"active\",\"eventType\":\"issuer_filing\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-05T14:00:00Z\",\"availableAt\":\"2025-05-05T14:03:00Z\",\"clockOwner\":\"regulator\",\"sourceId\":\"SYN-REGULATOR-FILING\"},{\"eventId\":\"EV-EFFECT\",\"revision\":1,\"state\":\"active\",\"eventType\":\"registration_effective\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-08T12:00:00Z\",\"availableAt\":\"2025-05-08T12:02:00Z\",\"clockOwner\":\"regulator\",\"sourceId\":\"SYN-REGULATOR-EFFECT\"},{\"eventId\":\"EV-LIST\",\"revision\":1,\"state\":\"active\",\"eventType\":\"listing_notice\",\"issuerId\":\"ISSUER-SYN-001\",\"instrumentId\":\"INSTRUMENT-SYN-001\",\"listingId\":\"LISTING-SYN-XNAS\",\"marketPhase\":\"all\",\"effectiveAt\":\"2025-05-13T13:30:00Z\",\"availableAt\":\"2025-05-08T15:10:00Z\",\"clockOwner\":\"exchange\",\"sourceId\":\"SYN-EXCHANGE-NOTICE\"}]})", "args": [ { "value": { @@ -12985,7 +12768,7 @@ "instrumentId": "INSTRUMENT-SYN-001", "listingId": "LISTING-SYN-XNAS", "effectiveAt": "2025-05-13T13:36:10Z", - "knownAt": "2025-05-13T13:35:30Z", + "knownAt": "2025-05-13T13:36:10Z", "policyId": "POLICY-SYN-IPO-RESEARCH" }, "policies": [ @@ -13075,53 +12858,17 @@ } ], "output": { - "effectiveAt": "2025-05-13T13:36:10Z", - "knownAt": "2025-05-13T13:35:30Z", - "identity": { - "issuerId": "ISSUER-SYN-001", - "instrumentId": "INSTRUMENT-SYN-001", - "listingId": "LISTING-SYN-XNAS" - }, - "policyId": "POLICY-SYN-IPO-RESEARCH", - "status": "incomplete", - "policySatisfied": false, - "policy": { - "policyId": "POLICY-SYN-IPO-RESEARCH", - "revision": 1, - "sourceId": "SYN-RESEARCH-GOVERNANCE", - "effectiveAt": "2025-05-01T00:00:00Z", - "availableAt": "2025-05-01T00:05:00Z", - "context": "traditional_ipo", - "marketPhase": "regular", - "requiredEventTypes": [ - "registration_effective", - "listing_notice", - "first_eligible_session", - "first_observed_trade", - "vendor_release", - "local_ingestion" - ] - }, - "effectiveGateAt": null, - "knowledgeGateAt": null, - "missingPolicy": false, - "missingEventTypes": [ - "local_ingestion" - ], - "pendingEffectiveEventTypes": [], - "ambiguousEventTypes": [], - "supplementalAmbiguousEventTypes": [] - }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 20 + "status": "resolved", + "effectiveGateAt": "2025-05-13T13:36:00Z", + "knowledgeGateAt": "2025-05-13T13:36:05Z", + "missingEventTypes": [] }, - "outputShape": "object with 20 fields: effectiveAt, knownAt, identity, policyId, status, policySatisfied, policy, effectiveGateAt, …" + "outputElided": null, + "outputShape": "object with 4 fields: status, effectiveGateAt, knowledgeGateAt, missingEventTypes" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -13261,9 +13008,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D02-F04-A04.json", "call": "calculate({\"entityId\":\"CIK0000033619\",\"reportPeriod\":\"2017-09-29\",\"formFamily\":\"10-K\",\"asOf\":\"2018-02-01T00:00:00Z\",\"records\":[{\"entityId\":\"CIK0000033619\",\"reportPeriod\":\"2017-09-29\",\"form\":\"10-K\",\"accessionNo\":\"0001564590-17-024189\",\"amendmentNumber\":0,\"acceptedAt\":\"2017-11-21T16:32:41Z\",\"ingestedAt\":\"2017-11-21T16:40:00Z\",\"amendmentScope\":[\"Original annual filing\"],\"facts\":{\"basicEpsUsdPerShare\":3.94,\"netEarningsUsdMillions\":117.387}},{\"entityId\":\"CIK0000033619\",\"reportPeriod\":\"2017-09-29\",\"form\":\"10-K/A\",\"accessionNo\":\"0001564590-18-007244\",\"amendmentNumber\":1,\"acceptedAt\":\"2018-03-30T14:43:54Z\",\"ingestedAt\":\"2018-03-30T15:00:00Z\",\"amendmentScope\":[\"Item 6\",\"Item 7\",\"Item 8\",\"Item 9A\",\"Item 15\"],\"facts\":{\"basicEpsUsdPerShare\":3.75,\"netEarningsUsdMillions\":111.554}}]})", "args": [ { @@ -13342,8 +13089,8 @@ "outputShape": "object with 13 fields: entityId, reportPeriod, asOf, selectionBasis, accessionNo, form, amendmentNumber, acceptedAt, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -22877,88 +22624,54 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculateNetAdvances({\"session_date\":\"2026-01-05\",\"session_id\":\"regular-close\",\"session_timezone\":\"America/New_York\",\"venue_id\":\"SYNTH:XNAS\",\"universe_id\":\"SYNTH:ACTIVE-LISTINGS@2026-01-05\",\"comparison_basis\":\"official-close-versus-source-adjusted-comparable-prior-close\",\"corporate_action_policy\":\"provider-supplies-split-and-distribution-adjusted-prior-close;calculator-does-not-adjust\",\"price_tolerance\":0.01,\"calculation_as_of\":\"2026-01-05T21:04:59Z\",\"revisions\":[{\"revision_id\":\"SYNTH-R1\",\"revision_sequence\":1,\"supersedes_revision_id\":null,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"is_final\":false,\"members\":[{\"listing_id\":\"L-001\",\"security_id\":\"SEC-001\",\"ticker\":\"ALFA\",\"state\":\"eligible\",\"current_price\":101,\"prior_comparable_price\":100},{\"listing_id\":\"L-002\",\"security_id\":\"SEC-002\",\"ticker\":\"BRAV\",\"state\":\"eligible\",\"current_price\":51,\"prior_comparable_price\":50},{\"listing_id\":\"L-003\",\"security_id\":\"SEC-003\",\"ticker\":\"CRWN\",\"state\":\"eligible\",\"current_price\":12,\"prior_comparable_price\":11}]},{\"revision_id\":\"SYNTH-R2\",\"revision_sequence\":2,\"supersedes_revision_id\":\"SYNTH-R1\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T22:00:00Z\",\"is_final\":true,\"members\":[{\"listing_id\":\"L-001\",\"security_id\":\"SEC-001\",\"ticker\":\"ALFA\",\"state\":\"eligible\",\"current_price\":101,\"prior_comparable_price\":100},{\"listing_id\":\"L-002\",\"security_id\":\"SEC-002\",\"ticker\":\"BRAV\",\"state\":\"eligible\",\"current_price\":51,\"prior_comparable_price\":50},{\"listing_id\":\"L-003\",\"security_id\":\"SEC-003\",\"ticker\":\"CRWN\",\"state\":\"eligible\",\"current_price\":12,\"prior_comparable_price\":11}]}]})", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F01-A01.json", + "call": "calculateNetAdvances({\"session_date\":\"2026-01-05\",\"session_id\":\"regular\",\"session_timezone\":\"UTC\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-3\",\"comparison_basis\":\"comparable-prior-close\",\"corporate_action_policy\":\"provider-adjusted\",\"price_tolerance\":0,\"calculation_as_of\":\"2026-01-05T22:00:00Z\",\"revisions\":[{\"revision_id\":\"R1\",\"revision_sequence\":1,\"supersedes_revision_id\":null,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"is_final\":true,\"members\":[{\"listing_id\":\"L-A\",\"security_id\":\"S-A\",\"ticker\":\"A\",\"state\":\"eligible\",\"current_price\":11,\"prior_comparable_price\":10},{\"listing_id\":\"L-D\",\"security_id\":\"S-D\",\"ticker\":\"D\",\"state\":\"eligible\",\"current_price\":9,\"prior_comparable_price\":10},{\"listing_id\":\"L-U\",\"security_id\":\"S-U\",\"ticker\":\"U\",\"state\":\"eligible\",\"current_price\":10,\"prior_comparable_price\":10}]}]})", "args": [ { "value": { "session_date": "2026-01-05", - "session_id": "regular-close", - "session_timezone": "America/New_York", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-LISTINGS@2026-01-05", - "comparison_basis": "official-close-versus-source-adjusted-comparable-prior-close", - "corporate_action_policy": "provider-supplies-split-and-distribution-adjusted-prior-close;calculator-does-not-adjust", - "price_tolerance": 0.01, - "calculation_as_of": "2026-01-05T21:04:59Z", + "session_id": "regular", + "session_timezone": "UTC", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-3", + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted", + "price_tolerance": 0, + "calculation_as_of": "2026-01-05T22:00:00Z", "revisions": [ { - "revision_id": "SYNTH-R1", + "revision_id": "R1", "revision_sequence": 1, "supersedes_revision_id": null, "effective_at": "2026-01-05T21:00:00Z", "available_at": "2026-01-05T21:05:00Z", - "is_final": false, - "members": [ - { - "listing_id": "L-001", - "security_id": "SEC-001", - "ticker": "ALFA", - "state": "eligible", - "current_price": 101, - "prior_comparable_price": 100 - }, - { - "listing_id": "L-002", - "security_id": "SEC-002", - "ticker": "BRAV", - "state": "eligible", - "current_price": 51, - "prior_comparable_price": 50 - }, - { - "listing_id": "L-003", - "security_id": "SEC-003", - "ticker": "CRWN", - "state": "eligible", - "current_price": 12, - "prior_comparable_price": 11 - } - ] - }, - { - "revision_id": "SYNTH-R2", - "revision_sequence": 2, - "supersedes_revision_id": "SYNTH-R1", - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T22:00:00Z", "is_final": true, "members": [ { - "listing_id": "L-001", - "security_id": "SEC-001", - "ticker": "ALFA", + "listing_id": "L-A", + "security_id": "S-A", + "ticker": "A", "state": "eligible", - "current_price": 101, - "prior_comparable_price": 100 + "current_price": 11, + "prior_comparable_price": 10 }, { - "listing_id": "L-002", - "security_id": "SEC-002", - "ticker": "BRAV", + "listing_id": "L-D", + "security_id": "S-D", + "ticker": "D", "state": "eligible", - "current_price": 51, - "prior_comparable_price": 50 + "current_price": 9, + "prior_comparable_price": 10 }, { - "listing_id": "L-003", - "security_id": "SEC-003", - "ticker": "CRWN", + "listing_id": "L-U", + "security_id": "S-U", + "ticker": "U", "state": "eligible", - "current_price": 12, - "prior_comparable_price": 11 + "current_price": 10, + "prior_comparable_price": 10 } ] } @@ -22968,31 +22681,27 @@ } ], "output": { - "status": "unsupported", - "direction": null, - "metric": "advances_minus_declines", - "session_date": "2026-01-05", - "session_id": "regular-close", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-LISTINGS@2026-01-05", - "calculation_as_of": "2026-01-05T21:04:59Z", - "selected_revision_id": null, - "selected_revision_sequence": null, - "selected_effective_at": null, - "selected_available_at": null, - "is_provisional": null, - "advances": null - }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 25 + "status": "ready", + "direction": "balanced", + "selected_revision_id": "R1", + "advances": 1, + "declines": 1, + "unchanged": 1, + "excluded": 0, + "unclassified": 0, + "universe_size": 3, + "mover_count": 2, + "classified_count": 3, + "coverage_ratio": 1, + "net_advances": 0, + "is_provisional": false }, - "outputShape": "object with 25 fields: status, direction, metric, session_date, session_id, venue_id, universe_id, calculation_as_of, …" + "outputElided": null, + "outputShape": "object with 14 fields: status, direction, selected_revision_id, advances, declines, unchanged, excluded, unclassified, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -23129,27 +22838,27 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculateAdvanceDeclineRatio({\"series_id\":\"SYNTH:XNAS:ACTIVE-ISSUES:CLOSE\",\"record_id\":\"SYNTH-2026-01-05-R1\",\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"venue_id\":\"SYNTH:XNAS\",\"calendar_id\":\"SYNTH:XNAS-CALENDAR\",\"session_id\":\"regular-close\",\"universe_id\":\"SYNTH:ACTIVE-COMMON-STOCK\",\"universe_revision\":\"2026-01-05-final\",\"listing_id_scheme\":\"synthetic-stable-listing-id-v1\",\"security_type_policy\":\"synthetic-common-stock-only\",\"comparison_basis\":\"official-close-to-corporate-action-adjusted-comparable-prior-close\",\"corporate_action_policy\":\"synthetic-adjusted-prior-close-v1\"})", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F01-A02.json", + "call": "calculateAdvanceDeclineRatio({\"series_id\":\"SYNTH-ADR\",\"record_id\":\"ADR-R1\",\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"venue_id\":\"SYNTH-X\",\"calendar_id\":\"SYNTH-CAL\",\"session_id\":\"regular\",\"universe_id\":\"SYNTH-100\",\"universe_revision\":\"U1\",\"listing_id_scheme\":\"synthetic-listing-id\",\"security_type_policy\":\"common-equity\",\"comparison_basis\":\"comparable-prior-close\",\"corporate_action_policy\":\"provider-adjusted\"})", "args": [ { "value": { - "series_id": "SYNTH:XNAS:ACTIVE-ISSUES:CLOSE", - "record_id": "SYNTH-2026-01-05-R1", + "series_id": "SYNTH-ADR", + "record_id": "ADR-R1", "session_date": "2026-01-05", "effective_at": "2026-01-05T21:00:00Z", "available_at": "2026-01-05T21:05:00Z", - "venue_id": "SYNTH:XNAS", - "calendar_id": "SYNTH:XNAS-CALENDAR", - "session_id": "regular-close", - "universe_id": "SYNTH:ACTIVE-COMMON-STOCK", - "universe_revision": "2026-01-05-final", - "listing_id_scheme": "synthetic-stable-listing-id-v1", - "security_type_policy": "synthetic-common-stock-only", - "comparison_basis": "official-close-to-corporate-action-adjusted-comparable-prior-close", - "corporate_action_policy": "synthetic-adjusted-prior-close-v1" + "venue_id": "SYNTH-X", + "calendar_id": "SYNTH-CAL", + "session_id": "regular", + "universe_id": "SYNTH-100", + "universe_revision": "U1", + "listing_id_scheme": "synthetic-listing-id", + "security_type_policy": "common-equity", + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted" }, "elided": { "kind": "object", @@ -23164,26 +22873,21 @@ "advance_decline_ratio": 2, "direction": "advances_dominant", "observed_partition_ratio": 2, - "observed_partition_direction": "advances_dominant", - "selected_record_id": "SYNTH-2026-01-05-R1", + "selected_record_id": "ADR-R1", "selected_revision": 1, - "advances": 60, - "declines": 30, - "unchanged": 10, "excluded_count": 0, - "universe_size": 100, - "mover_count": 90 + "mover_count": 90, + "classified_count": 100, + "coverage_ratio": 1, + "is_provisional": false, + "reasons": [] }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 19 - }, - "outputShape": "object with 19 fields: evidence_state, ratio_state, advance_decline_ratio, direction, observed_partition_ratio, observed_partition_direction, selected_record_id, selected_revision, …" + "outputElided": null, + "outputShape": "object with 13 fields: evidence_state, ratio_state, advance_decline_ratio, direction, observed_partition_ratio, selected_record_id, selected_revision, excluded_count, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -23345,25 +23049,25 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculateCumulativeAdvanceDeclineLine({\"metric\":\"cumulative_issue_count_advance_decline_line\",\"series_id\":\"SYNTH-ADL-001\",\"continuity_id\":\"CONTINUITY-ALPHA\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-COMMON-STOCK-V1\",\"calendar_id\":\"SYNTH-2026-WEEKDAYS\",\"session_type\":\"regular\",\"comparison_basis\":\"adjusted-prior-regular-close\",\"seed\":0,\"seed_lineage_id\":\"SEED-ALPHA-0\",\"seed_effective_at\":\"2026-01-04T21:00:00Z\",\"seed_available_at\":\"2026-01-04T21:00:01Z\",\"expected_sessions\":[{\"session_sequence\":1,\"session_date\":\"2026-01-05\"},{\"session_sequence\":2,\"session_date\":\"2026-01-06\"},{\"session_sequence\":3,\"session_date\":\"2026-01-07\"}]}, [{\"event_id\":\"EV-001-R1\",\"ingest_sequence\":1,\"revision_number\":1,\"supersedes_event_id\":null,\"action\":\"upsert\",\"session_sequence\":1,\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:00:05Z\",\"series_id\":\"SYNTH-ADL-001\",\"continuity_id\":\"CONTINUITY-ALPHA\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-COMMON-STOCK-V1\",\"calendar_id\":\"SYNTH-2026-WEEKDAYS\"},{\"event_id\":\"EV-002-R1\",\"ingest_sequence\":2,\"revision_number\":1,\"supersedes_event_id\":null,\"action\":\"upsert\",\"session_sequence\":2,\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:00:05Z\",\"series_id\":\"SYNTH-ADL-001\",\"continuity_id\":\"CONTINUITY-ALPHA\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-COMMON-STOCK-V1\",\"calendar_id\":\"SYNTH-2026-WEEKDAYS\"},{\"event_id\":\"EV-003-R1\",\"ingest_sequence\":3,\"revision_number\":1,\"supersedes_event_id\":null,\"action\":\"upsert\",\"session_sequence\":3,\"session_date\":\"2026-01-07\",\"effective_at\":\"2026-01-07T21:00:00Z\",\"available_at\":\"2026-01-07T21:00:05Z\",\"series_id\":\"SYNTH-ADL-001\",\"continuity_id\":\"CONTINUITY-ALPHA\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-COMMON-STOCK-V1\",\"calendar_id\":\"SYNTH-2026-WEEKDAYS\"}], \"2026-01-11T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F01-A03.json", + "call": "calculateCumulativeAdvanceDeclineLine({\"metric\":\"cumulative_issue_count_advance_decline_line\",\"series_id\":\"SYNTH-AD\",\"continuity_id\":\"SYNTH-CONTINUITY\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-5\",\"calendar_id\":\"SYNTH-CAL\",\"session_type\":\"regular\",\"comparison_basis\":\"comparable-prior-close\",\"seed\":0,\"seed_lineage_id\":\"SEED-0\",\"seed_effective_at\":\"2026-01-04T21:00:00Z\",\"seed_available_at\":\"2026-01-04T21:05:00Z\",\"expected_sessions\":[{\"session_sequence\":1,\"session_date\":\"2026-01-05\"},{\"session_sequence\":2,\"session_date\":\"2026-01-06\"}]}, [{\"event_id\":\"AD-1\",\"ingest_sequence\":1,\"revision_number\":1,\"supersedes_event_id\":null,\"action\":\"upsert\",\"session_sequence\":1,\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"series_id\":\"SYNTH-AD\",\"continuity_id\":\"SYNTH-CONTINUITY\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-5\",\"calendar_id\":\"SYNTH-CAL\"},{\"event_id\":\"AD-2\",\"ingest_sequence\":2,\"revision_number\":1,\"supersedes_event_id\":null,\"action\":\"upsert\",\"session_sequence\":2,\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:05:00Z\",\"series_id\":\"SYNTH-AD\",\"continuity_id\":\"SYNTH-CONTINUITY\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-5\",\"calendar_id\":\"SYNTH-CAL\"}], \"2026-01-06T22:00:00Z\")", "args": [ { "value": { "metric": "cumulative_issue_count_advance_decline_line", - "series_id": "SYNTH-ADL-001", - "continuity_id": "CONTINUITY-ALPHA", + "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-COMMON-STOCK-V1", - "calendar_id": "SYNTH-2026-WEEKDAYS", + "universe_id": "SYNTH-5", + "calendar_id": "SYNTH-CAL", "session_type": "regular", - "comparison_basis": "adjusted-prior-regular-close", + "comparison_basis": "comparable-prior-close", "seed": 0, - "seed_lineage_id": "SEED-ALPHA-0", + "seed_lineage_id": "SEED-0", "seed_effective_at": "2026-01-04T21:00:00Z", - "seed_available_at": "2026-01-04T21:00:01Z", + "seed_available_at": "2026-01-04T21:05:00Z", "expected_sessions": [ { "session_sequence": 1, @@ -23372,10 +23076,6 @@ { "session_sequence": 2, "session_date": "2026-01-06" - }, - { - "session_sequence": 3, - "session_date": "2026-01-07" } ] }, @@ -23384,7 +23084,7 @@ { "value": [ { - "event_id": "EV-001-R1", + "event_id": "AD-1", "ingest_sequence": 1, "revision_number": 1, "supersedes_event_id": null, @@ -23392,15 +23092,15 @@ "session_sequence": 1, "session_date": "2026-01-05", "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:05Z", - "series_id": "SYNTH-ADL-001", - "continuity_id": "CONTINUITY-ALPHA", + "available_at": "2026-01-05T21:05:00Z", + "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-COMMON-STOCK-V1", - "calendar_id": "SYNTH-2026-WEEKDAYS" + "universe_id": "SYNTH-5", + "calendar_id": "SYNTH-CAL" }, { - "event_id": "EV-002-R1", + "event_id": "AD-2", "ingest_sequence": 2, "revision_number": 1, "supersedes_event_id": null, @@ -23408,112 +23108,46 @@ "session_sequence": 2, "session_date": "2026-01-06", "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:05Z", - "series_id": "SYNTH-ADL-001", - "continuity_id": "CONTINUITY-ALPHA", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-COMMON-STOCK-V1", - "calendar_id": "SYNTH-2026-WEEKDAYS" - }, - { - "event_id": "EV-003-R1", - "ingest_sequence": 3, - "revision_number": 1, - "supersedes_event_id": null, - "action": "upsert", - "session_sequence": 3, - "session_date": "2026-01-07", - "effective_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:05Z", - "series_id": "SYNTH-ADL-001", - "continuity_id": "CONTINUITY-ALPHA", + "available_at": "2026-01-06T21:05:00Z", + "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-COMMON-STOCK-V1", - "calendar_id": "SYNTH-2026-WEEKDAYS" + "universe_id": "SYNTH-5", + "calendar_id": "SYNTH-CAL" } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 5 - } + "elided": null }, { - "value": "2026-01-11T00:00:00Z", + "value": "2026-01-06T22:00:00Z", "elided": null } ], "output": { "status": "resolved", "reasons": [], - "knowledge_cutoff": "2026-01-11T00:00:00Z", - "seed": 0, - "points": [ - { + "final_value": 1, + "contains_provisional": false, + "ignored_future_event_count": 0, + "points": { + "0": { "session_sequence": 1, - "session_date": "2026-01-05", - "event_id": "EV-001-R1", - "revision_number": 1, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:00:05Z", - "advances": 60, - "declines": 30, - "unchanged": 8, - "excluded": 2, - "unclassified": 0, - "universe_size": 100, - "net_advances": 30, - "cumulative_line": 30 + "net_advances": 2, + "cumulative_line": 2 }, - { + "1": { "session_sequence": 2, - "session_date": "2026-01-06", - "event_id": "EV-002-R1", - "revision_number": 1, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:00:05Z", - "advances": 35, - "declines": 55, - "unchanged": 8, - "excluded": 2, - "unclassified": 0, - "universe_size": 100, - "net_advances": -20, - "cumulative_line": 10 - }, - { - "session_sequence": 3, - "session_date": "2026-01-07", - "event_id": "EV-003-R1", - "revision_number": 1, - "effective_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:00:05Z", - "advances": 40, - "declines": 40, - "unchanged": 18, - "excluded": 2, - "unclassified": 0, - "universe_size": 100, - "net_advances": 0, - "cumulative_line": 10 + "net_advances": -1, + "cumulative_line": 1 } - ], - "final_value": 20, - "causal_prefix_diagnostic": [], - "missing_sessions": [], - "cancelled_sessions": [], - "contains_provisional": false, - "ignored_future_event_count": 0, - "recompute_from_session": null, - "blocked_from_session": null, - "metric": "cumulative_issue_count_advance_decline_line" + } }, "outputElided": null, - "outputShape": "object with 14 fields: status, reasons, knowledge_cutoff, seed, points, final_value, causal_prefix_diagnostic, missing_sessions, …" + "outputShape": "object with 6 fields: status, reasons, final_value, contains_provisional, ignored_future_event_count, points" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -23647,73 +23281,53 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculateNormalizedAdLine([{\"revision\":1,\"supersedes_revision\":null,\"event_type\":\"upsert\",\"venue_id\":\"SYNTH:XNAS\",\"universe_id\":\"SYNTH:ACTIVE-100\",\"calendar_id\":\"SYNTH:XNAS-REGULAR\",\"session\":\"regular\",\"comparison_basis\":\"official-close-to-comparable-prior-close\",\"corporate_action_policy\":\"point-in-time-listing-continuity-v1\",\"stable_id_scheme\":\"synthetic-listing-id-v1\",\"methodology_id\":\"mover-normalized-ad-line-v1\",\"denominator_policy\":\"movers\",\"seed\":0,\"scale\":100},{\"revision\":1,\"supersedes_revision\":null,\"event_type\":\"upsert\",\"venue_id\":\"SYNTH:XNAS\",\"universe_id\":\"SYNTH:ACTIVE-100\",\"calendar_id\":\"SYNTH:XNAS-REGULAR\",\"session\":\"regular\",\"comparison_basis\":\"official-close-to-comparable-prior-close\",\"corporate_action_policy\":\"point-in-time-listing-continuity-v1\",\"stable_id_scheme\":\"synthetic-listing-id-v1\",\"methodology_id\":\"mover-normalized-ad-line-v1\",\"denominator_policy\":\"movers\",\"seed\":0,\"scale\":100},{\"revision\":1,\"supersedes_revision\":null,\"event_type\":\"upsert\",\"venue_id\":\"SYNTH:XNAS\",\"universe_id\":\"SYNTH:ACTIVE-100\",\"calendar_id\":\"SYNTH:XNAS-REGULAR\",\"session\":\"regular\",\"comparison_basis\":\"official-close-to-comparable-prior-close\",\"corporate_action_policy\":\"point-in-time-listing-continuity-v1\",\"stable_id_scheme\":\"synthetic-listing-id-v1\",\"methodology_id\":\"mover-normalized-ad-line-v1\",\"denominator_policy\":\"movers\",\"seed\":0,\"scale\":100}], {\"cutoff\":\"2026-02-02T00:00:00Z\",\"expectedStartSequence\":1,\"expectedEndSequence\":20,\"initialValue\":0,\"scale\":100,\"minimumCoverage\":0.95})", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F01-A04.json", + "call": "calculateNormalizedAdLine([{\"event_id\":\"NAD-1\",\"revision\":1,\"supersedes_revision\":null,\"event_type\":\"upsert\",\"session_sequence\":1,\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-100\",\"calendar_id\":\"SYNTH-CAL\",\"session\":\"regular\",\"comparison_basis\":\"comparable-prior-close\",\"corporate_action_policy\":\"provider-adjusted\"},{\"event_id\":\"NAD-2\",\"revision\":1,\"supersedes_revision\":null,\"event_type\":\"upsert\",\"session_sequence\":2,\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:05:00Z\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-100\",\"calendar_id\":\"SYNTH-CAL\",\"session\":\"regular\",\"comparison_basis\":\"comparable-prior-close\",\"corporate_action_policy\":\"provider-adjusted\"}], {\"cutoff\":\"2026-01-06T22:00:00Z\",\"expectedStartSequence\":1,\"expectedEndSequence\":2,\"initialValue\":0,\"scale\":100,\"minimumCoverage\":0.95})", "args": [ { "value": [ { + "event_id": "NAD-1", "revision": 1, "supersedes_revision": null, "event_type": "upsert", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-100", - "calendar_id": "SYNTH:XNAS-REGULAR", - "session": "regular", - "comparison_basis": "official-close-to-comparable-prior-close", - "corporate_action_policy": "point-in-time-listing-continuity-v1", - "stable_id_scheme": "synthetic-listing-id-v1", - "methodology_id": "mover-normalized-ad-line-v1", - "denominator_policy": "movers", - "seed": 0, - "scale": 100 - }, - { - "revision": 1, - "supersedes_revision": null, - "event_type": "upsert", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-100", - "calendar_id": "SYNTH:XNAS-REGULAR", + "session_sequence": 1, + "session_date": "2026-01-05", + "effective_at": "2026-01-05T21:00:00Z", + "available_at": "2026-01-05T21:05:00Z", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-100", + "calendar_id": "SYNTH-CAL", "session": "regular", - "comparison_basis": "official-close-to-comparable-prior-close", - "corporate_action_policy": "point-in-time-listing-continuity-v1", - "stable_id_scheme": "synthetic-listing-id-v1", - "methodology_id": "mover-normalized-ad-line-v1", - "denominator_policy": "movers", - "seed": 0, - "scale": 100 + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted" }, { + "event_id": "NAD-2", "revision": 1, "supersedes_revision": null, "event_type": "upsert", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-100", - "calendar_id": "SYNTH:XNAS-REGULAR", + "session_sequence": 2, + "session_date": "2026-01-06", + "effective_at": "2026-01-06T21:00:00Z", + "available_at": "2026-01-06T21:05:00Z", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-100", + "calendar_id": "SYNTH-CAL", "session": "regular", - "comparison_basis": "official-close-to-comparable-prior-close", - "corporate_action_policy": "point-in-time-listing-continuity-v1", - "stable_id_scheme": "synthetic-listing-id-v1", - "methodology_id": "mover-normalized-ad-line-v1", - "denominator_policy": "movers", - "seed": 0, - "scale": 100 + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted" } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 20 - } + "elided": null }, { "value": { - "cutoff": "2026-02-02T00:00:00Z", + "cutoff": "2026-01-06T22:00:00Z", "expectedStartSequence": 1, - "expectedEndSequence": 20, + "expectedEndSequence": 2, "initialValue": 0, "scale": 100, "minimumCoverage": 0.95 @@ -23724,69 +23338,28 @@ "output": { "state": "resolved", "reason_codes": [], - "points": [ - { - "session_sequence": 1, - "session_date": "2026-01-05", - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:05:00Z", - "event_id": "S01", - "revision": 1, + "ignored_future_revisions": 0, + "points": { + "0": { "net_advances": 30, "mover_count": 90, - "normalized_breadth": 0.3333333333333333, "scaled_contribution": 33.33333333333333, - "normalized_line": 33.33333333333333, - "coverage_ratio": 0.98, - "daily_direction": "advancing", - "metric": "mover_normalized_advance_decline_line" + "normalized_line": 33.33333333333333 }, - { - "session_sequence": 2, - "session_date": "2026-01-06", - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:05:00Z", - "event_id": "S02", - "revision": 1, + "1": { "net_advances": -20, "mover_count": 90, - "normalized_breadth": -0.2222222222222222, "scaled_contribution": -22.22222222222222, - "normalized_line": 11.111111111111107, - "coverage_ratio": 0.98, - "daily_direction": "declining", - "metric": "mover_normalized_advance_decline_line" - }, - { - "session_sequence": 3, - "session_date": "2026-01-07", - "effective_at": "2026-01-07T21:00:00Z", - "available_at": "2026-01-07T21:05:00Z", - "event_id": "S03", - "revision": 1, - "net_advances": 0, - "mover_count": 80, - "normalized_breadth": 0, - "scaled_contribution": 0, - "normalized_line": 11.111111111111107, - "coverage_ratio": 0.98, - "daily_direction": "balanced", - "metric": "mover_normalized_advance_decline_line" + "normalized_line": 11.111111111111107 } - ], - "ignored_future_revisions": 0, - "denominator_policy": "movers", - "initial_value": 0, - "scale": 100, - "minimum_coverage": 0.95, - "cutoff": "2026-02-02T00:00:00Z" + } }, "outputElided": null, - "outputShape": "object with 9 fields: state, reason_codes, points, ignored_future_revisions, denominator_policy, initial_value, scale, minimum_coverage, …" + "outputShape": "object with 4 fields: state, reason_codes, ignored_future_revisions, points" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -23911,31 +23484,31 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "evaluateAbsoluteBreadthIndex({\"decision_time\":\"2026-01-05T21:05:00Z\",\"metric_variant\":\"raw_issue_count\",\"records\":[{\"record_id\":\"synthetic-r1\",\"revision\":1,\"supersedes_record_id\":null,\"kind\":\"observation\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:01:00Z\",\"is_final\":true,\"session_date\":\"2026-01-05\",\"venue_id\":\"SYNTH:XNAS\",\"universe_id\":\"SYNTH:ACTIVE-100\",\"universe_revision\":\"2026-01-05-r1\",\"session_id\":\"regular\",\"calendar_id\":\"SYNTH:XNAS-2026\",\"comparison_basis\":\"official-close-to-adjusted-comparable-prior-close\"}]})", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F01-A05.json", + "call": "evaluateAbsoluteBreadthIndex({\"decision_time\":\"2026-01-05T22:00:00Z\",\"metric_variant\":\"raw_issue_count\",\"records\":[{\"record_id\":\"ABI-R1\",\"revision\":1,\"supersedes_record_id\":null,\"kind\":\"observation\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:05:00Z\",\"is_final\":true,\"session_date\":\"2026-01-05\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-100\",\"universe_revision\":\"U1\",\"session_id\":\"regular\",\"calendar_id\":\"SYNTH-CAL\",\"comparison_basis\":\"comparable-prior-close\"}]})", "args": [ { "value": { - "decision_time": "2026-01-05T21:05:00Z", + "decision_time": "2026-01-05T22:00:00Z", "metric_variant": "raw_issue_count", "records": [ { - "record_id": "synthetic-r1", + "record_id": "ABI-R1", "revision": 1, "supersedes_record_id": null, "kind": "observation", "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:01:00Z", + "available_at": "2026-01-05T21:05:00Z", "is_final": true, "session_date": "2026-01-05", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-100", - "universe_revision": "2026-01-05-r1", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-100", + "universe_revision": "U1", "session_id": "regular", - "calendar_id": "SYNTH:XNAS-2026", - "comparison_basis": "official-close-to-adjusted-comparable-prior-close" + "calendar_id": "SYNTH-CAL", + "comparison_basis": "comparable-prior-close" } ] }, @@ -23943,31 +23516,25 @@ } ], "output": { - "session_date": "2026-01-05", - "venue_id": "SYNTH:XNAS", - "universe_id": "SYNTH:ACTIVE-100", - "universe_revision": "2026-01-05-r1", - "session_id": "regular", - "calendar_id": "SYNTH:XNAS-2026", - "comparison_basis": "official-close-to-adjusted-comparable-prior-close", - "corporate_action_policy": "synthetic-split-and-distribution-adjusted-v1", - "listing_identifier_scheme": "synthetic-stable-listing-id-v1", - "advances": 60, - "declines": 30, - "unchanged": 8, - "excluded": 2, - "missing": 0 - }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 32 + "evaluation_state": "resolved", + "publishable": true, + "reason_codes": [], + "record_id": "ABI-R1", + "revision": 1, + "is_provisional": false, + "net_advances": 30, + "absolute_breadth_index": 30, + "mover_count": 90, + "classified_count": 98, + "coverage_ratio": 0.98, + "breadth_state": "advances_imbalanced" }, - "outputShape": "object with 32 fields: session_date, venue_id, universe_id, universe_revision, session_id, calendar_id, comparison_basis, corporate_action_policy, …" + "outputElided": null, + "outputShape": "object with 12 fields: evaluation_state, publishable, reason_codes, record_id, revision, is_provisional, net_advances, absolute_breadth_index, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -24093,9 +23660,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A01.json", "call": "calculateMcClellanValues([0,0,0,0,0,0])", "args": [ { @@ -24114,42 +23681,56 @@ } } ], - "output": [ - { - "observation": 1, - "net_advances": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "status": "warming_fast" - }, - { - "observation": 2, - "net_advances": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "status": "warming_fast" - }, - { - "observation": 3, - "net_advances": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "status": "warming_fast" + "output": { + "38": { + "observation": 39, + "fast_ema": 0, + "slow_ema": 0, + "oscillator": 0, + "status": "ready" + }, + "39": { + "observation": 40, + "fast_ema": 10, + "slow_ema": 5, + "oscillator": 5, + "status": "ready" + }, + "40": { + "observation": 41, + "fast_ema": 19, + "slow_ema": 9.75, + "oscillator": 9.25, + "status": "ready" + }, + "41": { + "observation": 42, + "fast_ema": 7.1, + "slow_ema": 4.2625, + "oscillator": 2.8375, + "status": "ready" + }, + "42": { + "observation": 43, + "fast_ema": 6.39, + "slow_ema": 4.049375, + "oscillator": 2.340625, + "status": "ready" + }, + "43": { + "observation": 44, + "fast_ema": -4.249, + "slow_ema": -1.15309375, + "oscillator": -3.09590625, + "status": "ready" } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 44 }, - "outputShape": "array of 44 objects" + "outputElided": null, + "outputShape": "object with 6 fields: 38, 39, 40, 41, 42, 43" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -24304,10 +23885,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-05\",\"session_sequence\":2,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-06\",\"session_sequence\":3,\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A02.json", + "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", "args": [ { "value": [ @@ -24326,45 +23907,9 @@ "volume_unit": "shares", "volume_adjustment_basis": "reported-unadjusted", "advances": 100 - }, - { - "session_date": "2026-01-05", - "session_sequence": 2, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 - }, - { - "session_date": "2026-01-06", - "session_sequence": 3, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 60 - } + "elided": null }, { "value": "2026-04-01T00:00:00Z", @@ -24373,51 +23918,16 @@ ], "output": { "status": "resolved", - "reason_codes": [], - "points": [ - { - "observation": 1, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-02" - }, - { - "observation": 2, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-05" - }, - { - "observation": 3, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-06" - } - ], - "latest_oscillator": 4.329247050580548, + "latest_oscillator": null, "latest_index_value": null, - "ignored_future_records": 0, - "seed_policy": "sma_19_39", - "initial_index": null + "ignored_future_records": 0 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason_codes, points, latest_oscillator, latest_index_value, ignored_future_records, seed_policy, initial_index" + "outputShape": "object with 4 fields: status, latest_oscillator, latest_index_value, ignored_future_records" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -24542,10 +24052,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-05\",\"session_sequence\":2,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-06\",\"session_sequence\":3,\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A03.json", + "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", "args": [ { "value": [ @@ -24564,45 +24074,9 @@ "volume_unit": "shares", "volume_adjustment_basis": "reported-unadjusted", "advances": 100 - }, - { - "session_date": "2026-01-05", - "session_sequence": 2, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 - }, - { - "session_date": "2026-01-06", - "session_sequence": 3, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 60 - } + "elided": null }, { "value": "2026-04-01T00:00:00Z", @@ -24611,51 +24085,16 @@ ], "output": { "status": "resolved", - "reason_codes": [], - "points": [ - { - "observation": 1, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-02" - }, - { - "observation": 2, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-05" - }, - { - "observation": 3, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-06" - } - ], - "latest_oscillator": 0.8658494101161072, - "latest_index_value": 1086.3098267234077, - "ignored_future_records": 0, - "seed_policy": "sma_19_39", - "initial_index": 1000 + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason_codes, points, latest_oscillator, latest_index_value, ignored_future_records, seed_policy, initial_index" + "outputShape": "object with 4 fields: status, latest_oscillator, latest_index_value, ignored_future_records" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -24780,10 +24219,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-05\",\"session_sequence\":2,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-06\",\"session_sequence\":3,\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A04.json", + "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", "args": [ { "value": [ @@ -24802,45 +24241,9 @@ "volume_unit": "shares", "volume_adjustment_basis": "reported-unadjusted", "advances": 100 - }, - { - "session_date": "2026-01-05", - "session_sequence": 2, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 - }, - { - "session_date": "2026-01-06", - "session_sequence": 3, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 60 - } + "elided": null }, { "value": "2026-04-01T00:00:00Z", @@ -24849,51 +24252,16 @@ ], "output": { "status": "resolved", - "reason_codes": [], - "points": [ - { - "observation": 1, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-02" - }, - { - "observation": 2, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-05" - }, - { - "observation": 3, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-06" - } - ], - "latest_oscillator": 4.329247050580548, - "latest_index_value": 431.54913361703746, - "ignored_future_records": 0, - "seed_policy": "sma_19_39", - "initial_index": 0 + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason_codes, points, latest_oscillator, latest_index_value, ignored_future_records, seed_policy, initial_index" + "outputShape": "object with 4 fields: status, latest_oscillator, latest_index_value, ignored_future_records" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -25024,10 +24392,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-05\",\"session_sequence\":2,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-06\",\"session_sequence\":3,\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A05.json", + "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", "args": [ { "value": [ @@ -25046,45 +24414,9 @@ "volume_unit": "shares", "volume_adjustment_basis": "reported-unadjusted", "advances": 100 - }, - { - "session_date": "2026-01-05", - "session_sequence": 2, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 - }, - { - "session_date": "2026-01-06", - "session_sequence": 3, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 60 - } + "elided": null }, { "value": "2026-04-01T00:00:00Z", @@ -25093,51 +24425,16 @@ ], "output": { "status": "resolved", - "reason_codes": [], - "points": [ - { - "observation": 1, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-02" - }, - { - "observation": 2, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-05" - }, - { - "observation": 3, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-06" - } - ], - "latest_oscillator": 8658.494101161108, + "latest_oscillator": null, "latest_index_value": null, - "ignored_future_records": 0, - "seed_policy": "sma_19_39", - "initial_index": null + "ignored_future_records": 0 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason_codes, points, latest_oscillator, latest_index_value, ignored_future_records, seed_policy, initial_index" + "outputShape": "object with 4 fields: status, latest_oscillator, latest_index_value, ignored_future_records" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -25268,10 +24565,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-05\",\"session_sequence\":2,\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100},{\"session_date\":\"2026-01-06\",\"session_sequence\":3,\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F02-A06.json", + "call": "calculate([{\"session_date\":\"2026-01-02\",\"session_sequence\":1,\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:20:00Z\",\"revision\":0,\"event_type\":\"upsert\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-STABLE-200\",\"methodology_id\":\"close-vs-comparable-prior-close-v1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"volume_unit\":\"shares\",\"volume_adjustment_basis\":\"reported-unadjusted\",\"advances\":100}], \"2026-04-01T00:00:00Z\")", "args": [ { "value": [ @@ -25290,45 +24587,9 @@ "volume_unit": "shares", "volume_adjustment_basis": "reported-unadjusted", "advances": 100 - }, - { - "session_date": "2026-01-05", - "session_sequence": 2, - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 - }, - { - "session_date": "2026-01-06", - "session_sequence": 3, - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:20:00Z", - "revision": 0, - "event_type": "upsert", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-STABLE-200", - "methodology_id": "close-vs-comparable-prior-close-v1", - "calendar_id": "SYNTH-WEEKDAY", - "volume_unit": "shares", - "volume_adjustment_basis": "reported-unadjusted", - "advances": 100 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 60 - } + "elided": null }, { "value": "2026-04-01T00:00:00Z", @@ -25337,51 +24598,16 @@ ], "output": { "status": "resolved", - "reason_codes": [], - "points": [ - { - "observation": 1, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-02" - }, - { - "observation": 2, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-05" - }, - { - "observation": 3, - "input_value": 0, - "fast_ema": null, - "slow_ema": null, - "oscillator": null, - "index_value": null, - "status": "warming_fast", - "session_date": "2026-01-06" - } - ], - "latest_oscillator": 8658.494101161108, - "latest_index_value": 863098.267234075, - "ignored_future_records": 0, - "seed_policy": "sma_19_39", - "initial_index": 0 + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason_codes, points, latest_oscillator, latest_index_value, ignored_future_records, seed_policy, initial_index" + "outputShape": "object with 4 fields: status, latest_oscillator, latest_index_value, ignored_future_records" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -25517,106 +24743,50 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":9,\"new_lows\":3,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":4,\"new_lows\":8,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A01.json", + "call": "calculate([{\"session_date\":\"2026-01-15\",\"available_at\":\"2026-01-15T21:30:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HIGH-LOW-12\",\"methodology_id\":\"synthetic-high-low-v1\",\"lookback_sessions\":252,\"new_highs\":2,\"new_lows\":10,\"eligible_issues\":12,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", "args": [ { "value": [ { - "session_date": "2026-01-02", - "effective_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:25:00Z", + "session_date": "2026-01-15", + "available_at": "2026-01-15T21:30:00Z", "source_evidence_state": "ready", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", "lookback_sessions": 252, - "new_highs": 9, - "new_lows": 3, - "eligible_issues": 120, - "excluded_issues": 4, - "overlap_issues": 0 - }, - { - "session_date": "2026-01-05", - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:25:00Z", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", - "lookback_sessions": 252, - "new_highs": 7, - "new_lows": 5, - "eligible_issues": 120, - "excluded_issues": 4, - "overlap_issues": 0 - }, - { - "session_date": "2026-01-06", - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:25:00Z", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", - "lookback_sessions": 252, - "new_highs": 4, - "new_lows": 8, - "eligible_issues": 120, - "excluded_issues": 4, + "new_highs": 2, + "new_lows": 10, + "eligible_issues": 12, "overlap_issues": 0 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 30 - } + "elided": null }, { "value": "2026-03-01T00:00:00Z", "elided": null } ], - "output": [ - { - "session_date": "2026-01-02", - "new_highs": 9, - "new_lows": 3, - "value": 6, - "status": "resolved", - "reason": null - }, - { - "session_date": "2026-01-05", - "new_highs": 7, - "new_lows": 5, - "value": 2, - "status": "resolved", - "reason": null - }, - { - "session_date": "2026-01-06", - "new_highs": 4, - "new_lows": 8, - "value": -4, + "output": { + "0": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": -8, "status": "resolved", "reason": null } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 30 }, - "outputShape": "array of 30 objects" + "outputElided": null, + "outputShape": "object with 1 field: 0" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -25738,106 +24908,50 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":9,\"new_lows\":3,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":4,\"new_lows\":8,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A02.json", + "call": "calculate([{\"session_date\":\"2026-01-15\",\"available_at\":\"2026-01-15T21:30:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HIGH-LOW-12\",\"methodology_id\":\"synthetic-high-low-v1\",\"lookback_sessions\":252,\"new_highs\":2,\"new_lows\":10,\"eligible_issues\":12,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", "args": [ { "value": [ { - "session_date": "2026-01-02", - "effective_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:25:00Z", + "session_date": "2026-01-15", + "available_at": "2026-01-15T21:30:00Z", "source_evidence_state": "ready", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", "lookback_sessions": 252, - "new_highs": 9, - "new_lows": 3, - "eligible_issues": 120, - "excluded_issues": 4, - "overlap_issues": 0 - }, - { - "session_date": "2026-01-05", - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:25:00Z", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", - "lookback_sessions": 252, - "new_highs": 7, - "new_lows": 5, - "eligible_issues": 120, - "excluded_issues": 4, - "overlap_issues": 0 - }, - { - "session_date": "2026-01-06", - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:25:00Z", - "source_evidence_state": "ready", - "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", - "lookback_sessions": 252, - "new_highs": 4, - "new_lows": 8, - "eligible_issues": 120, - "excluded_issues": 4, + "new_highs": 2, + "new_lows": 10, + "eligible_issues": 12, "overlap_issues": 0 } ], - "elided": { - "kind": "array", - "shown": 3, - "total": 30 - } + "elided": null }, { "value": "2026-03-01T00:00:00Z", "elided": null } ], - "output": [ - { - "session_date": "2026-01-02", - "new_highs": 9, - "new_lows": 3, - "value": 3, - "status": "resolved", - "reason": null - }, - { - "session_date": "2026-01-05", - "new_highs": 7, - "new_lows": 5, - "value": 1.4, - "status": "resolved", - "reason": null - }, - { - "session_date": "2026-01-06", - "new_highs": 4, - "new_lows": 8, - "value": 0.5, + "output": { + "0": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": 0.2, "status": "resolved", "reason": null } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 30 }, - "outputShape": "array of 30 objects" + "outputElided": null, + "outputShape": "object with 1 field: 0" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -25959,63 +25073,57 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "calculate([{\"session_date\":\"2026-01-02\",\"effective_at\":\"2026-01-02T21:00:00Z\",\"available_at\":\"2026-01-02T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":9,\"new_lows\":3,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-05\",\"effective_at\":\"2026-01-05T21:00:00Z\",\"available_at\":\"2026-01-05T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0},{\"session_date\":\"2026-01-06\",\"effective_at\":\"2026-01-06T21:00:00Z\",\"available_at\":\"2026-01-06T21:25:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HL-120\",\"methodology_id\":\"session-high-low-vs-prior-252-sessions-v1\",\"lookback_sessions\":252,\"new_highs\":4,\"new_lows\":8,\"eligible_issues\":120,\"excluded_issues\":4,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A03.json", + "call": "calculate([{\"session_date\":\"2026-01-06\",\"available_at\":\"2026-01-06T21:30:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HIGH-LOW-12\",\"methodology_id\":\"synthetic-high-low-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":12,\"overlap_issues\":0},{\"session_date\":\"2026-01-07\",\"available_at\":\"2026-01-07T21:30:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HIGH-LOW-12\",\"methodology_id\":\"synthetic-high-low-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":12,\"overlap_issues\":0},{\"session_date\":\"2026-01-08\",\"available_at\":\"2026-01-08T21:30:00Z\",\"source_evidence_state\":\"ready\",\"venue_id\":\"SYNTH-X\",\"universe_id\":\"SYNTH-HIGH-LOW-12\",\"methodology_id\":\"synthetic-high-low-v1\",\"lookback_sessions\":252,\"new_highs\":7,\"new_lows\":5,\"eligible_issues\":12,\"overlap_issues\":0}], \"2026-03-01T00:00:00Z\")", "args": [ { "value": [ { - "session_date": "2026-01-02", - "effective_at": "2026-01-02T21:00:00Z", - "available_at": "2026-01-02T21:25:00Z", + "session_date": "2026-01-06", + "available_at": "2026-01-06T21:30:00Z", "source_evidence_state": "ready", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", "lookback_sessions": 252, - "new_highs": 9, - "new_lows": 3, - "eligible_issues": 120, - "excluded_issues": 4, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, "overlap_issues": 0 }, { - "session_date": "2026-01-05", - "effective_at": "2026-01-05T21:00:00Z", - "available_at": "2026-01-05T21:25:00Z", + "session_date": "2026-01-07", + "available_at": "2026-01-07T21:30:00Z", "source_evidence_state": "ready", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", "lookback_sessions": 252, "new_highs": 7, "new_lows": 5, - "eligible_issues": 120, - "excluded_issues": 4, + "eligible_issues": 12, "overlap_issues": 0 }, { - "session_date": "2026-01-06", - "effective_at": "2026-01-06T21:00:00Z", - "available_at": "2026-01-06T21:25:00Z", + "session_date": "2026-01-08", + "available_at": "2026-01-08T21:30:00Z", "source_evidence_state": "ready", "venue_id": "SYNTH-X", - "universe_id": "SYNTH-HL-120", - "methodology_id": "session-high-low-vs-prior-252-sessions-v1", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", "lookback_sessions": 252, - "new_highs": 4, - "new_lows": 8, - "eligible_issues": 120, - "excluded_issues": 4, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, "overlap_issues": 0 } ], "elided": { "kind": "array", "shown": 3, - "total": 30 + "total": 10 } }, { @@ -26023,42 +25131,22 @@ "elided": null } ], - "output": [ - { - "session_date": "2026-01-02", - "new_highs": 9, - "new_lows": 3, - "value": null, - "status": "warming", - "reason": "requires_10_sessions" - }, - { - "session_date": "2026-01-05", - "new_highs": 7, - "new_lows": 5, - "value": null, - "status": "warming", - "reason": "requires_10_sessions" - }, - { - "session_date": "2026-01-06", - "new_highs": 4, - "new_lows": 8, - "value": null, - "status": "warming", - "reason": "requires_10_sessions" + "output": { + "9": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": 54.166666666666664, + "status": "resolved", + "reason": null } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 30 }, - "outputShape": "array of 30 objects" + "outputElided": null, + "outputShape": "object with 1 field: 9" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -26185,65 +25273,29 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "evaluateSnapshot({\"session_date\":\"2026-06-30\",\"effective_at\":\"2026-06-30T21:00:00Z\",\"available_at\":\"2026-06-30T21:30:00Z\",\"universe_id\":\"SYNTH-TREND-24\",\"universe_revision\":\"2026-06-30-r1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"price_field\":\"adjusted_close\",\"window_sessions\":20,\"securities\":[{\"security_id\":\"SYNTH-001\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[50,50,50,50,50,50]},{\"security_id\":\"SYNTH-002\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[52,52,52,52,52,52]},{\"security_id\":\"SYNTH-003\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[54,54,54,54,54,54]}]}, \"2026-06-30T22:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A04.json", + "call": "evaluateSnapshot({\"window_sessions\":20,\"price_field\":\"adjusted_close\",\"securities\":[{\"security_id\":\"SYNTH-ABOVE\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[100,100,100,100,100,100]}]}, \"2026-06-30T22:00:00Z\")", "args": [ { "value": { - "session_date": "2026-06-30", - "effective_at": "2026-06-30T21:00:00Z", - "available_at": "2026-06-30T21:30:00Z", - "universe_id": "SYNTH-TREND-24", - "universe_revision": "2026-06-30-r1", - "calendar_id": "SYNTH-WEEKDAY", - "price_field": "adjusted_close", "window_sessions": 20, + "price_field": "adjusted_close", "securities": [ { - "security_id": "SYNTH-001", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 50, - 50, - 50, - 50, - 50, - 50 - ] - }, - { - "security_id": "SYNTH-002", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 52, - 52, - 52, - 52, - 52, - 52 - ] - }, - { - "security_id": "SYNTH-003", + "security_id": "SYNTH-ABOVE", "member_at_session": true, "source_evidence_state": "ready", "available_at": "2026-06-30T21:30:00Z", "adjustment_basis": "split-adjusted-price-return", "prices": [ - 54, - 54, - 54, - 54, - 54, - 54 + 100, + 100, + 100, + 100, + 100, + 100 ] } ] @@ -26259,40 +25311,17 @@ "status": "resolved", "reason": null, "window_sessions": 20, - "eligible_count": 24, - "above_count": 15, - "equal_count": 1, - "percent_above": 62.5, - "rows": [ - { - "security_id": "SYNTH-001", - "current_price": 60, - "moving_average": 50.5, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-002", - "current_price": 62, - "moving_average": 52.5, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-003", - "current_price": 64, - "moving_average": 54.5, - "above": true, - "equal": false - } - ] + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above, rows" + "outputShape": "object with 7 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -26413,65 +25442,29 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "evaluateSnapshot({\"session_date\":\"2026-06-30\",\"effective_at\":\"2026-06-30T21:00:00Z\",\"available_at\":\"2026-06-30T21:30:00Z\",\"universe_id\":\"SYNTH-TREND-24\",\"universe_revision\":\"2026-06-30-r1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"price_field\":\"adjusted_close\",\"window_sessions\":50,\"securities\":[{\"security_id\":\"SYNTH-001\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[50,50,50,50,50,50]},{\"security_id\":\"SYNTH-002\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[52,52,52,52,52,52]},{\"security_id\":\"SYNTH-003\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[54,54,54,54,54,54]}]}, \"2026-06-30T22:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A05.json", + "call": "evaluateSnapshot({\"window_sessions\":50,\"price_field\":\"adjusted_close\",\"securities\":[{\"security_id\":\"SYNTH-ABOVE\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[100,100,100,100,100,100]}]}, \"2026-06-30T22:00:00Z\")", "args": [ { "value": { - "session_date": "2026-06-30", - "effective_at": "2026-06-30T21:00:00Z", - "available_at": "2026-06-30T21:30:00Z", - "universe_id": "SYNTH-TREND-24", - "universe_revision": "2026-06-30-r1", - "calendar_id": "SYNTH-WEEKDAY", - "price_field": "adjusted_close", "window_sessions": 50, + "price_field": "adjusted_close", "securities": [ { - "security_id": "SYNTH-001", + "security_id": "SYNTH-ABOVE", "member_at_session": true, "source_evidence_state": "ready", "available_at": "2026-06-30T21:30:00Z", "adjustment_basis": "split-adjusted-price-return", "prices": [ - 50, - 50, - 50, - 50, - 50, - 50 - ] - }, - { - "security_id": "SYNTH-002", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 52, - 52, - 52, - 52, - 52, - 52 - ] - }, - { - "security_id": "SYNTH-003", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 54, - 54, - 54, - 54, - 54, - 54 + 100, + 100, + 100, + 100, + 100, + 100 ] } ] @@ -26487,40 +25480,17 @@ "status": "resolved", "reason": null, "window_sessions": 50, - "eligible_count": 24, - "above_count": 15, - "equal_count": 1, - "percent_above": 62.5, - "rows": [ - { - "security_id": "SYNTH-001", - "current_price": 60, - "moving_average": 50.2, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-002", - "current_price": 62, - "moving_average": 52.2, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-003", - "current_price": 64, - "moving_average": 54.2, - "above": true, - "equal": false - } - ] + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above, rows" + "outputShape": "object with 7 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -26641,65 +25611,29 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "evaluateSnapshot({\"session_date\":\"2026-06-30\",\"effective_at\":\"2026-06-30T21:00:00Z\",\"available_at\":\"2026-06-30T21:30:00Z\",\"universe_id\":\"SYNTH-TREND-24\",\"universe_revision\":\"2026-06-30-r1\",\"calendar_id\":\"SYNTH-WEEKDAY\",\"price_field\":\"adjusted_close\",\"window_sessions\":200,\"securities\":[{\"security_id\":\"SYNTH-001\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[50,50,50,50,50,50]},{\"security_id\":\"SYNTH-002\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[52,52,52,52,52,52]},{\"security_id\":\"SYNTH-003\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[54,54,54,54,54,54]}]}, \"2026-06-30T22:00:00Z\")", + "origin": "fixture", + "verified": true, + "source": "fixture:D04-F03-A06.json", + "call": "evaluateSnapshot({\"window_sessions\":200,\"price_field\":\"adjusted_close\",\"securities\":[{\"security_id\":\"SYNTH-ABOVE\",\"member_at_session\":true,\"source_evidence_state\":\"ready\",\"available_at\":\"2026-06-30T21:30:00Z\",\"adjustment_basis\":\"split-adjusted-price-return\",\"prices\":[100,100,100,100,100,100]}]}, \"2026-06-30T22:00:00Z\")", "args": [ { "value": { - "session_date": "2026-06-30", - "effective_at": "2026-06-30T21:00:00Z", - "available_at": "2026-06-30T21:30:00Z", - "universe_id": "SYNTH-TREND-24", - "universe_revision": "2026-06-30-r1", - "calendar_id": "SYNTH-WEEKDAY", - "price_field": "adjusted_close", "window_sessions": 200, + "price_field": "adjusted_close", "securities": [ { - "security_id": "SYNTH-001", + "security_id": "SYNTH-ABOVE", "member_at_session": true, "source_evidence_state": "ready", "available_at": "2026-06-30T21:30:00Z", "adjustment_basis": "split-adjusted-price-return", "prices": [ - 50, - 50, - 50, - 50, - 50, - 50 - ] - }, - { - "security_id": "SYNTH-002", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 52, - 52, - 52, - 52, - 52, - 52 - ] - }, - { - "security_id": "SYNTH-003", - "member_at_session": true, - "source_evidence_state": "ready", - "available_at": "2026-06-30T21:30:00Z", - "adjustment_basis": "split-adjusted-price-return", - "prices": [ - 54, - 54, - 54, - 54, - 54, - 54 + 100, + 100, + 100, + 100, + 100, + 100 ] } ] @@ -26715,40 +25649,17 @@ "status": "resolved", "reason": null, "window_sessions": 200, - "eligible_count": 24, - "above_count": 15, - "equal_count": 1, - "percent_above": 62.5, - "rows": [ - { - "security_id": "SYNTH-001", - "current_price": 60, - "moving_average": 50.05, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-002", - "current_price": 62, - "moving_average": 52.05, - "above": true, - "equal": false - }, - { - "security_id": "SYNTH-003", - "current_price": 64, - "moving_average": 54.05, - "above": true, - "equal": false - } - ] + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 }, "outputElided": null, - "outputShape": "object with 8 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above, rows" + "outputShape": "object with 7 fields: status, reason, window_sessions, eligible_count, above_count, equal_count, percent_above" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -28831,10 +27742,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "analyzeCandle({\"timestamp\":\"2026-01-05T10:00:00Z\",\"instrument_id\":\"SYNTH:ABC\",\"interval\":\"5m\",\"open\":100,\"high\":108,\"low\":97,\"close\":105,\"is_closed\":true,\"volume\":1200,\"price_basis\":\"raw-trades\",\"session\":\"synthetic-utc\"}, 0)", + "origin": "fixture", + "verified": true, + "source": "fixture:D06-F01-A01.json", + "call": "analyzeCandle({\"timestamp\":\"2026-01-05T10:00:00Z\",\"instrument_id\":\"SYNTH:ABC\",\"interval\":\"5m\",\"open\":100,\"high\":108,\"low\":97,\"close\":105,\"is_closed\":true,\"price_basis\":\"raw-trades\",\"session\":\"synthetic-utc\"}, 0)", "args": [ { "value": { @@ -28846,7 +27757,6 @@ "low": 97, "close": 105, "is_closed": true, - "volume": 1200, "price_basis": "raw-trades", "session": "synthetic-utc" }, @@ -28866,7 +27776,7 @@ "instrument_id": "SYNTH:ABC", "interval": "5m", "is_closed": true, - "volume": 1200, + "volume": null, "price_basis": "raw-trades", "session": "synthetic-utc", "body_high": 105, @@ -28881,8 +27791,8 @@ "outputShape": "object with 23 fields: open, high, low, close, timestamp, instrument_id, interval, is_closed, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -29033,9 +27943,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D06-F01-A02.json", "call": "classifyBody({\"timestamp\":\"2026-01-05T10:25:00Z\",\"instrument_id\":\"SYNTH:ABC\",\"interval\":\"5m\",\"body\":4,\"range\":6,\"is_closed\":true,\"price_basis\":\"raw\",\"session\":\"continuous\"}, [1,2,2,3,12], {\"window\":5,\"min_periods\":5,\"tick_size\":0.01,\"thresholds\":{\"tiny_max\":0.25,\"small_max\":0.75,\"long_min\":1.5}})", "args": [ { @@ -29076,31 +27986,22 @@ } ], "output": { - "timestamp": "2026-01-05T10:25:00Z", - "instrument_id": "SYNTH:ABC", - "interval": "5m", - "body": 4, - "range": 6, - "is_closed": true, - "price_basis": "raw", - "session": "continuous", "status": "ready", "body_class": "long", "body_score": 2, "raw_scale": 2, "effective_scale": 2, - "scale_floor_applied": false - }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 23 + "scale_floor_applied": false, + "history_count": 5, + "body_to_current_range": 0.6666666666666666, + "is_provisional": false }, - "outputShape": "object with 23 fields: timestamp, instrument_id, interval, body, range, is_closed, price_basis, session, …" + "outputElided": null, + "outputShape": "object with 9 fields: status, body_class, body_score, raw_scale, effective_scale, scale_floor_applied, history_count, body_to_current_range, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -29226,7 +28127,35 @@ "archetype": "record-transform", "signature": "shadowToBodyRatio(inputs)" }, - "api": null, + "api": { + "summary": "Decomposes one OHLC candle and reports raw and tick-stabilized shadow-to-body ratios without hiding the zero-body case.", + "params": [ + { + "name": "inputs", + "type": "{ candle: { open: number; high: number; low: number; close: number }; tick_size: number }", + "required": true, + "description": "Record containing `candle` and positive `tick_size` fields as defined by the topic data contract.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, body, upper_shadow, lower_shadow, range, tick_size, effective_body, upper_to_body, lower_to_body, upper_to_effective_body, lower_to_effective_body, upper_to_range, lower_to_range, dominant_shadow, dominant_shadow_ratio }", + "description": "One diagnostic record. `state` is `calculated` for a nonzero body and `zero-body` when raw body ratios are undefined; no positional series is returned." + }, + "warmup": null, + "errors": [ + { + "when": "the candle is invalid or tick_size is not positive", + "behaviour": "throws" + } + ], + "complexity": { + "time": "O(1)", + "space": "O(1)" + } + }, "example": { "origin": "executed", "verified": false, @@ -29364,7 +28293,35 @@ "archetype": "record-transform", "signature": "gapClassification(inputs)" }, - "api": null, + "api": { + "summary": "Classifies full-range, body, or opening gaps in either direction using an explicit tick-scaled minimum distance.", + "params": [ + { + "name": "inputs", + "type": "{ previous: { open: number; high: number; low: number; close: number }; current: { open: number; high: number; low: number; close: number }; tick_size: number; minimum_gap_ticks: number }", + "required": true, + "description": "Record containing `previous`, `current`, `tick_size`, and `minimum_gap_ticks` as defined by the topic data contract.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, gap_direction, gap_type, gap_distance, threshold_distance, open_gap_up, open_gap_down, body_gap_up, body_gap_down, full_range_gap_up, full_range_gap_down, signed_open_gap, previous_close, current_open }", + "description": "One classification record with `state` equal to `gap` or `overlap`, plus all directional checks and measured distances." + }, + "warmup": null, + "errors": [ + { + "when": "either candle is invalid, tick_size is not positive, or minimum_gap_ticks is negative", + "behaviour": "throws" + } + ], + "complexity": { + "time": "O(1)", + "space": "O(1)" + } + }, "example": { "origin": "executed", "verified": false, @@ -29505,7 +28462,39 @@ "archetype": "record-transform", "signature": "trendContextFilter(inputs)" }, - "api": null, + "api": { + "summary": "Classifies prior closes as an uptrend, downtrend, or sideways context from normalized net movement and path efficiency.", + "params": [ + { + "name": "inputs", + "type": "{ prior_closes: number[]; prior_ranges: number[]; lookback: number; minimum_efficiency: number; minimum_move_scale: number }", + "required": true, + "description": "Record containing aligned `prior_closes`, `prior_ranges`, `lookback`, `minimum_efficiency`, and `minimum_move_scale` fields.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, trend_context, history_count, net_move, path_move, efficiency, range_scale, normalized_move }", + "description": "One readiness record. `state` is `warmup` until `lookback` observations exist, `zero-scale` when the range scale is zero, and `ready` otherwise; this is not a positional warmup series." + }, + "warmup": { + "count": "lookback prior observations", + "value": "state: warmup", + "note": "The function returns one readiness record until the configured lookback is available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "lookback is below 3, arrays are misaligned, or thresholds are outside their allowed ranges", + "behaviour": "throws" + } + ], + "complexity": { + "time": "O(n log n)", + "space": "O(n)" + } + }, "example": { "origin": "executed", "verified": false, @@ -29651,7 +28640,36 @@ "archetype": "record-transform", "signature": "doji(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against the repository's explicit doji geometry and scale convention.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup` before five history observations, then `matched` or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -29812,7 +28830,36 @@ "archetype": "record-transform", "signature": "dragonflyDoji(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against the repository's explicit dragonfly-doji geometry and scale convention.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup` before five history observations, then `matched` or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -29973,7 +29020,36 @@ "archetype": "record-transform", "signature": "gravestoneDoji(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against the repository's explicit gravestone-doji geometry and scale convention.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup` before five history observations, then `matched` or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -30132,170 +29208,228 @@ "tweezerBottom" ], "archetype": "record-transform", - "signature": "marubozu(inputs)" + "signature": "marubozu(inputs)" + }, + "api": { + "summary": "Evaluates one candle against the repository's explicit marubozu geometry and scale convention.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup` before five history observations, then `matched` or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, + "example": { + "origin": "executed", + "verified": false, + "source": "executed against the catalog's own test input", + "call": "marubozu({\"current\":{\"open\":100,\"high\":102.6,\"low\":99.8,\"close\":102.4},\"prior_bodies\":[2,2.2,1.8,2.1,1.9,2],\"prior_ranges\":[5,5,5,5,5,5],\"trend_context\":\"sideways\",\"tick_size\":0.1})", + "args": [ + { + "value": { + "current": { + "open": 100, + "high": 102.6, + "low": 99.8, + "close": 102.4 + }, + "prior_bodies": [ + 2, + 2.2, + 1.8, + 2.1, + 1.9, + 2 + ], + "prior_ranges": [ + 5, + 5, + 5, + 5, + 5, + 5 + ], + "trend_context": "sideways", + "tick_size": 0.1 + }, + "elided": null + } + ], + "output": { + "topic_id": "D06-F02-A04", + "pattern": "Marubozu", + "matched": true, + "state": "matched", + "direction": "bullish", + "trend_context": "sideways", + "required_context": null, + "body": 2.4000000000000057, + "upper_shadow": 0.19999999999998863, + "lower_shadow": 0.20000000000000284, + "range": 2.799999999999997, + "body_scale": 2, + "range_scale": 5, + "history_count": 10 + }, + "outputElided": { + "kind": "object", + "shown": 14, + "total": 17 + }, + "outputShape": "object with 17 fields: topic_id, pattern, matched, state, direction, trend_context, required_context, body, …" + }, + "verification": { + "tier": "contract", + "via": null + }, + "assets": { + "diagrams": [ + { + "file": "system-map.svg", + "url": "https://thefintechbuilder.com/content/d06-f02-a04/static/system-map.svg" + } + ], + "mermaid": [] + }, + "references": [ + { + "key": "S1", + "title": "Japanese Candlestick Charting Techniques, Second Edition", + "author": "Steve Nison", + "url": "https://www.penguinrandomhouse.com/books/350650/japanese-candlestick-charting-techniques-by-steve-nison/" + }, + { + "key": "S2", + "title": "CMT Program Guide 2026", + "author": "CMT Association", + "url": "https://cmtassociation.org/wp-content/uploads/2025/12/CMT-PROGRAM-GUIDE-2026-1.pdf" + }, + { + "key": "S3", + "title": "Candlestick Settings", + "author": "TA-Lib project", + "url": "https://ta-lib.org/api/candle-settings/" + }, + { + "key": "S4", + "title": "Marubozu recognizer", + "author": "TA-Lib project", + "url": "https://ta-lib.org/functions/cdlmarubozu" + }, + { + "key": "Evidence boundary", + "title": "Evidence boundary", + "author": null, + "url": null + } + ], + "links": { + "article": "https://thefintechbuilder.com/price-action-and-candlesticks/single-candle-patterns/marubozu/", + "repo": null, + "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/marubozu/impl.ts", + "npm": "https://www.npmjs.com/package/fintech-algorithms" + }, + "languages": [ + "typescript", + "python" + ] + }, + { + "id": "D06-F02-A05", + "name": "Spinning Top", + "headline": null, + "slug": "spinning-top", + "path": "price-action-and-candlesticks/single-candle-patterns/spinning-top", + "taxonomy": { + "domainId": "D06", + "domain": "Price Action and Candlesticks", + "familyId": "D06-F02", + "family": "Single-Candle Patterns", + "difficulty": 2 + }, + "import": { + "subpath": "fintech-algorithms/price-action-and-candlesticks/single-candle-patterns/spinning-top", + "entry": "spinningTop", + "params": [ + "inputs" + ], + "exports": [ + "calculate", + "shadowToBodyRatio", + "gapClassification", + "trendContextFilter", + "doji", + "dragonflyDoji", + "gravestoneDoji", + "marubozu", + "spinningTop", + "hammer", + "hangingMan", + "invertedHammer", + "shootingStar", + "bullishEngulfing", + "bearishEngulfing", + "bullishHarami", + "bearishHarami", + "piercingLine", + "darkCloudCover", + "tweezerTop", + "tweezerBottom" + ], + "archetype": "record-transform", + "signature": "spinningTop(inputs)" }, - "api": null, - "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "marubozu({\"current\":{\"open\":100,\"high\":102.6,\"low\":99.8,\"close\":102.4},\"prior_bodies\":[2,2.2,1.8,2.1,1.9,2],\"prior_ranges\":[5,5,5,5,5,5],\"trend_context\":\"sideways\",\"tick_size\":0.1})", - "args": [ + "api": { + "summary": "Evaluates one candle against the repository's explicit spinning-top geometry and scale convention.", + "params": [ { - "value": { - "current": { - "open": 100, - "high": 102.6, - "low": 99.8, - "close": 102.4 - }, - "prior_bodies": [ - 2, - 2.2, - 1.8, - 2.1, - 1.9, - 2 - ], - "prior_ranges": [ - 5, - 5, - 5, - 5, - 5, - 5 - ], - "trend_context": "sideways", - "tick_size": 0.1 - }, - "elided": null + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null } ], - "output": { - "topic_id": "D06-F02-A04", - "pattern": "Marubozu", - "matched": true, - "state": "matched", - "direction": "bullish", - "trend_context": "sideways", - "required_context": null, - "body": 2.4000000000000057, - "upper_shadow": 0.19999999999998863, - "lower_shadow": 0.20000000000000284, - "range": 2.799999999999997, - "body_scale": 2, - "range_scale": 5, - "history_count": 10 + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup` before five history observations, then `matched` or `not-matched`; this is not a positional series." }, - "outputElided": { - "kind": "object", - "shown": 14, - "total": 17 + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." }, - "outputShape": "object with 17 fields: topic_id, pattern, matched, state, direction, trend_context, required_context, body, …" - }, - "verification": { - "tier": "contract", - "via": null - }, - "assets": { - "diagrams": [ + "errors": [ { - "file": "system-map.svg", - "url": "https://thefintechbuilder.com/content/d06-f02-a04/static/system-map.svg" + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" } ], - "mermaid": [] - }, - "references": [ - { - "key": "S1", - "title": "Japanese Candlestick Charting Techniques, Second Edition", - "author": "Steve Nison", - "url": "https://www.penguinrandomhouse.com/books/350650/japanese-candlestick-charting-techniques-by-steve-nison/" - }, - { - "key": "S2", - "title": "CMT Program Guide 2026", - "author": "CMT Association", - "url": "https://cmtassociation.org/wp-content/uploads/2025/12/CMT-PROGRAM-GUIDE-2026-1.pdf" - }, - { - "key": "S3", - "title": "Candlestick Settings", - "author": "TA-Lib project", - "url": "https://ta-lib.org/api/candle-settings/" - }, - { - "key": "S4", - "title": "Marubozu recognizer", - "author": "TA-Lib project", - "url": "https://ta-lib.org/functions/cdlmarubozu" - }, - { - "key": "Evidence boundary", - "title": "Evidence boundary", - "author": null, - "url": null - } - ], - "links": { - "article": "https://thefintechbuilder.com/price-action-and-candlesticks/single-candle-patterns/marubozu/", - "repo": null, - "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/marubozu/impl.ts", - "npm": "https://www.npmjs.com/package/fintech-algorithms" - }, - "languages": [ - "typescript", - "python" - ] - }, - { - "id": "D06-F02-A05", - "name": "Spinning Top", - "headline": null, - "slug": "spinning-top", - "path": "price-action-and-candlesticks/single-candle-patterns/spinning-top", - "taxonomy": { - "domainId": "D06", - "domain": "Price Action and Candlesticks", - "familyId": "D06-F02", - "family": "Single-Candle Patterns", - "difficulty": 2 - }, - "import": { - "subpath": "fintech-algorithms/price-action-and-candlesticks/single-candle-patterns/spinning-top", - "entry": "spinningTop", - "params": [ - "inputs" - ], - "exports": [ - "calculate", - "shadowToBodyRatio", - "gapClassification", - "trendContextFilter", - "doji", - "dragonflyDoji", - "gravestoneDoji", - "marubozu", - "spinningTop", - "hammer", - "hangingMan", - "invertedHammer", - "shootingStar", - "bullishEngulfing", - "bearishEngulfing", - "bullishHarami", - "bearishHarami", - "piercingLine", - "darkCloudCover", - "tweezerTop", - "tweezerBottom" - ], - "archetype": "record-transform", - "signature": "spinningTop(inputs)" + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" }, - "api": null, "example": { "origin": "executed", "verified": false, @@ -30456,7 +29590,36 @@ "archetype": "record-transform", "signature": "hammer(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against explicit hammer geometry, scale, and downtrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -30617,7 +29780,36 @@ "archetype": "record-transform", "signature": "hangingMan(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against explicit hanging-man geometry, scale, and uptrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -30778,7 +29970,36 @@ "archetype": "record-transform", "signature": "invertedHammer(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against explicit inverted-hammer geometry, scale, and downtrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -30939,7 +30160,36 @@ "archetype": "record-transform", "signature": "shootingStar(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates one candle against explicit shooting-star geometry, scale, and uptrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ current: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number }", + "required": true, + "description": "Record containing `current`, prior body/range history, `trend_context`, and `tick_size`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks }", + "description": "One pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; this is not a positional series." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "OHLC, history, context, or tick-size input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31100,7 +30350,36 @@ "archetype": "record-transform", "signature": "bullishEngulfing(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit bullish-engulfing geometry, scale, and downtrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31268,7 +30547,36 @@ "archetype": "record-transform", "signature": "bearishEngulfing(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit bearish-engulfing geometry, scale, and uptrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31436,7 +30744,36 @@ "archetype": "record-transform", "signature": "bullishHarami(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit bullish-harami containment, scale, and downtrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31604,7 +30941,36 @@ "archetype": "record-transform", "signature": "bearishHarami(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit bearish-harami containment, scale, and uptrend context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31772,7 +31138,36 @@ "archetype": "record-transform", "signature": "piercingLine(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit piercing-line gap, midpoint, scale, and downtrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -31940,7 +31335,36 @@ "archetype": "record-transform", "signature": "darkCloudCover(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit dark-cloud gap, midpoint, scale, and uptrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32108,7 +31532,36 @@ "archetype": "record-transform", "signature": "tweezerTop(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit tweezer-top tolerance, rejection, scale, and uptrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32276,7 +31729,36 @@ "archetype": "record-transform", "signature": "tweezerBottom(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates two candles against explicit tweezer-bottom tolerance, rejection, scale, and downtrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ first: { open: number; high: number; low: number; close: number }; second: { open: number; high: number; low: number; close: number }; prior_bodies: number[]; prior_ranges: number[]; trend_context: string; tick_size: number; price_tolerance_ticks: number }", + "required": true, + "description": "Record containing `first`, `second`, prior body/range history, context, tick size, and price tolerance.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, body, upper_shadow, lower_shadow, range, body_scale, range_scale, history_count, geometry_score, checks, failed_checks, first_direction, second_direction, first_body, second_body, first_body_low?, first_body_high?, second_body_low?, second_body_high?, first_high?, second_high?, first_low?, second_low?, midpoint?, price_tolerance }", + "description": "One pattern record with causal geometry diagnostics. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; detailed price fields are absent during warmup." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "candle, history, context, tick-size, or tolerance input violates the data contract", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32431,7 +31913,36 @@ "archetype": "record-transform", "signature": "morningStar(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit morning-star gap, penetration, scale, and downtrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and optional penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32601,7 +32112,36 @@ "archetype": "record-transform", "signature": "eveningStar(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit evening-star gap, penetration, scale, and uptrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and optional penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32771,7 +32311,36 @@ "archetype": "record-transform", "signature": "threeWhiteSoldiers(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit white-soldiers body, close, shadow, scale, and downtrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -32941,7 +32510,36 @@ "archetype": "record-transform", "signature": "threeBlackCrows(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit black-crows body, close, shadow, scale, and uptrend conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -33111,7 +32709,36 @@ "archetype": "record-transform", "signature": "threeInsideUpDown(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit inside-pair containment, confirmation, scale, and trend-context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -33280,7 +32907,36 @@ "archetype": "record-transform", "signature": "threeOutsideUpDown(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit outside-pair engulfing, confirmation, scale, and trend-context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -33447,7 +33103,36 @@ "archetype": "record-transform", "signature": "abandonedBaby(inputs)" }, - "api": null, + "api": { + "summary": "Evaluates exactly three candles against explicit abandoned-baby isolation, doji, penetration, scale, and context conventions.", + "params": [ + { + "name": "inputs", + "type": "{ candles: { open: number; high: number; low: number; close: number }[]; trend_context: string; prior_bodies: number[]; prior_ranges: number[]; tick_size: number; penetration_fraction: number }", + "required": true, + "description": "Record containing three `candles`, trend context, prior body/range history, tick size, and penetration fraction.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, pattern, matched, state, direction, trend_context, required_context, history_count, body_scale, range_scale, geometry_score, checks, failed_checks, reason, thresholds, candles }", + "description": "One three-candle pattern record. `state` is `warmup`, `wrong-context`, `matched`, or `not-matched`; readiness is record state, not positional output." + }, + "warmup": { + "count": "5 prior observations", + "value": "state: warmup", + "note": "The detector returns one readiness record before five prior body/range observations are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "the record does not contain exactly three valid candles or scale/context inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -33614,7 +33299,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ patterns: { pattern_id: string; name: string; direction: string; window: number; detector: string; version: string; enabled: boolean; priority: number }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -33622,7 +33307,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, registry_id, pattern_count, enabled_count, max_window, patterns }", + "description": "One `ready` registry record with stable catalog ordering, a versioned registry identity, aggregate counts, maximum detector window, and the validated pattern specifications." + }, "warmup": null, "errors": [], "complexity": { @@ -33772,7 +33460,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ instrument_id: string; interval: string; price_basis: string; session: string; pattern_id: string; pattern_name: string; direction: string; start_index: number; end_index: number; start_time: string; end_time: string; detected_at: string; available_at: string; bar_closed: boolean; detector_version: string; geometry_score: number; reason_codes: string[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -33780,7 +33468,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ occurrence_id, instrument_id, interval, price_basis, session, pattern_id, pattern_name, direction, start_index, end_index, start_time, end_time, detected_at, available_at, bar_closed, detector_version, geometry_score, reason_codes }", + "description": "One normalized closed-bar occurrence with a deterministic identity, causal timestamps, detector version, bounded geometry score, and explicit reason codes." + }, "warmup": null, "errors": [], "complexity": { @@ -33924,7 +33615,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ as_of: string; minimum_geometry_score: number; registry: { pattern_id: string; name: string; direction: string; window: number; detector: string; version: string; enabled: boolean; priority: number }[]; candidates: { instrument_id: string; interval: string; price_basis: string; session: string; pattern_id: string; pattern_name: string; direction: string; start_index: number; end_index: number; start_time: string; end_time: string; detected_at: string; available_at: string; bar_closed: boolean; detector_version: string; geometry_score: number; reason_codes: string[] }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -33932,7 +33623,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, as_of, candidate_count, occurrence_count, skipped_count, occurrences, skipped }", + "description": "One `ready` scan record containing deterministically ordered causal occurrences and reason-coded skipped candidates, with counts for both." + }, "warmup": null, "errors": [], "complexity": { @@ -34123,7 +33817,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ features: { geometry: number; support_resistance: number; trend: number; volatility: number; volume: number; confirmation: number }; minimum_coverage: number }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34131,7 +33825,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, score, evidence_coverage, minimum_coverage, contributions, interpretation }", + "description": "One context-fit record. `state` is `ready` with a 0-100 score when the minimum evidence coverage is met, otherwise `insufficient-evidence` with a null score; this is not a probability." + }, "warmup": null, "errors": [], "complexity": { @@ -34267,7 +33964,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ pattern_price: number; atr: number; direction: string; occurrence_index: number; max_distance_atr: number; levels: { price: number; kind: string; strength: number; confirmed_index: number }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34275,7 +33972,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, context_score, matched_level, target_kind?, distance_atr? }", + "description": "One directional context record. `state` is `ready`, `no-causal-level`, or `unsupported-direction`; score and distance are present only when their evidence exists." + }, "warmup": null, "errors": [], "complexity": { @@ -34427,7 +34127,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ prior_closes: number[]; prior_ranges: number[]; prior_volumes: number[]; lookback: number; expected_prior_trend: string; current_range: number; current_volume: number; target_volume_ratio: number }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34435,8 +34135,15 @@ "default": null } ], - "returns": null, - "warmup": null, + "returns": { + "type": "{ state, history_count?, range_scale?, volume_scale?, normalized_slope?, trend_score?, volatility_ratio?, volatility_score?, volume_ratio?, volume_score? }", + "description": "One readiness record. `state` is `warmup` until `lookback` aligned observations exist, `zero-scale` for unusable range or volume scales, and `ready` with the three component scores otherwise; no positional series is returned." + }, + "warmup": { + "count": "lookback aligned observations", + "value": "state: warmup", + "note": "The function returns one readiness record until aligned close, range, and volume histories reach lookback; it does not emit a positional null prefix." + }, "errors": [], "complexity": { "time": "O(n log n) worst case; see README for topic-specific n", @@ -34591,7 +34298,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ occurrences: { occurrence_id: string; instrument_id: string; interval: string; pattern_id: string; direction: string; start_index: number; end_index: number; priority: number; confidence: number; geometry_score: number }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34599,7 +34306,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, winner_count, suppressed_count, winners, suppressed }", + "description": "One `ready` conflict-resolution record containing the deterministic winners and reason-coded suppressed occurrences with aggregate counts." + }, "warmup": null, "errors": [], "complexity": { @@ -34763,7 +34473,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ detection_index: number; direction: string; confirmation_level: number; invalidation_level: number; expires_after_bars: number; events: { bar_index: number; bar_closed: boolean; close: number }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34771,7 +34481,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, direction, confirmation_level, invalidation_level, transitions, terminal }", + "description": "One lifecycle record. `state` progresses from `awaiting-confirmation` to `confirmed`, `invalidated`, or `expired`; `terminal` identifies those final states and `transitions` preserves the full reason-coded trace." + }, "warmup": null, "errors": [], "complexity": { @@ -34915,7 +34628,7 @@ "params": [ { "name": "data", - "type": "Record", + "type": "{ recency_half_life_bars: number; dedup_window_bars: number; occurrences: { occurrence_id: string; instrument_id: string; interval: string; pattern_id: string; direction: string; end_index: number; confidence: number; age_bars: number; liquidity_score: number; priority_score: number }[] }", "required": true, "description": "Topic input record; the required fields are fixed by this topic data-contract.", "constraints": null, @@ -34923,7 +34636,10 @@ "default": null } ], - "returns": null, + "returns": { + "type": "{ state, ranked_count, suppressed_count, ranked, suppressed }", + "description": "One `ready` ranking record containing stable ranks and component traces for kept occurrences plus reason-coded duplicates and both counts." + }, "warmup": null, "errors": [], "complexity": { @@ -35133,9 +34849,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A01.json", "call": "calculateSma([10,13,12,15,14,18], 3)", "args": [ { @@ -35166,8 +34882,8 @@ "outputShape": "array of 6 nulls" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -35343,9 +35059,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A02.json", "call": "calculateEma([10,13,12,15,14,18], 3)", "args": [ { @@ -35368,16 +35084,16 @@ null, null, 11.666666666666666, - 13.333333333333332, + 13.333333333333334, 13.666666666666666, - 15.833333333333332 + 15.833333333333334 ], "outputElided": null, "outputShape": "array of 6 nulls" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -35520,9 +35236,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A03.json", "call": "calculateWma([10,13,12,15,14,18], 3)", "args": [ { @@ -35553,8 +35269,8 @@ "outputShape": "array of 6 nulls" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -35721,9 +35437,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A04.json", "call": "calculateRma([10,13,12,15,14,18], 3)", "args": [ { @@ -35746,7 +35462,7 @@ null, null, 11.666666666666666, - 12.777777777777777, + 12.777777777777779, 13.185185185185185, 14.790123456790123 ], @@ -35754,8 +35470,8 @@ "outputShape": "array of 6 nulls" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -35910,9 +35626,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A05.json", "call": "calculateDemaComponents([10,13,12,15,14,18], 3)", "args": [ { @@ -35935,39 +35651,30 @@ "elided": null } ], - "output": [ - { - "value": 10, - "ema1": null, - "ema2": null, - "dema": null, - "status": "warming_ema1" + "output": { + "4": { + "dema": 14.444444444444445, + "status": "ready" }, - { - "value": 13, - "ema1": null, - "ema2": null, - "dema": null, - "status": "warming_ema1" + "5": { + "dema": 17.305555555555557, + "status": "ready" }, - { - "value": 12, - "ema1": 11.666666666666666, - "ema2": null, - "dema": null, - "status": "warming_ema2" + "6": { + "dema": 17.444444444444443, + "status": "ready" + }, + "7": { + "dema": 19.618055555555557, + "status": "ready" } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 8 }, - "outputShape": "array of 8 objects" + "outputElided": null, + "outputShape": "object with 4 fields: 4, 5, 6, 7" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -36116,9 +35823,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F01-A06.json", "call": "calculateTemaComponents([10,13,12,15,14,18], 3)", "args": [ { @@ -36141,42 +35848,33 @@ "elided": null } ], - "output": [ - { - "value": 10, - "ema1": null, - "ema2": null, - "ema3": null, - "tema": null, - "status": "warming_ema1" + "output": { + "6": { + "ema1": 16.416666666666664, + "ema2": 15.388888888888888, + "ema3": 14.212962962962962, + "tema": 17.29629629629629, + "status": "ready" }, - { - "value": 13, - "ema1": null, - "ema2": null, - "ema3": null, - "tema": null, - "status": "warming_ema1" + "7": { + "tema": 19.73495370370371, + "status": "ready" }, - { - "value": 12, - "ema1": 11.666666666666666, - "ema2": null, - "ema3": null, - "tema": null, - "status": "warming_ema2" + "8": { + "tema": 19.311921296296298, + "status": "ready" + }, + "9": { + "tema": 21.703703703703713, + "status": "ready" } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 10 }, - "outputShape": "array of 10 objects" + "outputElided": null, + "outputShape": "object with 4 fields: 6, 7, 8, 9" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -36388,8 +36086,8 @@ "outputShape": "object with 6 fields: halfLength, rootLength, shortWma, longWma, rawHull, hullMa" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "scenario-fixture" }, "assets": { "diagrams": [ @@ -36633,8 +36331,8 @@ "outputShape": "object with 4 fields: efficiencyRatio, blendedAlpha, smoothingConstant, kama" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "scenario-fixture" }, "assets": { "diagrams": [ @@ -36983,8 +36681,8 @@ "outputShape": "object with 14 fields: smooth, detrender, i1, q1, i2, q2, re, im, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "scenario-fixture" }, "assets": { "diagrams": [ @@ -37193,9 +36891,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D07-F02-A01.json", "call": "macd([10,11,12,13,14,15], 3, 5, 3)", "args": [ { @@ -37226,48 +36924,50 @@ "elided": null } ], - "output": [ - { - "index": 0, - "value": 10, - "fastEma": null, - "slowEma": null, - "macd": null, - "signal": null, - "histogram": null, - "status": "warming_price_emas" - }, - { - "index": 1, - "value": 11, - "fastEma": null, - "slowEma": null, - "macd": null, - "signal": null, - "histogram": null, - "status": "warming_price_emas" - }, - { - "index": 2, - "value": 12, - "fastEma": 11, - "slowEma": null, - "macd": null, + "output": { + "4": { + "fastEma": 13, + "slowEma": 12, + "macd": 1, "signal": null, "histogram": null, - "status": "warming_price_emas" + "status": "warming_signal" + }, + "6": { + "fastEma": 15, + "slowEma": 14, + "macd": 1, + "signal": 1, + "histogram": 0, + "status": "ready" + }, + "7": { + "fastEma": 15, + "slowEma": 14.333333333333334, + "macd": 0.6666666666666661, + "signal": 0.833333333333333, + "histogram": -0.16666666666666696, + "status": "ready" + }, + "9": { + "macd": -0.06481481481481488, + "signal": 0.24537037037037002, + "histogram": -0.3101851851851849, + "status": "ready" + }, + "12": { + "macd": 0.2088048696844993, + "signal": 0.04260973936899856, + "histogram": 0.16619513031550073, + "status": "ready" } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 14 }, - "outputShape": "array of 14 objects" + "outputElided": null, + "outputShape": "object with 5 fields: 4, 6, 7, 9, 12" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -37848,7 +37548,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/trend-systems/directional-movement", - "entry": "directional_movement", + "entry": "directionalMovement", "params": [ "high", "low", @@ -37856,10 +37556,10 @@ "period" ], "exports": [ - "directional_movement" + "directionalMovement" ], "archetype": "series-transform", - "signature": "directional_movement(high, low, close, period)" + "signature": "directionalMovement(high, low, close, period)" }, "api": { "summary": "The components beneath ADX: directional movement in each direction, Wilder-smoothed, divided by the average true range to give +DI and −DI.", @@ -37933,7 +37633,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "directional_movement([105.45,106.10084,106.816229,107.542653,108.232784,108.852128], [103.293,103.437436,103.948153,104.603166,105.372863,106.203002], [104.42,104.954567,105.585587,106.282695,107.006608,107.713561], 14)", + "call": "directionalMovement([105.45,106.10084,106.816229,107.542653,108.232784,108.852128], [103.293,103.437436,103.948153,104.603166,105.372863,106.203002], [104.42,104.954567,105.585587,106.282695,107.006608,107.713561], 14)", "args": [ { "value": [ @@ -38747,7 +38447,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/trend-systems/parabolic-sar", - "entry": "parabolic_sar", + "entry": "parabolicSar", "params": [ "high", "low", @@ -38756,10 +38456,10 @@ "accelerationMax" ], "exports": [ - "parabolic_sar" + "parabolicSar" ], "archetype": "series-transform", - "signature": "parabolic_sar(high, low, initialDirection, accelerationStep, accelerationMax)" + "signature": "parabolicSar(high, low, initialDirection, accelerationStep, accelerationMax)" }, "api": { "summary": "Stop-and-reverse: a trailing stop that accelerates toward price while a trend persists and flips side when price crosses it. Path-dependent — the whole series follows from the initial direction.", @@ -38839,7 +38539,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "parabolic_sar([117.555,118.215368,118.945956,119.686391,120.381031,120.987562], [115.1985,115.34324,115.864377,116.536001,117.321542,118.15831], \"long\", 0.02, 0.2)", + "call": "parabolicSar([117.555,118.215368,118.945956,119.686391,120.381031,120.987562], [115.1985,115.34324,115.864377,116.536001,117.321542,118.15831], \"long\", 0.02, 0.2)", "args": [ { "value": [ @@ -39337,12 +39037,12 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", "signature": "rsi(close, p)" @@ -39505,12 +39205,12 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", "signature": "stochastic(high, low, close, kp, sk, sd)" @@ -39752,7 +39452,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/momentum/stochastic-rsi", - "entry": "stochastic_rsi", + "entry": "stochasticRsi", "params": [ "close", "rp", @@ -39763,15 +39463,15 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", - "signature": "stochastic_rsi(close, rp, sp, sk, sd)" + "signature": "stochasticRsi(close, rp, sp, sk, sd)" }, "api": { "summary": "The stochastic formula applied to RSI rather than to price — a second-order indicator that measures where RSI sits within its own recent range, and therefore moves far faster than either input.", @@ -39859,7 +39559,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "stochastic_rsi([100,100.999214,102.324548,103.755998,105.030823,105.911843])", + "call": "stochasticRsi([100,100.999214,102.324548,103.755998,105.030823,105.911843])", "args": [ { "value": [ @@ -39985,7 +39685,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/momentum/williams-r", - "entry": "williams_r", + "entry": "williamsR", "params": [ "high", "low", @@ -39995,15 +39695,15 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", - "signature": "williams_r(high, low, close, p)" + "signature": "williamsR(high, low, close, p)" }, "api": { "summary": "Where the close sits within the lookback's high–low range, on a −100…0 scale. Arithmetically the inverse of fast %K.", @@ -40076,7 +39776,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "williams_r([101,101.992465,103.28276,104.655405,105.856544,106.661472], [99.08,99.149664,100.233798,101.654978,103.180913,104.534685], [100,100.999214,102.324548,103.755998,105.030823,105.911843])", + "call": "williamsR([101,101.992465,103.28276,104.655405,105.856544,106.661472], [99.08,99.149664,100.233798,101.654978,103.180913,104.534685], [100,100.999214,102.324548,103.755998,105.030823,105.911843])", "args": [ { "value": [ @@ -40219,12 +39919,12 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", "signature": "cci(high, low, close, p, k)" @@ -40445,7 +40145,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/momentum/ultimate-oscillator", - "entry": "ultimate_oscillator", + "entry": "ultimateOscillator", "params": [ "high", "low", @@ -40457,15 +40157,15 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", - "signature": "ultimate_oscillator(high, low, close, s, m, g)" + "signature": "ultimateOscillator(high, low, close, s, m, g)" }, "api": { "summary": "Weighted buying pressure across three lookbacks at once, which is what makes it less sensitive to the choice of any single period than a plain oscillator.", @@ -40562,7 +40262,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "ultimate_oscillator([101,101.992465,103.28276,104.655405,105.856544,106.661472], [99.08,99.149664,100.233798,101.654978,103.180913,104.534685], [100,100.999214,102.324548,103.755998,105.030823,105.911843])", + "call": "ultimateOscillator([101,101.992465,103.28276,104.655405,105.856544,106.661472], [99.08,99.149664,100.233798,101.654978,103.180913,104.534685], [100,100.999214,102.324548,103.755998,105.030823,105.911843])", "args": [ { "value": [ @@ -40713,12 +40413,12 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", "signature": "tsi(close, g, s)" @@ -40887,7 +40587,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/momentum/connors-rsi", - "entry": "connors_rsi", + "entry": "connorsRsi", "params": [ "close", "pp", @@ -40897,15 +40597,15 @@ "exports": [ "rsi", "stochastic", - "stochastic_rsi", - "williams_r", + "stochasticRsi", + "williamsR", "cci", - "ultimate_oscillator", + "ultimateOscillator", "tsi", - "connors_rsi" + "connorsRsi" ], "archetype": "series-transform", - "signature": "connors_rsi(close, pp, sp, rp)" + "signature": "connorsRsi(close, pp, sp, rp)" }, "api": { "summary": "The average of three components: RSI of price, RSI of the up/down streak length, and the percentile rank of the latest return. Designed for short-horizon mean reversion rather than trend.", @@ -40980,7 +40680,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "connors_rsi([100,100.999214,102.324548,103.755998,105.030823,105.911843])", + "call": "connorsRsi([100,100.999214,102.324548,103.755998,105.030823,105.911843])", "args": [ { "value": [ @@ -41108,17 +40808,17 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/true-range", - "entry": "true_range", + "entry": "trueRange", "params": [ "high", "low", "close" ], "exports": [ - "true_range" + "trueRange" ], "archetype": "series-transform", - "signature": "true_range(high, low, close)" + "signature": "trueRange(high, low, close)" }, "api": { "summary": "The greater of today's range, the gap up from yesterday's close, and the gap down from it. Using the plain high−low range instead understates volatility on every gap.", @@ -41176,7 +40876,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "true_range([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197])", + "call": "trueRange([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197])", "args": [ { "value": [ @@ -41346,7 +41046,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/atr", - "entry": "average_true_range", + "entry": "averageTrueRange", "params": [ "high", "low", @@ -41354,11 +41054,11 @@ "p" ], "exports": [ - "true_range", - "average_true_range" + "trueRange", + "averageTrueRange" ], "archetype": "series-transform", - "signature": "average_true_range(high, low, close, p)" + "signature": "averageTrueRange(high, low, close, p)" }, "api": { "summary": "Wilder-smoothed true range. Most often used for position sizing and stop placement rather than as a signal — it says how far price typically moves, not which way.", @@ -41432,7 +41132,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "average_true_range([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197], 14)", + "call": "averageTrueRange([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197], 14)", "args": [ { "value": [ @@ -41588,17 +41288,17 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/bollinger-bands", - "entry": "bollinger_bands", + "entry": "bollingerBands", "params": [ "close", "p", "multiplier" ], "exports": [ - "bollinger_bands" + "bollingerBands" ], "archetype": "series-transform", - "signature": "bollinger_bands(close, p, multiplier)" + "signature": "bollingerBands(close, p, multiplier)" }, "api": { "summary": "A moving average with bands a number of standard deviations away, so the channel widens and narrows with realised volatility.", @@ -41660,7 +41360,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "bollinger_bands([100,100.54129063,101.06589044,101.55765885,102.00153762,102.3840473], 20, 2)", + "call": "bollingerBands([100,100.54129063,101.06589044,101.55765885,102.00153762,102.3840473], 20, 2)", "args": [ { "value": [ @@ -41820,7 +41520,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/keltner-channels", - "entry": "keltner_channels", + "entry": "keltnerChannels", "params": [ "high", "low", @@ -41830,12 +41530,12 @@ "multiplier" ], "exports": [ - "true_range", - "average_true_range", - "keltner_channels" + "trueRange", + "averageTrueRange", + "keltnerChannels" ], "archetype": "series-transform", - "signature": "keltner_channels(high, low, close, emaPeriod, atrPeriod, multiplier)" + "signature": "keltnerChannels(high, low, close, emaPeriod, atrPeriod, multiplier)" }, "api": { "summary": "An EMA with bands placed a number of ATRs away. Because it scales with true range rather than standard deviation, it reacts differently to gaps than Bollinger Bands — which is the basis of the squeeze comparison between the two.", @@ -41931,7 +41631,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "keltner_channels([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197], 20, 10, 2)", + "call": "keltnerChannels([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], [100,100.50948657,100.98130867,101.38252022,101.68897903,101.88825197], 20, 10, 2)", "args": [ { "value": [ @@ -42119,17 +41819,17 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/donchian-channels", - "entry": "donchian_channels", + "entry": "donchianChannels", "params": [ "high", "low", "p" ], "exports": [ - "donchian_channels" + "donchianChannels" ], "archetype": "series-transform", - "signature": "donchian_channels(high, low, p)" + "signature": "donchianChannels(high, low, p)" }, "api": { "summary": "The highest high and lowest low of the lookback. The oldest channel in use, and the only one here with no smoothing at all — the bands step rather than glide.", @@ -42193,7 +41893,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "donchian_channels([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], 20)", + "call": "donchianChannels([101.08,101.6243955,102.13058177,102.56507653,102.90321818,103.1320792], [98.92,99.39457765,99.83203556,100.19996391,100.47473988,100.64442473], 20)", "args": [ { "value": [ @@ -42338,18 +42038,18 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volatility-and-channels/bollinger-bandwidth", - "entry": "bollinger_bandwidth", + "entry": "bollingerBandwidth", "params": [ "close", "p", "multiplier" ], "exports": [ - "bollinger_bands", - "bollinger_bandwidth" + "bollingerBands", + "bollingerBandwidth" ], "archetype": "series-transform", - "signature": "bollinger_bandwidth(close, p, multiplier)" + "signature": "bollingerBandwidth(close, p, multiplier)" }, "api": { "summary": "The width of a Bollinger channel relative to its middle band. Low readings mark contraction, which historically precedes expansion — the quantity behind every 'squeeze' screen.", @@ -42411,7 +42111,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "bollinger_bandwidth([100,100.40234656,100.79879348,101.18354586,101.55101638,101.89592451], 20, 2)", + "call": "bollingerBandwidth([100,100.40234656,100.79879348,101.18354586,101.55101638,101.89592451], 20, 2)", "args": [ { "value": [ @@ -42579,11 +42279,11 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", "signature": "obv(close, volume, initial)" @@ -42819,7 +42519,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volume-indicators/accumulation-distribution-line", - "entry": "accumulation_distribution_line", + "entry": "accumulationDistributionLine", "params": [ "high", "low", @@ -42829,14 +42529,14 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", - "signature": "accumulation_distribution_line(high, low, close, volume, initial)" + "signature": "accumulationDistributionLine(high, low, close, volume, initial)" }, "api": { "summary": "Weights each bar's volume by where the close sat within that bar's range, then accumulates. Unlike OBV it distinguishes a close at the high from a close barely above the open.", @@ -42912,7 +42612,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "accumulation_distribution_line([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", + "call": "accumulationDistributionLine([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", "args": [ { "value": [ @@ -43131,7 +42831,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volume-indicators/chaikin-money-flow", - "entry": "chaikin_money_flow", + "entry": "chaikinMoneyFlow", "params": [ "high", "low", @@ -43141,14 +42841,14 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", - "signature": "chaikin_money_flow(high, low, close, volume, p)" + "signature": "chaikinMoneyFlow(high, low, close, volume, p)" }, "api": { "summary": "Money-flow volume summed over a lookback and divided by total volume over the same window — the accumulation/distribution idea as a bounded oscillator rather than a running total.", @@ -43230,7 +42930,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "chaikin_money_flow([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", + "call": "chaikinMoneyFlow([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", "args": [ { "value": [ @@ -43443,7 +43143,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volume-indicators/money-flow-index", - "entry": "money_flow_index", + "entry": "moneyFlowIndex", "params": [ "high", "low", @@ -43453,14 +43153,14 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", - "signature": "money_flow_index(high, low, close, volume, p)" + "signature": "moneyFlowIndex(high, low, close, volume, p)" }, "api": { "summary": "RSI computed on typical price weighted by volume — commonly described as volume-weighted RSI, and read on the same 0–100 scale.", @@ -43543,7 +43243,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "money_flow_index([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", + "call": "moneyFlowIndex([101.05,101.52482,102.098461,102.729464,103.36806,103.963227], [99.4,99.462904,99.936275,100.512674,101.151059,101.802588], [100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", "args": [ { "value": [ @@ -43770,7 +43470,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volume-indicators/volume-price-trend", - "entry": "volume_price_trend", + "entry": "volumePriceTrend", "params": [ "close", "volume", @@ -43778,14 +43478,14 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", - "signature": "volume_price_trend(close, volume, initial)" + "signature": "volumePriceTrend(close, volume, initial)" }, "api": { "summary": "Like OBV, but each bar contributes volume scaled by the size of the return rather than only its sign — so a 3% move counts for more than a 0.1% one.", @@ -43843,7 +43543,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "volume_price_trend([100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", + "call": "volumePriceTrend([100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", "args": [ { "value": [ @@ -44018,7 +43718,7 @@ }, "import": { "subpath": "fintech-algorithms/technical-indicators/volume-indicators/force-index", - "entry": "force_index", + "entry": "forceIndex", "params": [ "close", "volume", @@ -44026,14 +43726,14 @@ ], "exports": [ "obv", - "accumulation_distribution_line", - "chaikin_money_flow", - "money_flow_index", - "volume_price_trend", - "force_index" + "accumulationDistributionLine", + "chaikinMoneyFlow", + "moneyFlowIndex", + "volumePriceTrend", + "forceIndex" ], "archetype": "series-transform", - "signature": "force_index(close, volume, p)" + "signature": "forceIndex(close, volume, p)" }, "api": { "summary": "Price change multiplied by volume, then smoothed. Combines direction, size and participation in one number — a large move on no volume scores low.", @@ -44098,7 +43798,7 @@ "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "force_index([100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", + "call": "forceIndex([100.28,100.686113,101.200346,101.789282,102.408843,103.010585], [990000,1066468.036,1130033.236,1170141.961,1180511.26,1160272.794])", "args": [ { "value": [ @@ -44354,9 +44054,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D08-F01-A01.json", "call": "detectCausalPivots([{\"timestamp\":\"2026-01-01T00:00:00Z\",\"high\":10,\"low\":8,\"close\":9},{\"timestamp\":\"2026-01-01T01:00:00Z\",\"high\":12,\"low\":10,\"close\":11},{\"timestamp\":\"2026-01-01T02:00:00Z\",\"high\":15,\"low\":13,\"close\":14}], 2, 2, 0)", "args": [ { @@ -44399,8 +44099,8 @@ "elided": null } ], - "output": [ - { + "output": { + "0": { "kind": "high", "event_index": 2, "confirmation_index": 4, @@ -44408,13 +44108,13 @@ "separation": 2, "latency": 2 } - ], + }, "outputElided": null, - "outputShape": "array of 1 object" + "outputShape": "object with 1 field: 0" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -44548,10 +44248,10 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "zigzagSegment([100,103,106,101,100], 0.05, 1)", + "origin": "fixture", + "verified": true, + "source": "fixture:D08-F01-A02.json", + "call": "zigzagSegment([100,103,106,101,100], 0.05, 2)", "args": [ { "value": [ @@ -44568,7 +44268,7 @@ "elided": null }, { - "value": 1, + "value": 2, "elided": null } ], @@ -44586,45 +44286,14 @@ "confirmation_index": 4, "price": 106 } - ], - "states": [ - { - "state": "searching", - "confirmed_event": null, - "confirmed_count": 0, - "provisional_kind": "unknown", - "provisional_index": null, - "provisional_price": null - }, - { - "state": "searching", - "confirmed_event": null, - "confirmed_count": 0, - "provisional_kind": "unknown", - "provisional_index": null, - "provisional_price": null - }, - { - "state": "up", - "confirmed_event": { - "kind": "low", - "event_index": 0, - "confirmation_index": 2, - "price": 100 - }, - "confirmed_count": 1, - "provisional_kind": "high", - "provisional_index": 2, - "provisional_price": 106 - } ] }, "outputElided": null, - "outputShape": "object with 2 fields: pivots, states" + "outputShape": "object with 1 field: pivots" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -44759,29 +44428,29 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "clusterPivotLevels([{\"kind\":\"high\",\"event_index\":0,\"confirmation_index\":3,\"price\":100},{\"kind\":\"high\",\"event_index\":10,\"confirmation_index\":13,\"price\":100.3},{\"kind\":\"high\",\"event_index\":20,\"confirmation_index\":23,\"price\":99.9}], 50, 3)", + "origin": "fixture", + "verified": true, + "source": "fixture:D08-F01-A03.json", + "call": "clusterPivotLevels([{\"kind\":\"high\",\"event_index\":0,\"confirmation_index\":1,\"price\":100},{\"kind\":\"high\",\"event_index\":2,\"confirmation_index\":3,\"price\":100.3},{\"kind\":\"high\",\"event_index\":4,\"confirmation_index\":5,\"price\":99.9}], 50, 3)", "args": [ { "value": [ { "kind": "high", "event_index": 0, - "confirmation_index": 3, + "confirmation_index": 1, "price": 100 }, { "kind": "high", - "event_index": 10, - "confirmation_index": 13, + "event_index": 2, + "confirmation_index": 3, "price": 100.3 }, { "kind": "high", - "event_index": 20, - "confirmation_index": 23, + "event_index": 4, + "confirmation_index": 5, "price": 99.9 } ], @@ -44809,20 +44478,20 @@ "lower": 99.9, "upper": 100.3, "touch_count": 3, - "first_confirmation_index": 3, - "last_confirmation_index": 23, + "first_confirmation_index": 1, + "last_confirmation_index": 5, "member_event_indexes": [ 0, - 10, - 20 + 2, + 4 ] } ], "noise": [ { "kind": "high", - "event_index": 30, - "confirmation_index": 33, + "event_index": 6, + "confirmation_index": 7, "price": 105 } ] @@ -44831,8 +44500,8 @@ "outputShape": "object with 2 fields: clusters, noise" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -44990,29 +44659,29 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "fitRobustTrendline([{\"kind\":\"low\",\"event_index\":0,\"confirmation_index\":3,\"price\":99.48431564193378},{\"kind\":\"low\",\"event_index\":10,\"confirmation_index\":13,\"price\":109.94717245212351},{\"kind\":\"low\",\"event_index\":20,\"confirmation_index\":23,\"price\":121.51041751873485}], \"low\", 75, 3, 12, 40)", + "origin": "fixture", + "verified": true, + "source": "fixture:D08-F01-A04.json", + "call": "fitRobustTrendline([{\"kind\":\"low\",\"event_index\":0,\"confirmation_index\":2,\"price\":99.48431564193378},{\"kind\":\"low\",\"event_index\":10,\"confirmation_index\":12,\"price\":109.94717245212352},{\"kind\":\"low\",\"event_index\":20,\"confirmation_index\":22,\"price\":121.51041751873485}], \"low\", 50, 3, 12)", "args": [ { "value": [ { "kind": "low", "event_index": 0, - "confirmation_index": 3, + "confirmation_index": 2, "price": 99.48431564193378 }, { "kind": "low", "event_index": 10, - "confirmation_index": 13, - "price": 109.94717245212351 + "confirmation_index": 12, + "price": 109.94717245212352 }, { "kind": "low", "event_index": 20, - "confirmation_index": 23, + "confirmation_index": 22, "price": 121.51041751873485 } ], @@ -45027,7 +44696,7 @@ "elided": null }, { - "value": 75, + "value": 50, "elided": null }, { @@ -45037,18 +44706,14 @@ { "value": 12, "elided": null - }, - { - "value": 40, - "elided": null } ], "output": { "kind": "low", "slope_log_per_bar": 0.010000000000000009, "intercept_log": 4.6, - "projected_index": 40, - "projected_price": 148.4131591025766, + "projected_index": 31, + "projected_price": 135.63941440846523, "inlier_count": 3, "outlier_count": 1, "median_absolute_residual_bps": 0, @@ -45063,8 +44728,8 @@ "outputShape": "object with 10 fields: kind, slope_log_per_bar, intercept_log, projected_index, projected_price, inlier_count, outlier_count, median_absolute_residual_bps, …" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -45139,34 +44804,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/double-top", - "entry": "double_top", - "params": [], + "entry": "doubleTop", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "doubleTop" ], "archetype": "record-transform", - "signature": "double_top()" + "signature": "doubleTop(close, params)" }, "api": { - "summary": "Double top detection: two comparable highs separated by a trough, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Double top detection: two comparable highs separated by a trough, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. This topic wrapper accepts the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -45175,10 +44865,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "double_top([100,101,102,103,104,105])", + "call": "doubleTop([100,101,102,103,104,105])", "args": [ { "value": [ @@ -45353,34 +45043,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/double-bottom", - "entry": "double_bottom", - "params": [], + "entry": "doubleBottom", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "doubleBottom" ], "archetype": "record-transform", - "signature": "double_bottom()" + "signature": "doubleBottom(close, params)" }, "api": { - "summary": "Double bottom detection: two comparable lows separated by a peak, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Double bottom detection: two comparable lows separated by a peak, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. This topic wrapper accepts the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -45389,10 +45104,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "double_bottom([120,119,118,117,116,115])", + "call": "doubleBottom([120,119,118,117,116,115])", "args": [ { "value": [ @@ -45567,34 +45282,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/triple-top", - "entry": "triple_top", - "params": [], + "entry": "tripleTop", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "tripleTop" ], "archetype": "record-transform", - "signature": "triple_top()" + "signature": "tripleTop(close, params)" }, "api": { - "summary": "Triple top detection: three comparable highs, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Triple top detection: three comparable highs, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. This topic wrapper accepts the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -45603,10 +45343,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "triple_top([100,101.125,102.25,103.375,104.5,105.625])", + "call": "tripleTop([100,101.125,102.25,103.375,104.5,105.625])", "args": [ { "value": [ @@ -45793,34 +45533,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/triple-bottom", - "entry": "triple_bottom", - "params": [], + "entry": "tripleBottom", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "tripleBottom" ], "archetype": "record-transform", - "signature": "triple_bottom()" + "signature": "tripleBottom(close, params)" }, "api": { - "summary": "Triple bottom detection: three comparable lows, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Triple bottom detection: three comparable lows, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -45829,10 +45594,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "triple_bottom([120,118.875,117.75,116.625,115.5,114.375])", + "call": "tripleBottom([120,118.875,117.75,116.625,115.5,114.375])", "args": [ { "value": [ @@ -46019,34 +45784,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/head-and-shoulders", - "entry": "head_and_shoulders", - "params": [], + "entry": "headAndShoulders", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "headAndShoulders" ], "archetype": "record-transform", - "signature": "head_and_shoulders()" + "signature": "headAndShoulders(close, params)" }, "api": { - "summary": "Head and shoulders detection: a central high flanked by two lower highs, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Head and shoulders detection: a central high flanked by two lower highs, confirmed on a close below the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. This topic wrapper accepts the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -46055,10 +45845,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "head_and_shoulders([100,101.125,102.25,103.375,104.5,105.625])", + "call": "headAndShoulders([100,101.125,102.25,103.375,104.5,105.625])", "args": [ { "value": [ @@ -46245,34 +46035,59 @@ }, "import": { "subpath": "fintech-algorithms/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders", - "entry": "inverse_head_and_shoulders", - "params": [], + "entry": "inverseHeadAndShoulders", + "params": [ + "close", + "params" + ], "exports": [ "confirmedPivots", "detectReversal", "traceReversal", - "double_top", - "double_bottom", - "triple_top", - "triple_bottom", - "head_and_shoulders", - "inverse_head_and_shoulders" + "inverseHeadAndShoulders" ], "archetype": "record-transform", - "signature": "inverse_head_and_shoulders()" + "signature": "inverseHeadAndShoulders(close, params)" }, "api": { - "summary": "Inverse head and shoulders detection: a central low flanked by two higher lows, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. Takes the close series and detection parameters, both supplied by the shared family implementation.", - "params": [], + "summary": "Inverse head and shoulders detection: a central low flanked by two higher lows, confirmed on a close above the neckline. Chart patterns are usually described in prose vague enough to fit almost anything; encoding one forces a decision about how close \"comparable\" is and how much confirmation is required, and this returns those tolerances alongside the verdict. This topic wrapper accepts the close series and detection parameters, then delegates to the family detector core.", + "params": [ + { + "name": "close", + "type": "number[]", + "required": true, + "description": "Finite, strictly positive closes in chronological order.", + "constraints": null, + "nulls": null, + "default": null + }, + { + "name": "params", + "type": "Record", + "required": false, + "description": "Optional pivot, geometry, prior-trend, and confirmation overrides; unknown keys are rejected.", + "constraints": null, + "nulls": null, + "default": "{}" + } + ], "returns": { "type": "{ pattern, state, reason, event, events, pivots, parameters }", - "description": "A `state` rather than a boolean — forming, confirmed or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." + "description": "A `state` rather than a boolean — searching, candidate, confirmed, or rejected — with the `reason`, the pivots that formed it, and the `parameters` in force. The parameters are the point: the same series yields a different answer under different tolerances, and a pattern reported without them cannot be reproduced." }, "warmup": null, "errors": [ { - "when": "fewer bars are supplied than the pattern needs", - "behaviour": "returned as a rejected state rather than thrown" + "when": "close is empty, non-finite, zero, or negative", + "behaviour": "throws an Error" + }, + { + "when": "a parameter is unknown or outside its accepted range", + "behaviour": "throws an Error" + }, + { + "when": "a valid non-empty series has insufficient confirmed pivots", + "behaviour": "returns state `searching` rather than throwing" } ], "complexity": { @@ -46281,10 +46096,10 @@ } }, "example": { - "origin": "derived", + "origin": "executed", "verified": false, "source": "executed against the catalog's own test input", - "call": "inverse_head_and_shoulders([120,118.875,117.75,116.625,115.5,114.375])", + "call": "inverseHeadAndShoulders([120,118.875,117.75,116.625,115.5,114.375])", "args": [ { "value": [ @@ -46496,7 +46311,36 @@ "archetype": "record-transform", "signature": "priceIndicatorPivotAlignment(payload)" }, - "api": null, + "api": { + "summary": "Aligns confirmed price and indicator pivots of the same kind within an explicit lag bound while preserving both event and knowledge indexes.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing price pivots, indicator definitions, and `parameters.max_lag`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, alignments, alignment_count?, reason }", + "description": "One alignment record. `state` is `warmup` when no indicator pivots or fewer than two alignments are available and `ready` otherwise; it does not describe leading null positions in a returned series." + }, + "warmup": { + "count": "2 eligible aligned pivots", + "value": "state: warmup", + "note": "The function returns one alignment record when fewer than two causal alignments are available; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "pivot identity, chronology, value, scale, polarity, or max-lag input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(p x q log q)\", space: \"O(p + q)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -46854,7 +46698,32 @@ "archetype": "record-transform", "signature": "regularBullishBearishDivergenceDetection(payload)" }, - "api": null, + "api": { + "summary": "Detects regular bullish and bearish divergence from causally aligned consecutive pivot pairs.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing price pivots, indicators, and separation, alignment, price, and indicator thresholds.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, events, event_count }", + "description": "One detection record with `state` equal to `detected` or `not-detected` and regular-divergence event diagnostics." + }, + "warmup": null, + "errors": [ + { + "when": "pivot, indicator, lag, separation, or divergence-threshold input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(k x p x q log q)\", space: \"O(p + q + events)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -47263,7 +47132,32 @@ "archetype": "record-transform", "signature": "hiddenBullishBearishDivergenceDetection(payload)" }, - "api": null, + "api": { + "summary": "Detects hidden bullish and bearish divergence from causally aligned consecutive pivot pairs.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing price pivots, indicators, and separation, alignment, price, and indicator thresholds.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, events, event_count }", + "description": "One detection record with `state` equal to `detected` or `not-detected` and hidden-divergence event diagnostics." + }, + "warmup": null, + "errors": [ + { + "when": "pivot, indicator, lag, separation, or divergence-threshold input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(k x p x q log q)\", space: \"O(p + q + events)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -47672,7 +47566,36 @@ "archetype": "record-transform", "signature": "multiIndicatorDivergenceAdapters(payload)" }, - "api": null, + "api": { + "summary": "Normalizes indicator pivots into one polarity- and scale-aware representation for downstream divergence logic.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing zero or more named indicator definitions and their confirmed pivots.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, adapters, adapter_count }", + "description": "One adapter record. `state` is `warmup` when no indicators were supplied and `ready` when at least one adapter was built; no positional warmup series is returned." + }, + "warmup": { + "count": "1 supplied indicator", + "value": "state: warmup", + "note": "The function returns one adapter record when no indicator is supplied; it does not emit a positional null prefix." + }, + "errors": [ + { + "when": "an indicator lacks valid identity, family, polarity, scale, or pivot fields", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(pivots)\", space: \"O(pivots)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -48069,7 +47992,32 @@ "archetype": "record-transform", "signature": "divergenceStrengthAndQualityScoring(payload)" }, - "api": null, + "api": { + "summary": "Scores the first detected divergence from explicit geometry, prominence, alignment, and separation components.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing the price pivots, indicators, and detection parameters needed to produce a divergence event.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, event?, score, reason? }", + "description": "One scoring record: `not-detected` with null score and a reason, or `scored` with the event and component score object." + }, + "warmup": null, + "errors": [ + { + "when": "the underlying pivot, indicator, detection, or score inputs are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(k x p x q log q)\", space: \"O(p + q + events)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -48431,7 +48379,32 @@ "archetype": "record-transform", "signature": "divergenceConfirmationAndInvalidationStateMachine(payload)" }, - "api": null, + "api": { + "summary": "Advances the first detected divergence through causal confirmation, invalidation, and expiry checks.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing divergence inputs, bars, confirmation horizon, and invalidation buffer.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, event, lifecycle }", + "description": "One lifecycle record. Without an event, `state` is `searching`; otherwise it mirrors the lifecycle state (`candidate`, `confirmed`, `invalidated`, or `expired`) and includes causal levels and trace." + }, + "warmup": null, + "errors": [ + { + "when": "detection input, bar data, confirmation horizon, or invalidation buffer is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(k x p x q log q + bars)\", space: \"O(events + bars)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -48806,7 +48779,32 @@ "archetype": "record-transform", "signature": "multiIndicatorDivergenceConfluence(payload)" }, - "api": null, + "api": { + "summary": "Combines same-geometry divergence events across distinct indicators using declared non-negative weights.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing divergence inputs, indicator weights, and `parameters.minimum_indicators`.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, groups, group_count }", + "description": "One confluence record with `state` equal to `confluent` or `insufficient-confluence` and deterministic group scores." + }, + "warmup": null, + "errors": [ + { + "when": "event, weight, or minimum-indicator input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(events log events)\", space: \"O(events)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -49151,7 +49149,32 @@ "archetype": "record-transform", "signature": "marketWideDivergenceScannerAndRanking(payload)" }, - "api": null, + "api": { + "summary": "Filters point-in-time eligible universe records and ranks them from explicit confluence, state, freshness, liquidity, and data-quality components.", + "params": [ + { + "name": "payload", + "type": "{ topic_id: string; data_class: string; as_of: string; bars: { timestamp: string; open: number; high: number; low: number; close: number; finalized: boolean }[]; price_pivots: { kind: string; event_index: number; confirmation_index: number; price: number; prominence: number }[]; indicators: { name: string; family: string; polarity: number; scale: number; pivots: { kind: string; event_index: number; confirmation_index: number; value: number; prominence: number }[] }[]; parameters: { max_lag: number; min_separation: number; max_separation: number; min_price_fraction: number; min_indicator_delta: number; confirmation_horizon: number; invalidation_buffer: number; minimum_indicators: number }; weights: { RSI: number; MACD-Histogram: number; Stochastic-K: number }; as_of_index: number; universe: { symbol: string; state: string; divergence_type: string; confluence_score: number; freshness: number; liquidity: number; data_quality: number; available_index: number; eligible: boolean }[] }", + "required": true, + "description": "Topic payload containing `universe` records and an `as_of_index` or bars from which that index can be derived.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ topic_id, state, ranking, eligible_count }", + "description": "One scanner record with `state` equal to `ranked` or `empty`; each eligible row has a stable rank and component trace." + }, + "warmup": null, + "errors": [ + { + "when": "as-of index, universe score, availability, or scanner-state input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n log n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -49515,7 +49538,32 @@ "archetype": "record-transform", "signature": "priceByVolumeProfileConstruction(input)" }, - "api": null, + "api": { + "summary": "Aggregates eligible point-in-time trades into deterministic tick-aligned price-by-volume bins.", + "params": [ + { + "name": "input", + "type": "{ tick_size: number; bin_size_ticks: number; window_end: string; trades: { trade_id: string; timestamp: string; price: number; volume: number; final: boolean }[] }", + "required": true, + "description": "Record containing `tick_size`, `bin_size_ticks`, `window_end`, and chronologically ordered unique trades.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, tick_size, bin_size_ticks, bin_width, total_volume, trade_count, eligible_trade_count, rows }", + "description": "One `calculated` profile record; each row contains bin index, bounds, midpoint, volume, and volume share." + }, + "warmup": null, + "errors": [ + { + "when": "tick/bin settings, window time, trade identity, chronology, price, or volume is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(t log t)\", space: \"O(b)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -49676,7 +49724,36 @@ "archetype": "record-transform", "signature": "pocValueAreaHvnLvnDetection(input)" }, - "api": null, + "api": { + "summary": "Selects the point of control, expands a deterministic value area, and identifies local high- and low-volume nodes.", + "params": [ + { + "name": "input", + "type": "{ profile_rows: { lower: number; upper: number; volume: number }[]; value_area_fraction: number; hvn_median_ratio: number; lvn_median_ratio: number }", + "required": true, + "description": "Record containing at least three ordered contiguous `profile_rows` and declared value-area, HVN, and LVN thresholds.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, poc_index, poc_price, poc_volume, value_area_low, value_area_high, value_area_volume, value_area_share, target_share, included_indices, expansion_trace, hvn, lvn }", + "description": "One `calculated` feature record with auditable expansion order and node diagnostics; insufficient rows are rejected rather than emitted as positional warmup." + }, + "warmup": { + "count": "0", + "value": "not emitted", + "note": "This record transform has no warm-up output: fewer than three profile rows are rejected explicitly instead of producing positional or state warm-up values." + }, + "errors": [ + { + "when": "profile rows are too few, unordered, non-contiguous, or thresholds are outside their canonical ranges", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(b log b)\", space: \"O(b)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -49840,7 +49917,32 @@ "archetype": "record-transform", "signature": "fibonacciRetracementExtensionProjection(input)" }, - "api": null, + "api": { + "summary": "Projects declared retracement and extension ratios from a directed price leg and snaps every level to the nearest tick.", + "params": [ + { + "name": "input", + "type": "{ start_price: number; end_price: number; retracement_end_price: number; tick_size: number; retracement_ratios: number[]; extension_ratios: number[] }", + "required": true, + "description": "Record containing leg anchors, retracement-end anchor, tick size, and non-empty retracement and extension ratio lists.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, direction, leg_size, retracement_levels, extension_levels, rounding }", + "description": "One `calculated` projection record; each level reports its ratio, raw price, and tick-snapped price." + }, + "warmup": null, + "errors": [ + { + "when": "anchors coincide, tick size is invalid, ratios are empty, or ratios fall outside allowed ranges", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(r + e)\", space: \"O(r + e)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -49997,7 +50099,32 @@ "archetype": "record-transform", "signature": "psychologicalRoundNumberLevelGeneration(input)" }, - "api": null, + "api": { + "summary": "Generates tick-aligned round-number levels inside explicit bounds and labels their salience and distance from current price.", + "params": [ + { + "name": "input", + "type": "{ current_price: number; lower_bound: number; upper_bound: number; tick_size: number; base_unit: number }", + "required": true, + "description": "Record containing current price, lower/upper bounds, tick size, and an aligned base unit.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, base_unit, level_count, closest_level, levels }", + "description": "One `calculated` level record; every level reports class, salience weight, absolute distance, and basis-point distance." + }, + "warmup": null, + "errors": [ + { + "when": "bounds are inconsistent, tick/base-unit values are invalid or misaligned, or the bounds contain no levels", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(levels)\", space: \"O(levels)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -50131,7 +50258,32 @@ "archetype": "record-transform", "signature": "multiSourceSupportResistanceZoneFusion(input)" }, - "api": null, + "api": { + "summary": "Clusters nearby levels, computes deterministic zone centers, and separates accepted multi-source zones from rejected clusters.", + "params": [ + { + "name": "input", + "type": "{ fusion_tolerance: number; minimum_sources: number; levels: { level_id: string; source: string; price: number; weight: number }[] }", + "required": true, + "description": "Record containing non-empty uniquely identified levels, fusion tolerance, and minimum distinct-source count.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, zones, rejected_clusters, fusion_tolerance, minimum_sources }", + "description": "One `calculated` fusion record with ranked accepted zones and reason-coded rejected clusters." + }, + "warmup": null, + "errors": [ + { + "when": "levels are empty, identities repeat, source/price/weight fields are invalid, or fusion settings are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n log n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -50303,7 +50455,32 @@ "archetype": "record-transform", "signature": "supportResistanceZoneStrengthDecayScoring(input)" }, - "api": null, + "api": { + "summary": "Scores zone strength from source confluence, decayed touches, rejection quality, durability, and break penalties.", + "params": [ + { + "name": "input", + "type": "{ source_confluence: number; zone_age_bars: number; half_life_bars: number; break_count: number; rejection_target_atr: number; touches: { age_bars: number; rejection_atr: number }[] }", + "required": true, + "description": "Record containing source confluence, zone age, decay half-life, break count, rejection target, and touch observations.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, score, grade, components, decayed_touch_evidence, touch_count }", + "description": "One `calculated` score record with a bounded 0-100 score, qualitative grade, and every component contribution." + }, + "warmup": null, + "errors": [ + { + "when": "confluence, age, half-life, break-count, rejection, or touch input is outside its declared range", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(touches)\", space: \"O(touches)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -50436,7 +50613,32 @@ "archetype": "record-transform", "signature": "supportResistanceRoleReversalStateMachine(input)" }, - "api": null, + "api": { + "summary": "Processes closes through active-role, break, retest, confirmation, and invalidation transitions for one zone.", + "params": [ + { + "name": "input", + "type": "{ zone_lower: number; zone_upper: number; break_buffer: number; confirmation_closes: number; initial_role: string; closes: number[] }", + "required": true, + "description": "Record containing zone bounds, break buffer, required confirmation closes, initial role, and non-empty close observations.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, final_role, confirmed, retest_seen, transitions, observations }", + "description": "One state-machine record with final role, confirmation flag, retest flag, observation count, and transition trace." + }, + "warmup": null, + "errors": [ + { + "when": "zone bounds, role, confirmation count, buffer, or close observations are invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(transitions)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -50572,7 +50774,36 @@ "archetype": "record-transform", "signature": "breakoutAndRetestDetection(input)" }, - "api": null, + "api": { + "summary": "Processes bars through breakout-pending, retest, confirmation, failure, and expiry states around one zone.", + "params": [ + { + "name": "input", + "type": "{ zone_lower: number; zone_upper: number; break_buffer: number; retest_tolerance: number; breakout_closes: number; max_retest_bars: number; direction: string; bars: { high: number; low: number; close: number }[] }", + "required": true, + "description": "Record containing zone bounds, buffers/tolerance, breakout close count, retest horizon, direction, and non-empty bars.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, confirmed, direction, breakout_index, retest_index, confirmation_index, transitions }", + "description": "One state-machine record with nullable event indexes and a complete transition trace; no positional warmup series is returned." + }, + "warmup": { + "count": "0", + "value": "not emitted", + "note": "This state machine has no warm-up output: an empty bar set is rejected and valid observations begin in searching state rather than a positional warm-up series." + }, + "errors": [ + { + "when": "zone, direction, buffer, count, horizon, or bar geometry input is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n)\", space: \"O(transitions)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -50724,7 +50955,32 @@ "archetype": "record-transform", "signature": "marketWideZoneProximityScannerRanking(input)" }, - "api": null, + "api": { + "summary": "Filters point-in-time zone records by proximity and ranks eligible instruments from proximity, strength, and freshness.", + "params": [ + { + "name": "input", + "type": "{ as_of: string; max_distance_bps: number; freshness_half_life_hours: number; instruments: { instrument_id: string; current_price: number; zone_lower: number; zone_upper: number; zone_strength: number; observed_at: string }[] }", + "required": true, + "description": "Record containing zoned `as_of`, maximum distance, freshness half-life, and non-empty unique instrument records.", + "constraints": null, + "nulls": null, + "default": null + } + ], + "returns": { + "type": "{ state, as_of, eligible_count, ranked }", + "description": "One `calculated` scanner record; eligible rows include inside-zone flag, distances, strength, freshness, score, and stable rank." + }, + "warmup": null, + "errors": [ + { + "when": "as-of time, thresholds, instrument identity, zone geometry, price, strength, or observation time is invalid", + "behaviour": "throws" + } + ], + "complexity": "{ time: \"O(n log n)\", space: \"O(n)\" }" + }, "example": { "origin": "executed", "verified": false, @@ -52126,9 +52382,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A01.json", "call": "forecastAutoReg([10,12,11], [0.5], 5, 2)", "args": [ { @@ -52158,30 +52414,14 @@ "forecast": [ 10.5, 10.25 - ], - "fitted": [ - null, - 10, - 11 - ], - "residuals": [ - null, - 2, - 0 - ], - "state": { - "order": 1, - "last_values": [ - 11 - ] - } + ] }, "outputElided": null, - "outputShape": "object with 4 fields: forecast, fitted, residuals, state" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -52349,9 +52589,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A02.json", "call": "forecastARMA([10,12,11], [0.5], [0.25], 5, 2)", "args": [ { @@ -52387,38 +52627,14 @@ "forecast": [ 10.375, 10.1875 - ], - "fitted": [ - null, - 10, - 11.5 - ], - "residuals": [ - 0, - 2, - -0.5 - ], - "state": { - "order": [ - 1, - 1 - ], - "last_values": [ - 11 - ], - "last_residuals": [ - -0.5 - ], - "presample_innovations": "zero", - "future_innovations": "zero conditional mean" - } + ] }, "outputElided": null, - "outputShape": "object with 4 fields: forecast, fitted, residuals, state" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -52599,9 +52815,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A03.json", "call": "forecastARIMA([100,102,105,109,114,120], [0.5], [], 1, 1, 2)", "args": [ { @@ -52642,50 +52858,14 @@ "forecast": [ 124, 127 - ], - "fitted": [ - null, - 2, - 2.5, - 3, - 3.5 - ], - "residuals": [ - 0, - 1, - 1.5, - 2, - 2.5 - ], - "state": { - "order": [ - 1, - 0 - ], - "last_values": [ - 6 - ], - "last_residuals": [ - 2.5 - ], - "presample_innovations": "zero", - "future_innovations": "zero conditional mean", - "difference_order": 1, - "integration_anchors": [ - 120 - ] - }, - "differenced_forecast": [ - 4, - 3 ] }, "outputElided": null, - "outputShape": "object with 5 fields: forecast, fitted, residuals, state, differenced_forecast" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -52942,9 +53122,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A04.json", "call": "forecastSARIMAX([12,15,18,21,24,27], [[1],[2],[3]], [[9],[10]], [2], [0.5], [], [0.25], [], 0, 1, 0, 2, 2)", "args": [ { @@ -53042,76 +53222,14 @@ "forecast": [ 35.625, 38.0625 - ], - "fitted": [ - null, - null, - null, - 0.625, - 0.625, - 0.625 - ], - "residuals": [ - 0, - 0, - 0, - 0.375, - 0.375, - 0.375 - ], - "state": { - "order": [ - 3, - 0 - ], - "last_values": [ - 1, - 1, - 1 - ], - "last_residuals": [ - 0.375 - ], - "presample_innovations": "zero", - "future_innovations": "zero conditional mean", - "orders": { - "nonseasonal": [ - 1, - 1, - 0 - ], - "seasonal": [ - 1, - 0, - 0, - 2 - ] - }, - "combined_ar": [ - 0.5, - 0.25, - -0.125 - ], - "combined_ma": [], - "beta": [ - 2 - ] - }, - "transformed_forecast": [ - 0.625, - 0.4375 - ], - "residualized_forecast": [ - 17.625, - 18.0625 ] }, "outputElided": null, - "outputShape": "object with 6 fields: forecast, fitted, residuals, state, transformed_forecast, residualized_forecast" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -53334,9 +53452,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A05.json", "call": "forecastHoltWintersAdditive([10,12,11,13], 0.5, 0.5, 0.5, 2, 2, 9, 1, [-1,1])", "args": [ { @@ -53388,54 +53506,14 @@ "forecast": [ 12.35546875, 14.58203125 - ], - "fitted": [ - 9, - 12.75, - 11.6875, - 13.796875 - ], - "residuals": [ - 1, - -0.75, - -0.6875, - -0.796875 - ], - "trace": [ - { - "index": 0, - "level": 10.5, - "trend": 1.25, - "seasonal": -0.75 - }, - { - "index": 1, - "level": 11.375, - "trend": 1.0625, - "seasonal": 0.8125 - }, - { - "index": 2, - "level": 12.09375, - "trend": 0.890625, - "seasonal": -0.921875 - } - ], - "state": { - "level": 12.5859375, - "trend": 0.69140625, - "seasonals": [ - -0.921875, - 0.61328125 - ] - } + ] }, "outputElided": null, - "outputShape": "object with 5 fields: forecast, fitted, residuals, trace, state" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -53585,9 +53663,9 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F02-A06.json", "call": "forecastTheta([10,12,14,16], 0.5, 2)", "args": [ { @@ -53612,26 +53690,14 @@ "forecast": [ 16.125, 17.125 - ], - "fitted": [ - null, - 10, - 11, - 12.5 - ], - "state": { - "ses_level": 14.25, - "ols_slope": 2, - "alpha": 0.5, - "finite_sample_correction": 1.875 - } + ] }, "outputElided": null, - "outputShape": "object with 3 fields: forecast, fitted, state" + "outputShape": "object with 1 field: forecast" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -55103,25 +55169,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([0.1740371542,0.7180296431,0.0364260071,-0.3580458703,0.3552038047,0.4311906307], {\"a\":0.96,\"h\":1,\"q\":0.08,\"r\":0.64,\"initial_mean\":0,\"initial_variance\":2})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A01.json", + "call": "runFilter([0.1740371542,0.7180296431,0.0364260071], {\"a\":0.96,\"h\":1,\"q\":0.08,\"r\":0.64,\"initial_mean\":0,\"initial_variance\":2})", "args": [ { "value": [ 0.1740371542, 0.7180296431, - 0.0364260071, - -0.3580458703, - 0.3552038047, - 0.4311906307 + 0.0364260071 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -55135,30 +55194,8 @@ "elided": null } ], - "output": [ - { - "index": 0, - "predicted_mean": 0, - "predicted_variance": 1.9232, - "predicted_observation": 0, - "innovation": 0.1740371542, - "innovation_variance": 2.5632, - "kalman_gain": 0.7503121098626716, - "filtered_mean": 0.1305821843622971, - "filtered_variance": 0.4801997503121099 - }, - { - "index": 1, - "predicted_mean": 0.12535889698780522, - "predicted_variance": 0.5225520898876405, - "predicted_observation": 0.12535889698780522, - "innovation": 0.5926707461121947, - "innovation_variance": 1.1625520898876405, - "kalman_gain": 0.4494870332546945, - "filtered_mean": 0.3917567123546219, - "filtered_variance": 0.28767170128300446 - }, - { + "output": { + "2": { "index": 2, "predicted_mean": 0.376086443860437, "predicted_variance": 0.3451182399024169, @@ -55169,17 +55206,13 @@ "filtered_mean": 0.25709259383197747, "filtered_variance": 0.22421234791006017 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -55318,25 +55351,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([0.1740564489,0.7180957323,0.0365723689,-0.3580227464,0.3553945738,0.4323328535], {\"a\":0.9,\"b\":0.22,\"c\":0.04,\"q\":0.06,\"r\":0.49,\"initial_mean\":0,\"initial_variance\":1.5})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A02.json", + "call": "runFilter([0.1740564489,0.7180957323,0.0365723689], {\"a\":0.9,\"b\":0.22,\"c\":0.04,\"q\":0.06,\"r\":0.49,\"initial_mean\":0,\"initial_variance\":1.5})", "args": [ { "value": [ 0.1740564489, 0.7180957323, - 0.0365723689, - -0.3580227464, - 0.3553945738, - 0.4323328535 + 0.0365723689 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -55351,34 +55377,8 @@ "elided": null } ], - "output": [ - { - "index": 0, - "transition_jacobian": 1.12, - "measurement_jacobian": 1, - "predicted_mean": 0, - "predicted_variance": 1.9416000000000002, - "predicted_observation": 0, - "innovation": 0.1740564489, - "innovation_variance": 2.4316000000000004, - "kalman_gain": 0.7984865931896693, - "filtered_mean": 0.13898174090485277, - "filtered_variance": 0.391258430662938 - }, - { - "index": 1, - "transition_jacobian": 1.1178786662536586, - "measurement_jacobian": 1.0124448968753026, - "predicted_mean": 0.15556121094128242, - "predicted_variance": 0.5489371591527625, - "predicted_observation": 0.15652918255526316, - "innovation": 0.5615665497447369, - "innovation_variance": 1.0526851087201852, - "kalman_gain": 0.5279533460534298, - "filtered_mean": 0.452042149910696, - "filtered_variance": 0.25551725369409706 - }, - { + "output": { + "2": { "index": 2, "transition_jacobian": 1.0979025313193456, "measurement_jacobian": 1.040234775932769, @@ -55391,17 +55391,13 @@ "filtered_mean": 0.2975785852529078, "filtered_variance": 0.20301476071185573 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -55540,25 +55536,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([0.1740564489,0.7180957323,0.0365723689,-0.3580227464,0.3553945738,0.4323328535], {\"a\":0.9,\"b\":0.22,\"c\":0.04,\"q\":0.06,\"r\":0.49,\"alpha\":1,\"beta\":2,\"kappa\":0,\"initial_mean\":0,\"initial_variance\":1.5})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A03.json", + "call": "runFilter([0.1740564489,0.7180957323,0.0365723689], {\"a\":0.9,\"b\":0.22,\"c\":0.04,\"q\":0.06,\"r\":0.49,\"alpha\":1,\"beta\":2,\"kappa\":0,\"initial_mean\":0,\"initial_variance\":1.5})", "args": [ { "value": [ 0.1740564489, 0.7180957323, - 0.0365723689, - -0.3580227464, - 0.3553945738, - 0.4323328535 + 0.0365723689 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -55576,36 +55565,8 @@ "elided": null } ], - "output": [ - { - "index": 0, - "sigma_left": -1.224744871391589, - "sigma_center": 0, - "sigma_right": 1.224744871391589, - "predicted_mean": 0, - "predicted_variance": 1.7740796257097713, - "predicted_measurement": 0.07096318502839094, - "innovation": 0.10309326387160905, - "innovation_variance": 2.2741511729685184, - "kalman_gain": 0.7801062861595132, - "filtered_mean": 0.08042370320694366, - "filtered_variance": 0.3901089575460621 - }, - { - "index": 1, - "sigma_left": -0.5441633263942658, - "sigma_center": 0.08042370320694366, - "sigma_right": 0.7050107328081532, - "predicted_mean": 0.08671868415920991, - "predicted_variance": 0.536619496516218, - "predicted_measurement": 0.10848426922715082, - "innovation": 0.6096114630728492, - "innovation_variance": 1.0350123867965022, - "kalman_gain": 0.5220635987934528, - "filtered_mean": 0.4049746384367636, - "filtered_variance": 0.2545264552632097 - }, - { + "output": { + "2": { "index": 2, "sigma_left": -0.0995315114397366, "sigma_center": 0.4049746384367636, @@ -55619,17 +55580,13 @@ "filtered_mean": 0.2577947817954489, "filtered_variance": 0.20295800755826507 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -55768,25 +55725,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([-0.9183368993,-0.5364890278,-0.550167602,-1.0221111597,-0.9348142289,-0.5355520167], {\"transition\":[[0.94,0.06],[0.12,0.88]],\"means\":[-0.15,0.25],\"stds\":[0.55,1.45],\"initial\":[0.8,0.2]})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A04.json", + "call": "runFilter([-0.9183368993,-0.5364890278,-0.550167602], {\"transition\":[[0.94,0.06],[0.12,0.88]],\"means\":[-0.15,0.25],\"stds\":[0.55,1.45],\"initial\":[0.8,0.2]})", "args": [ { "value": [ -0.9183368993, -0.5364890278, - -0.550167602, - -1.0221111597, - -0.9348142289, - -0.5355520167 + -0.550167602 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -55816,45 +55766,23 @@ "elided": null } ], - "output": [ - { - "index": 0, - "predicted_state_0": 0.776, - "predicted_state_1": 0.22400000000000003, - "posterior_state_0": 0.8264612333826495, - "posterior_state_1": 0.17353876661735046, - "most_likely_state": 0, - "log_predictive_density": -1.3598732483743445 - }, - { - "index": 1, - "predicted_state_0": 0.7976982113737725, - "predicted_state_1": 0.20230178862622736, - "posterior_state_0": 0.9039212244809284, - "posterior_state_1": 0.09607877551907154, - "most_likely_state": 0, - "log_predictive_density": -0.6930121943884898 - }, - { + "output": { + "2": { "index": 2, "predicted_state_0": 0.8612154040743613, "predicted_state_1": 0.13878459592563866, - "posterior_state_0": 0.9359801579550975, + "posterior_state_0": 0.9359801579550974, "posterior_state_1": 0.0640198420449025, "most_likely_state": 0, "log_predictive_density": -0.6690356366768324 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -55981,25 +55909,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([-0.0710447869,0.2119198541,0.4036856432,0.1288063984,0.0072781565,0.2691322581], {\"transition\":[[0.95,0.05],[0.1,0.9]],\"intercepts\":[0.12,-0.18],\"phis\":[0.72,-0.3],\"stds\":[0.35,1.05],\"initial\":[0.85,0.15]})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A05.json", + "call": "runFilter([-0.0710447869,0.2119198541,0.4036856432], {\"transition\":[[0.95,0.05],[0.1,0.9]],\"intercepts\":[0.12,-0.18],\"phis\":[0.72,-0.3],\"stds\":[0.35,1.05],\"initial\":[0.85,0.15]})", "args": [ { "value": [ -0.0710447869, 0.2119198541, - 0.4036856432, - 0.1288063984, - 0.0072781565, - 0.2691322581 + 0.4036856432 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -56033,54 +55954,26 @@ "elided": null } ], - "output": [ - { - "index": 0, - "regime_0_forecast": 0.4285714285714285, - "regime_1_forecast": -0.13846153846153844, - "predicted_state_0": 0.8225, - "predicted_state_1": 0.17750000000000002, - "posterior_state_0": 0.8341333456896518, - "posterior_state_1": 0.1658666543103482, - "most_likely_state": 0, - "next_mixture_forecast": 0.025391734996519682, - "log_predictive_density": -0.9020034995504373 - }, - { - "index": 1, - "regime_0_forecast": 0.068847753432, - "regime_1_forecast": -0.15868656393, - "predicted_state_0": 0.809013343836204, - "predicted_state_1": 0.19098665616379595, - "posterior_state_0": 0.9255985027572549, - "posterior_state_1": 0.0744014972427451, - "most_likely_state": 0, - "next_mixture_forecast": 0.2141318776960829, - "log_predictive_density": -0.0872910496699388 - }, - { + "output": { + "2": { "index": 2, "regime_0_forecast": 0.272582294952, "regime_1_forecast": -0.24357595623, - "predicted_state_0": 0.8867587273436666, + "predicted_state_0": 0.8867587273436667, "predicted_state_1": 0.11324127265633334, "posterior_state_0": 0.9636140438968227, - "posterior_state_1": 0.03638595610317734, + "posterior_state_1": 0.03638595610317732, "most_likely_state": 0, "next_mixture_forecast": 0.3530523573178951, - "log_predictive_density": -0.02238977910202937 + "log_predictive_density": -0.022389779102029245 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ @@ -56213,25 +56106,18 @@ } }, "example": { - "origin": "executed", - "verified": false, - "source": "executed against the catalog's own test input", - "call": "runFilter([-0.3275053489,0.2452664583,0.224748597,-0.4831667396,-0.3522213433,0.2466719749], {\"hazard\":0.025,\"observation_variance\":0.36,\"prior_mean\":0,\"prior_variance\":4})", + "origin": "fixture", + "verified": true, + "source": "fixture:D09-F04-A06.json", + "call": "runFilter([-0.3275053489,0.2452664583,0.224748597], {\"hazard\":0.025,\"observation_variance\":0.36,\"prior_mean\":0,\"prior_variance\":4})", "args": [ { "value": [ -0.3275053489, 0.2452664583, - 0.224748597, - -0.4831667396, - -0.3522213433, - 0.2466719749 + 0.224748597 ], - "elided": { - "kind": "array", - "shown": 6, - "total": 160 - } + "elided": null }, { "value": { @@ -56243,45 +56129,23 @@ "elided": null } ], - "output": [ - { - "index": 0, - "change_probability": 0.025000000000000012, - "map_run_length": 1, - "expected_run_length": 0.9750000000000001, - "active_hypotheses": 2, - "map_mean": -0.3004636228440367, - "log_predictive_density": -1.6674749923390564 - }, - { - "index": 1, - "change_probability": 0.012415673831408902, - "map_run_length": 2, - "expected_run_length": 1.9504790441829676, - "active_hypotheses": 3, - "map_mean": -0.0393487514832536, - "log_predictive_density": -0.9621570121513477 - }, - { + "output": { + "2": { "index": 2, - "change_probability": 0.00942784148480788, + "change_probability": 0.00942784148480789, "map_run_length": 3, - "expected_run_length": 2.924161240458136, + "expected_run_length": 2.9241612404581354, "active_hypotheses": 4, "map_mean": 0.04611964608414239, "log_predictive_density": -0.6857585614486436 } - ], - "outputElided": { - "kind": "array", - "shown": 3, - "total": 160 }, - "outputShape": "array of 160 objects" + "outputElided": null, + "outputShape": "object with 1 field: 2" }, "verification": { - "tier": "contract", - "via": null + "tier": "verified", + "via": "input-expected" }, "assets": { "diagrams": [ diff --git a/package-lock.json b/package-lock.json index 1f4818b..dbb1e2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "fintech-algorithms", - "version": "0.11.0", + "version": "0.12.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fintech-algorithms", - "version": "0.11.0", + "version": "0.12.0", "license": "MIT", "devDependencies": { "@types/node": "^22.10.2", diff --git a/package.json b/package.json index 0af8b8a..813ef91 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fintech-algorithms", - "version": "0.11.0", + "version": "0.12.0", "description": "The Fintech Builder algorithm library — canonical, cross-language reference implementations of market-data, corporate-action, index, breadth, candlestick and technical-indicator algorithms, exposed as provider-agnostic subpath modules.", "keywords": [ "fintech", @@ -40,7 +40,7 @@ "sync": "node scripts/sync.mjs && node scripts/update-readme.mjs && node scripts/gen-docs.mjs", "docs": "node scripts/gen-docs.mjs", "examples": "node scripts/capture-examples.mjs", - "build": "tsc -p tsconfig.json", + "build": "node scripts/clean.mjs && tsc -p tsconfig.json", "test": "node --experimental-strip-types --test test/*.test.ts", "test:conformance": "node --experimental-strip-types --test test/conformance.test.ts", "verify": "npm run build && npm test", diff --git a/scripts/clean.mjs b/scripts/clean.mjs new file mode 100644 index 0000000..3a216e7 --- /dev/null +++ b/scripts/clean.mjs @@ -0,0 +1,12 @@ +import { rmSync } from "node:fs"; +import { basename, dirname, join, resolve } from "node:path"; +import { fileURLToPath } from "node:url"; + +const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); +const dist = resolve(join(repoRoot, "dist")); + +if (dirname(dist) !== repoRoot || basename(dist) !== "dist") { + throw new Error(`Refusing to clean unexpected build directory: ${dist}`); +} + +rmSync(dist, { recursive: true, force: true }); diff --git a/scripts/gen-docs.mjs b/scripts/gen-docs.mjs index 155d0b7..29935d2 100644 --- a/scripts/gen-docs.mjs +++ b/scripts/gen-docs.mjs @@ -371,6 +371,15 @@ function apiContract(topic, dir, entryParams) { ); } + for (const param of api.params ?? []) { + if (param.type === "Record") { + apiErrors.push(`${topic.id}: api.params.${param.name} uses opaque Record`); + } + } + if (/warmup|warm-up/i.test(api.returns?.description ?? "") && !api.warmup) { + apiErrors.push(`${topic.id}: return prose mentions warm-up but api.warmup is missing`); + } + return { summary: api.summary ?? null, params: (api.params ?? []).map((p) => ({ diff --git a/scripts/sync.mjs b/scripts/sync.mjs index d7ea1be..7b0dac9 100644 --- a/scripts/sync.mjs +++ b/scripts/sync.mjs @@ -270,6 +270,38 @@ const SHARED_ENTRY_EXEMPT = [ ["D04-F05-A04", "D04-F05-A05"], ]; +/** + * Exact topic sets whose shared implementation intentionally exposes every + * topic entry through every peer subpath. New or expanded broad facades must be + * reviewed here; otherwise sync fails instead of silently widening the public + * API. D08-F02 is deliberately absent because each reversal subpath is private. + */ +const REVIEWED_SHARED_SURFACES = new Set([ + "D01-F05-A01,D01-F05-A02,D01-F05-A03,D01-F05-A04,D01-F05-A05,D01-F05-A06,D01-F05-A07", + "D06-F01-A03,D06-F01-A04,D06-F01-A05,D06-F02-A01,D06-F02-A02,D06-F02-A03,D06-F02-A04,D06-F02-A05,D06-F02-A06,D06-F02-A07,D06-F02-A08,D06-F02-A09,D06-F03-A01,D06-F03-A02,D06-F03-A03,D06-F03-A04,D06-F03-A05,D06-F03-A06,D06-F03-A07,D06-F03-A08", + "D06-F04-A01,D06-F04-A02,D06-F04-A03,D06-F04-A04,D06-F04-A05,D06-F04-A06,D06-F04-A07", + "D07-F03-A01,D07-F03-A02,D07-F03-A03,D07-F03-A04,D07-F03-A05,D07-F03-A06,D07-F03-A07,D07-F03-A08", + "D07-F05-A01,D07-F05-A02,D07-F05-A03,D07-F05-A04,D07-F05-A05,D07-F05-A06", + "D08-F05-A01,D08-F05-A02,D08-F05-A03,D08-F05-A04,D08-F05-A05,D08-F05-A06,D08-F05-A07,D08-F05-A08", + "D08-F06-A01,D08-F06-A02,D08-F06-A03,D08-F06-A04,D08-F06-A05,D08-F06-A06,D08-F06-A07,D08-F06-A08,D08-F06-A09", + "D09-F01-A01,D09-F01-A02,D09-F01-A03,D09-F01-A04,D09-F01-A05,D09-F01-A06", + "D09-F03-A01,D09-F03-A02,D09-F03-A03,D09-F03-A04,D09-F03-A05", + "D09-F05-A01,D09-F05-A02,D09-F05-A03,D09-F05-A04,D09-F05-A05,D09-F05-A06", + "D11-F01-A01,D11-F01-A02,D11-F01-A03,D11-F01-A04", + "D11-F02-A01,D11-F02-A02,D11-F02-A03,D11-F02-A04,D11-F02-A05,D11-F02-A06", + "D11-F03-A01,D11-F03-A02,D11-F03-A03,D11-F03-A04,D11-F03-A05,D11-F03-A06", + "D11-F04-A01,D11-F04-A02,D11-F04-A03,D11-F04-A04,D11-F04-A05", + "D11-F05-A01,D11-F05-A02,D11-F05-A03,D11-F05-A04,D11-F05-A05,D11-F05-A06,D11-F05-A07,D11-F05-A08", + "D12-F01-A01,D12-F01-A02,D12-F01-A03,D12-F01-A04", + "D12-F02-A01,D12-F02-A02,D12-F02-A03,D12-F02-A04,D12-F02-A05", + "D12-F03-A01,D12-F03-A02,D12-F03-A03,D12-F03-A04,D12-F03-A05,D12-F03-A06", + "D12-F04-A01,D12-F04-A02,D12-F04-A03,D12-F04-A04,D12-F04-A05,D12-F04-A06", + "D13-F01-A01,D13-F01-A02,D13-F01-A03,D13-F01-A04", + "D13-F02-A01,D13-F02-A02,D13-F02-A03,D13-F02-A04,D13-F02-A05", + "D25-F01-A01,D25-F01-A02,D25-F01-A03,D25-F01-A04,D25-F01-A05", + "D25-F02-A01,D25-F02-A02,D25-F02-A03,D25-F02-A04,D25-F02-A05", +]); + const ENTRY_OVERRIDES = { // asOfSnapshot builds the point-in-time view; leakageAudit reports on it. "D01-F04-A05": "asOfSnapshot", @@ -688,6 +720,14 @@ if (unresolved.length > 0) { process.exit(1); } +const snakeCasePublicEntries = topics.filter((topic) => topic.entry.includes("_")); +if (snakeCasePublicEntries.length > 0) { + console.error(`\n FAILED: ${snakeCasePublicEntries.length} snake_case TypeScript public entry point(s).\n`); + for (const topic of snakeCasePublicEntries) console.error(` ${topic.id}: ${topic.entry}()`); + console.error("\n Public TypeScript entries must use camelCase; keep snake_case for Python and data fields only.\n"); + process.exit(1); +} + // Two topics resolving to the same entry is only a bug when they also come from // the SAME implementation file. Different files that each export `calculate` are // the catalog's normal convention and collide only in name, never in behaviour. @@ -714,6 +754,36 @@ if (collided.length > 0) { process.exit(1); } +// A shared body can also be wrong when each topic resolves to a distinct entry +// but `export *` exposes all peer entries through every subpath. Preserve only +// the exact legacy groups reviewed above; reject a new or expanded broad facade. +const broadSurfaceGroups = new Map(); +for (const topic of topics) { + broadSurfaceGroups.set(topic.sourceKey, [...(broadSurfaceGroups.get(topic.sourceKey) ?? []), topic]); +} +const unreviewedBroadSurfaces = []; +for (const group of broadSurfaceGroups.values()) { + if (group.length < 2) continue; + const entries = [...new Set(group.map((topic) => topic.entry).filter(Boolean))]; + if (entries.length < 2) continue; + const exposesEveryPeer = group.every((topic) => entries.every((entry) => topic.exports.includes(entry))); + if (!exposesEveryPeer) continue; + const ids = group.map((topic) => topic.id).sort(); + if (!REVIEWED_SHARED_SURFACES.has(ids.join(","))) unreviewedBroadSurfaces.push({ ids, entries }); +} +if (unreviewedBroadSurfaces.length > 0) { + console.error(`\n FAILED: ${unreviewedBroadSurfaces.length} unreviewed shared public surface(s).\n`); + for (const group of unreviewedBroadSurfaces) { + console.error(` ${group.ids.join(", ")}`); + console.error(` peer entries exposed by every subpath: ${group.entries.join(", ")}`); + } + console.error( + `\n Split each topic facade, or add the exact topic set to REVIEWED_SHARED_SURFACES\n` + + ` after confirming the cross-topic exports are an intentional compatibility contract.\n`, + ); + process.exit(1); +} + // `sourceKey` is a build-time diagnostic, not public metadata. for (const topic of topics) delete topic.sourceKey; diff --git a/src/_registry.ts b/src/_registry.ts index f3cf035..2bdd979 100644 --- a/src/_registry.ts +++ b/src/_registry.ts @@ -35,13 +35,13 @@ export interface TopicMeta { } export const topics: readonly TopicMeta[] = [ - { id: "D01-F01-A01", title: "Time Bars", slug: "time-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 1, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/time-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/time-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Time-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A02", title: "Tick Bars", slug: "tick-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 1, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A03", title: "Volume Bars", slug: "volume-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 2, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/volume-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/volume-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Volume-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A04", title: "Dollar Bars", slug: "dollar-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 2, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/dollar-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/dollar-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Dollar-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A05", title: "Tick-Imbalance Bars", slug: "tick-imbalance-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-imbalance-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-imbalance-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Imbalance-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A06", title: "Volume-Imbalance Bars", slug: "volume-imbalance-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/volume-imbalance-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/volume-imbalance-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Volume-Imbalance-Bars-Bar-Construction-algorithm", hasFixture: false }, - { id: "D01-F01-A07", title: "Tick-Run Bars", slug: "tick-run-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-run-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-run-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Run-Bars-Bar-Construction-algorithm", hasFixture: false }, + { id: "D01-F01-A01", title: "Time Bars", slug: "time-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 1, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/time-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/time-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Time-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A02", title: "Tick Bars", slug: "tick-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 1, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A03", title: "Volume Bars", slug: "volume-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 2, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/volume-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/volume-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Volume-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A04", title: "Dollar Bars", slug: "dollar-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 2, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/dollar-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/dollar-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Dollar-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A05", title: "Tick-Imbalance Bars", slug: "tick-imbalance-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-imbalance-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-imbalance-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Imbalance-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A06", title: "Volume-Imbalance Bars", slug: "volume-imbalance-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/volume-imbalance-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/volume-imbalance-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Volume-Imbalance-Bars-Bar-Construction-algorithm", hasFixture: true }, + { id: "D01-F01-A07", title: "Tick-Run Bars", slug: "tick-run-bars", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F01", family: "Bar Construction", difficulty: 4, archetype: "tape-aggregate", entry: "constructBars", exports: ["constructBars"], path: "market-data-engineering/bar-construction/tick-run-bars", articleUrl: "https://thefintechbuilder.com/market-data-engineering/bar-construction/tick-run-bars/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Tick-Run-Bars-Bar-Construction-algorithm", hasFixture: true }, { id: "D01-F02-A01", title: "OHLC Consistency Validator", slug: "ohlc-consistency-validator", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F02", family: "Cleaning and Validation", difficulty: 2, archetype: "row-classify", entry: "validateBars", exports: ["validateBars"], path: "market-data-engineering/cleaning-and-validation/ohlc-consistency-validator", articleUrl: "https://thefintechbuilder.com/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/", repoUrl: "https://github.com/IslamBaraka90/Fintech-OHLC-Consistency-Validator-Data-Quality-algorithm", hasFixture: false }, { id: "D01-F02-A02", title: "Hampel Bad-Tick Filter", slug: "hampel-bad-tick-filter", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F02", family: "Cleaning and Validation", difficulty: 3, archetype: "record-transform", entry: "hampelFilter", exports: ["hampelFilter"], path: "market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter", articleUrl: "https://thefintechbuilder.com/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Hampel-Bad-Tick-Filter-Data-Quality-algorithm", hasFixture: false }, { id: "D01-F02-A03", title: "Median Absolute Deviation Outlier Filter", slug: "median-absolute-deviation-outlier-filter", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F02", family: "Cleaning and Validation", difficulty: 3, archetype: "record-transform", entry: "madOutliers", exports: ["madOutliers"], path: "market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter", articleUrl: "https://thefintechbuilder.com/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/", repoUrl: "https://github.com/IslamBaraka90/Fintech-MAD-Median-Absolute-Deviation-Outlier-Filter-algorithm", hasFixture: false }, @@ -67,24 +67,24 @@ export const topics: readonly TopicMeta[] = [ { id: "D01-F05-A06", title: "Snapshot/Incremental-Feed Reconciliation", slug: "snapshot-incremental-feed-reconciliation", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F05", family: "Order-Book Feed Engineering", difficulty: 3, archetype: "record-transform", entry: "reconcileSnapshotIncrementals", exports: ["normalizeEvents","reconstructL2","aggregatePriceLevels","reconstructL3","recoverSequenceStream","reconcileSnapshotIncrementals","consolidateVenues","calculate"], path: "market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation", articleUrl: "https://thefintechbuilder.com/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/", repoUrl: null, hasFixture: false }, { id: "D01-F05-A07", title: "Multi-Venue Best-Quote and Book Consolidation", slug: "multi-venue-best-quote-and-book-consolidation", domainId: "D01", domain: "Market Data Engineering", familyId: "D01-F05", family: "Order-Book Feed Engineering", difficulty: 3, archetype: "record-transform", entry: "consolidateVenues", exports: ["normalizeEvents","reconstructL2","aggregatePriceLevels","reconstructL3","recoverSequenceStream","reconcileSnapshotIncrementals","consolidateVenues","calculate"], path: "market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation", articleUrl: "https://thefintechbuilder.com/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/", repoUrl: null, hasFixture: false }, { id: "D02-F01-A01", title: "Backward Split Adjustment", slug: "backward-split-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/", repoUrl: null, hasFixture: true }, - { id: "D02-F01-A02", title: "Forward Split Adjustment: carry later observations onto an earlier share basis", slug: "forward-split-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F01-A03", title: "Cash-Dividend Total-Return Adjustment: From Price Drop to Exact Return", slug: "cash-dividend-total-return-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F01-A04", title: "CRSP Cumulative Price Adjustment: Respect the Vendor Basis, Sign, and Gaps", slug: "crsp-cumulative-price-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F01-A05", title: "CRSP Cumulative Share/Volume Adjustment", slug: "crsp-cumulative-share-volume-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F02-A01", title: "Rights-Issue TERP Adjustment", slug: "rights-issue-terp-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F02-A02", title: "Spin-Off Price Adjustment: Separate Parent Price from Distributed Value", slug: "spin-off-price-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate","roundHalfUp6"], path: "corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F02-A03", title: "Stock-Dividend Adjustment: Convert Price and Quantity Bases Without Inventing Value", slug: "stock-dividend-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate","settleEntitlement","roundOutput"], path: "corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F02-A04", title: "Special-Dividend Adjustment: Preserve Return Meaning Across the Ex-Date", slug: "special-dividend-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F02-A05", title: "Return-of-Capital Adjustment: Keep Price, Return, and Tax Views Separate", slug: "return-of-capital-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/", repoUrl: null, hasFixture: false }, - { id: "D02-F03-A01", title: "Permanent Security Identifier Mapping: Scoped, Effective-Dated Crosswalks", slug: "permanent-security-identifier-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "row-classify", entry: "resolveIdentifier", exports: ["resolveIdentifier"], path: "corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/", repoUrl: null, hasFixture: false }, - { id: "D02-F03-A02", title: "Ticker-Change Chain Resolution", slug: "ticker-change-chain-resolution", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "row-classify", entry: "resolveTickerChain", exports: ["resolveTickerChain"], path: "corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/", repoUrl: null, hasFixture: false }, - { id: "D02-F03-A03", title: "Share-Class Relationship Mapping: Same Issuer Does Not Mean Same Security", slug: "share-class-relationship-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/", repoUrl: null, hasFixture: false }, - { id: "D02-F03-A04", title: "Merger Predecessor/Successor Mapping: Preserve Identity and Entitlements Without Inventing Continuity", slug: "merger-predecessor-successor-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 4, archetype: "row-classify", entry: "resolveMerger", exports: ["resolveMerger"], path: "corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/", repoUrl: null, hasFixture: false }, - { id: "D02-F03-A05", title: "Delisting Return Reconstruction: Separate Observed Proceeds from Estimates", slug: "delisting-return-reconstruction", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/", repoUrl: null, hasFixture: false }, - { id: "D02-F04-A01", title: "Historical Constituent Reconstruction: Rebuild the Roster Without Looking Ahead", slug: "historical-constituent-reconstruction", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/", repoUrl: null, hasFixture: false }, - { id: "D02-F04-A02", title: "Survivorship-Bias Guard: Keep Historical Failures in the Test", slug: "survivorship-bias-guard", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "row-classify", entry: "guardSurvivorship", exports: ["guardSurvivorship","compareEqualWeightedReturns"], path: "corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/", repoUrl: null, hasFixture: false }, - { id: "D02-F04-A03", title: "IPO Availability Timestamping: Separate Listing Events from Research Knowledge", slug: "ipo-availability-timestamping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/", repoUrl: null, hasFixture: false }, - { id: "D02-F04-A04", title: "Filing-Revision Versioning", slug: "filing-revision-versioning", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/", repoUrl: null, hasFixture: false }, + { id: "D02-F01-A02", title: "Forward Split Adjustment: carry later observations onto an earlier share basis", slug: "forward-split-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F01-A03", title: "Cash-Dividend Total-Return Adjustment: From Price Drop to Exact Return", slug: "cash-dividend-total-return-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F01-A04", title: "CRSP Cumulative Price Adjustment: Respect the Vendor Basis, Sign, and Gaps", slug: "crsp-cumulative-price-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F01-A05", title: "CRSP Cumulative Share/Volume Adjustment", slug: "crsp-cumulative-share-volume-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F01", family: "Adjustment Factors", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F02-A01", title: "Rights-Issue TERP Adjustment", slug: "rights-issue-terp-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F02-A02", title: "Spin-Off Price Adjustment: Separate Parent Price from Distributed Value", slug: "spin-off-price-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate","roundHalfUp6"], path: "corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F02-A03", title: "Stock-Dividend Adjustment: Convert Price and Quantity Bases Without Inventing Value", slug: "stock-dividend-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate","settleEntitlement","roundOutput"], path: "corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F02-A04", title: "Special-Dividend Adjustment: Preserve Return Meaning Across the Ex-Date", slug: "special-dividend-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F02-A05", title: "Return-of-Capital Adjustment: Keep Price, Return, and Tax Views Separate", slug: "return-of-capital-adjustment", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F02", family: "Complex Distributions", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/", repoUrl: null, hasFixture: true }, + { id: "D02-F03-A01", title: "Permanent Security Identifier Mapping: Scoped, Effective-Dated Crosswalks", slug: "permanent-security-identifier-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "row-classify", entry: "resolveIdentifier", exports: ["resolveIdentifier"], path: "corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/", repoUrl: null, hasFixture: true }, + { id: "D02-F03-A02", title: "Ticker-Change Chain Resolution", slug: "ticker-change-chain-resolution", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "row-classify", entry: "resolveTickerChain", exports: ["resolveTickerChain"], path: "corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/", repoUrl: null, hasFixture: true }, + { id: "D02-F03-A03", title: "Share-Class Relationship Mapping: Same Issuer Does Not Mean Same Security", slug: "share-class-relationship-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/", repoUrl: null, hasFixture: true }, + { id: "D02-F03-A04", title: "Merger Predecessor/Successor Mapping: Preserve Identity and Entitlements Without Inventing Continuity", slug: "merger-predecessor-successor-mapping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 4, archetype: "row-classify", entry: "resolveMerger", exports: ["resolveMerger"], path: "corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/", repoUrl: null, hasFixture: true }, + { id: "D02-F03-A05", title: "Delisting Return Reconstruction: Separate Observed Proceeds from Estimates", slug: "delisting-return-reconstruction", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F03", family: "Identity Continuity", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/", repoUrl: null, hasFixture: true }, + { id: "D02-F04-A01", title: "Historical Constituent Reconstruction: Rebuild the Roster Without Looking Ahead", slug: "historical-constituent-reconstruction", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/", repoUrl: null, hasFixture: true }, + { id: "D02-F04-A02", title: "Survivorship-Bias Guard: Keep Historical Failures in the Test", slug: "survivorship-bias-guard", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "row-classify", entry: "guardSurvivorship", exports: ["guardSurvivorship","compareEqualWeightedReturns"], path: "corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/", repoUrl: null, hasFixture: true }, + { id: "D02-F04-A03", title: "IPO Availability Timestamping: Separate Listing Events from Research Knowledge", slug: "ipo-availability-timestamping", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/", repoUrl: null, hasFixture: true }, + { id: "D02-F04-A04", title: "Filing-Revision Versioning", slug: "filing-revision-versioning", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/", repoUrl: null, hasFixture: true }, { id: "D02-F04-A05", title: "Corporate-Action Status and Effective-Date Reconciliation", slug: "corporate-action-status-and-effective-date-reconciliation", domainId: "D02", domain: "Corporate Actions and Security Master Data", familyId: "D02-F04", family: "Point-in-Time Universe", difficulty: 4, archetype: "record-transform", entry: "reconcileCorporateAction", exports: ["reconcileCorporateAction"], path: "corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation", articleUrl: "https://thefintechbuilder.com/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/", repoUrl: null, hasFixture: false }, { id: "D03-F01-A01", title: "Base-Date/Base-Value Initialization", slug: "base-date-base-value-initialization", domainId: "D03", domain: "Index and Benchmark Engineering", familyId: "D03-F01", family: "Index Initialization and Continuity", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization", articleUrl: "https://thefintechbuilder.com/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/", repoUrl: null, hasFixture: true }, { id: "D03-F01-A02", title: "Index Divisor Initialization", slug: "index-divisor-initialization", domainId: "D03", domain: "Index and Benchmark Engineering", familyId: "D03-F01", family: "Index Initialization and Continuity", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization", articleUrl: "https://thefintechbuilder.com/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/", repoUrl: null, hasFixture: true }, @@ -126,23 +126,23 @@ export const topics: readonly TopicMeta[] = [ { id: "D03-F06-A06", title: "Rebalancing Algorithm", slug: "rebalancing-algorithm", domainId: "D03", domain: "Index and Benchmark Engineering", familyId: "D03-F06", family: "Governance and Maintenance", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm", articleUrl: "https://thefintechbuilder.com/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/", repoUrl: null, hasFixture: true }, { id: "D03-F06-A07", title: "Turnover Buffer Rule", slug: "turnover-buffer-rule", domainId: "D03", domain: "Index and Benchmark Engineering", familyId: "D03-F06", family: "Governance and Maintenance", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule", articleUrl: "https://thefintechbuilder.com/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/", repoUrl: null, hasFixture: true }, { id: "D03-F06-A08", title: "Index Replication-Cost Estimator", slug: "index-replication-cost-estimator", domainId: "D03", domain: "Index and Benchmark Engineering", familyId: "D03-F06", family: "Governance and Maintenance", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator", articleUrl: "https://thefintechbuilder.com/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/", repoUrl: null, hasFixture: true }, - { id: "D04-F01-A01", title: "Net Advances: Count Participation Without Hiding Data Gaps", slug: "net-advances", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 1, archetype: "record-transform", entry: "calculateNetAdvances", exports: ["calculateNetAdvances"], path: "market-breadth-and-internals/advance-decline-breadth/net-advances", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/net-advances/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Net-Advances-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F01-A02", title: "Advance/Decline Ratio: Advancing Issues per Declining Issue", slug: "advance-decline-ratio", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 1, archetype: "record-transform", entry: "calculateAdvanceDeclineRatio", exports: ["calculateAdvanceDeclineRatio","evaluateAdvanceDeclineRatioAsOf"], path: "market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Advance-Decline-Ratio-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F01-A03", title: "Cumulative Advance/Decline Line: Recompute History Without Looking Ahead", slug: "cumulative-advance-decline-line", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "record-transform", entry: "calculateCumulativeAdvanceDeclineLine", exports: ["calculateCumulativeAdvanceDeclineLine"], path: "market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Cumulative-Advance-Decline-Line-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F01-A04", title: "Normalized Advance/Decline Line: Cumulative (A-D)/(A+D) Breadth", slug: "normalized-advance-decline-line", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "record-transform", entry: "calculateNormalizedAdLine", exports: ["calculateNormalizedAdLine"], path: "market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Normalized-Advance-Decline-Line-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F01-A05", title: "Absolute Breadth Index", slug: "absolute-breadth-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateAbsoluteBreadthIndex", exports: ["evaluateAbsoluteBreadthIndex"], path: "market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Absolute-Breadth-Index-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F02-A01", title: "Traditional McClellan Oscillator: Compare Fast and Slow Raw Breadth", slug: "traditional-mcclellan-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculateMcClellanValues", exports: ["calculateMcClellanValues","calculateMcClellan"], path: "market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/", repoUrl: "https://github.com/IslamBaraka90/Fintech-McClellan-Oscillator-Market-Breadth-algorithm", hasFixture: false }, - { id: "D04-F02-A02", title: "Ratio-Adjusted McClellan Oscillator", slug: "ratio-adjusted-mcclellan-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/", repoUrl: null, hasFixture: false }, - { id: "D04-F02-A03", title: "Traditional McClellan Summation Index", slug: "traditional-mcclellan-summation-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/", repoUrl: null, hasFixture: false }, - { id: "D04-F02-A04", title: "Ratio-Adjusted Summation Index (RASI)", slug: "ratio-adjusted-summation-index-rasi", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/", repoUrl: null, hasFixture: false }, - { id: "D04-F02-A05", title: "McClellan Volume Oscillator", slug: "mcclellan-volume-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/", repoUrl: null, hasFixture: false }, - { id: "D04-F02-A06", title: "McClellan Volume Summation Index", slug: "mcclellan-volume-summation-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A01", title: "New Highs–New Lows", slug: "new-highs-new-lows", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A02", title: "High-Low Ratio", slug: "high-low-ratio", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A03", title: "High-Low Index", slug: "high-low-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/high-low-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A04", title: "Percent Above 20-Day MA", slug: "percent-above-20-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A05", title: "Percent Above 50-Day MA", slug: "percent-above-50-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/", repoUrl: null, hasFixture: false }, - { id: "D04-F03-A06", title: "Percent Above 200-Day MA", slug: "percent-above-200-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 3, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/", repoUrl: null, hasFixture: false }, + { id: "D04-F01-A01", title: "Net Advances: Count Participation Without Hiding Data Gaps", slug: "net-advances", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 1, archetype: "record-transform", entry: "calculateNetAdvances", exports: ["calculateNetAdvances"], path: "market-breadth-and-internals/advance-decline-breadth/net-advances", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/net-advances/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Net-Advances-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F01-A02", title: "Advance/Decline Ratio: Advancing Issues per Declining Issue", slug: "advance-decline-ratio", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 1, archetype: "record-transform", entry: "calculateAdvanceDeclineRatio", exports: ["calculateAdvanceDeclineRatio","evaluateAdvanceDeclineRatioAsOf"], path: "market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Advance-Decline-Ratio-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F01-A03", title: "Cumulative Advance/Decline Line: Recompute History Without Looking Ahead", slug: "cumulative-advance-decline-line", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "record-transform", entry: "calculateCumulativeAdvanceDeclineLine", exports: ["calculateCumulativeAdvanceDeclineLine"], path: "market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Cumulative-Advance-Decline-Line-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F01-A04", title: "Normalized Advance/Decline Line: Cumulative (A-D)/(A+D) Breadth", slug: "normalized-advance-decline-line", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "record-transform", entry: "calculateNormalizedAdLine", exports: ["calculateNormalizedAdLine"], path: "market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Normalized-Advance-Decline-Line-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F01-A05", title: "Absolute Breadth Index", slug: "absolute-breadth-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F01", family: "Advance/Decline Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateAbsoluteBreadthIndex", exports: ["evaluateAbsoluteBreadthIndex"], path: "market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Absolute-Breadth-Index-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F02-A01", title: "Traditional McClellan Oscillator: Compare Fast and Slow Raw Breadth", slug: "traditional-mcclellan-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculateMcClellanValues", exports: ["calculateMcClellanValues","calculateMcClellan"], path: "market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/", repoUrl: "https://github.com/IslamBaraka90/Fintech-McClellan-Oscillator-Market-Breadth-algorithm", hasFixture: true }, + { id: "D04-F02-A02", title: "Ratio-Adjusted McClellan Oscillator", slug: "ratio-adjusted-mcclellan-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/", repoUrl: null, hasFixture: true }, + { id: "D04-F02-A03", title: "Traditional McClellan Summation Index", slug: "traditional-mcclellan-summation-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/", repoUrl: null, hasFixture: true }, + { id: "D04-F02-A04", title: "Ratio-Adjusted Summation Index (RASI)", slug: "ratio-adjusted-summation-index-rasi", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/", repoUrl: null, hasFixture: true }, + { id: "D04-F02-A05", title: "McClellan Volume Oscillator", slug: "mcclellan-volume-oscillator", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/", repoUrl: null, hasFixture: true }, + { id: "D04-F02-A06", title: "McClellan Volume Summation Index", slug: "mcclellan-volume-summation-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F02", family: "McClellan Family", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["transformRecord","calculateValues","calculate"], path: "market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A01", title: "New Highs–New Lows", slug: "new-highs-new-lows", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A02", title: "High-Low Ratio", slug: "high-low-ratio", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A03", title: "High-Low Index", slug: "high-low-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/high-low-and-trend-breadth/high-low-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A04", title: "Percent Above 20-Day MA", slug: "percent-above-20-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A05", title: "Percent Above 50-Day MA", slug: "percent-above-50-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 2, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/", repoUrl: null, hasFixture: true }, + { id: "D04-F03-A06", title: "Percent Above 200-Day MA", slug: "percent-above-200-day-ma", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F03", family: "High/Low and Trend Breadth", difficulty: 3, archetype: "snapshot-evaluate", entry: "evaluateSnapshot", exports: ["evaluateSnapshot"], path: "market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/", repoUrl: null, hasFixture: true }, { id: "D04-F04-A01", title: "Zweig Breadth Thrust", slug: "zweig-breadth-thrust", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F04", family: "Thrust and Pressure", difficulty: 4, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/", repoUrl: null, hasFixture: true }, { id: "D04-F04-A02", title: "Arms Index (TRIN)", slug: "arms-index-trin", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F04", family: "Thrust and Pressure", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/thrust-and-pressure/arms-index-trin", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/", repoUrl: null, hasFixture: true }, { id: "D04-F04-A03", title: "Advance/Decline Volume Line", slug: "advance-decline-volume-line", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F04", family: "Thrust and Pressure", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/", repoUrl: null, hasFixture: true }, @@ -154,8 +154,8 @@ export const topics: readonly TopicMeta[] = [ { id: "D04-F05-A03", title: "Effective Number of Constituents", slug: "effective-number-of-constituents", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F05", family: "Concentration and Diffusion", difficulty: 2, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/", repoUrl: null, hasFixture: true }, { id: "D04-F05-A04", title: "Sector Diffusion Index", slug: "sector-diffusion-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F05", family: "Concentration and Diffusion", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/", repoUrl: null, hasFixture: true }, { id: "D04-F05-A05", title: "Factor Diffusion Index", slug: "factor-diffusion-index", domainId: "D04", domain: "Market Breadth and Internals", familyId: "D04-F05", family: "Concentration and Diffusion", difficulty: 3, archetype: "record-transform", entry: "calculate", exports: ["calculate"], path: "market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index", articleUrl: "https://thefintechbuilder.com/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/", repoUrl: null, hasFixture: true }, - { id: "D06-F01-A01", title: "Candle Anatomy", slug: "candle-anatomy", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 1, archetype: "record-transform", entry: "analyzeCandle", exports: ["analyzeCandle","analyzeCandles"], path: "price-action-and-candlesticks/candle-foundations/candle-anatomy", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/candle-anatomy/", repoUrl: null, hasFixture: false }, - { id: "D06-F01-A02", title: "Scale-Aware Body Classification", slug: "scale-aware-body-classification", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 2, archetype: "row-classify", entry: "classifyBody", exports: ["classifyBody","classifyBodySeries"], path: "price-action-and-candlesticks/candle-foundations/scale-aware-body-classification", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/", repoUrl: null, hasFixture: false }, + { id: "D06-F01-A01", title: "Candle Anatomy", slug: "candle-anatomy", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 1, archetype: "record-transform", entry: "analyzeCandle", exports: ["analyzeCandle","analyzeCandles"], path: "price-action-and-candlesticks/candle-foundations/candle-anatomy", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/candle-anatomy/", repoUrl: null, hasFixture: true }, + { id: "D06-F01-A02", title: "Scale-Aware Body Classification", slug: "scale-aware-body-classification", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 2, archetype: "row-classify", entry: "classifyBody", exports: ["classifyBody","classifyBodySeries"], path: "price-action-and-candlesticks/candle-foundations/scale-aware-body-classification", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/", repoUrl: null, hasFixture: true }, { id: "D06-F01-A03", title: "Shadow-to-Body Ratio", slug: "shadow-to-body-ratio", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 2, archetype: "record-transform", entry: "shadowToBodyRatio", exports: ["calculate","shadowToBodyRatio","gapClassification","trendContextFilter","doji","dragonflyDoji","gravestoneDoji","marubozu","spinningTop","hammer","hangingMan","invertedHammer","shootingStar","bullishEngulfing","bearishEngulfing","bullishHarami","bearishHarami","piercingLine","darkCloudCover","tweezerTop","tweezerBottom"], path: "price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/", repoUrl: null, hasFixture: false }, { id: "D06-F01-A04", title: "Gap Classification", slug: "gap-classification", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 2, archetype: "record-transform", entry: "gapClassification", exports: ["calculate","shadowToBodyRatio","gapClassification","trendContextFilter","doji","dragonflyDoji","gravestoneDoji","marubozu","spinningTop","hammer","hangingMan","invertedHammer","shootingStar","bullishEngulfing","bearishEngulfing","bullishHarami","bearishHarami","piercingLine","darkCloudCover","tweezerTop","tweezerBottom"], path: "price-action-and-candlesticks/candle-foundations/gap-classification", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/gap-classification/", repoUrl: null, hasFixture: false }, { id: "D06-F01-A05", title: "Trend-Context Filter", slug: "trend-context-filter", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F01", family: "Candle Foundations", difficulty: 3, archetype: "record-transform", entry: "trendContextFilter", exports: ["calculate","shadowToBodyRatio","gapClassification","trendContextFilter","doji","dragonflyDoji","gravestoneDoji","marubozu","spinningTop","hammer","hangingMan","invertedHammer","shootingStar","bullishEngulfing","bearishEngulfing","bullishHarami","bearishHarami","piercingLine","darkCloudCover","tweezerTop","tweezerBottom"], path: "price-action-and-candlesticks/candle-foundations/trend-context-filter", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candle-foundations/trend-context-filter/", repoUrl: null, hasFixture: false }, @@ -192,53 +192,53 @@ export const topics: readonly TopicMeta[] = [ { id: "D06-F05-A07", title: "Overlapping-Pattern Conflict Resolver", slug: "overlapping-pattern-conflict-resolver", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F05", family: "Candlestick Scanning and Context", difficulty: 3, archetype: "row-classify", entry: "resolveConflicts", exports: ["resolveConflicts"], path: "price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/", repoUrl: null, hasFixture: true }, { id: "D06-F05-A08", title: "Candlestick Confirmation and Invalidation State Machine", slug: "candlestick-confirmation-and-invalidation-state-machine", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F05", family: "Candlestick Scanning and Context", difficulty: 4, archetype: "record-transform", entry: "runConfirmationStateMachine", exports: ["runConfirmationStateMachine"], path: "price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/", repoUrl: null, hasFixture: true }, { id: "D06-F05-A09", title: "Candlestick Scanner Ranking and Deduplication", slug: "candlestick-scanner-ranking-and-deduplication", domainId: "D06", domain: "Price Action and Candlesticks", familyId: "D06-F05", family: "Candlestick Scanning and Context", difficulty: 4, archetype: "record-transform", entry: "rankAndDeduplicate", exports: ["rankAndDeduplicate"], path: "price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication", articleUrl: "https://thefintechbuilder.com/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/", repoUrl: null, hasFixture: true }, - { id: "D07-F01-A01", title: "Simple Moving Average (SMA): Define the Window Before the Mean", slug: "sma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 1, archetype: "series-transform", entry: "calculateSma", exports: ["calculateSma","calculateSmaSeries"], path: "technical-indicators/trend-smoothing/sma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/sma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-SMA-Simple-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A02", title: "Exponential Moving Average (EMA)", slug: "ema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateEma", exports: ["alphaFromSpan","calculateEma","calculateAdjustedEma","calculateTimeAwareEma"], path: "technical-indicators/trend-smoothing/ema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/ema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-EMA-Exponential-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A03", title: "Weighted Moving Average (WMA): Newest-Heavy Linear Smoothing", slug: "wma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 1, archetype: "series-transform", entry: "calculateWma", exports: ["calculateWma"], path: "technical-indicators/trend-smoothing/wma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/wma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-WMA-Weighted-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A04", title: "Wilder RMA: SMA-Seeded Alpha 1/n Smoothing", slug: "wilder-rma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateRma", exports: ["calculateRma"], path: "technical-indicators/trend-smoothing/wilder-rma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/wilder-rma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Wilder-RMA-Smoothing-algorithm", hasFixture: false }, - { id: "D07-F01-A05", title: "Double Exponential Moving Average (DEMA): Reduced Lag and Overshoot", slug: "dema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateDemaComponents", exports: ["calculateDemaComponents","calculateDema","demaSteadyStateWeights"], path: "technical-indicators/trend-smoothing/dema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/dema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-DEMA-Double-Exponential-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A06", title: "Triple Exponential Moving Average (TEMA): Layered Warm-Up and Signed Weights", slug: "tema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateTemaComponents", exports: ["calculateTemaComponents","calculateTema","temaSteadyStateWeight"], path: "technical-indicators/trend-smoothing/tema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/tema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-TEMA-Triple-Exponential-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A07", title: "Hull MA", slug: "hull-ma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateHullMa", exports: ["calculateHullMa"], path: "technical-indicators/trend-smoothing/hull-ma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/hull-ma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-HMA-Hull-Moving-Average-algorithm", hasFixture: false }, - { id: "D07-F01-A08", title: "Kaufman Adaptive Moving Average (KAMA)", slug: "kama", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 4, archetype: "series-transform", entry: "calculateKama", exports: ["calculateKama"], path: "technical-indicators/trend-smoothing/kama", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/kama/", repoUrl: null, hasFixture: false }, - { id: "D07-F01-A09", title: "MESA Adaptive Moving Average (MAMA)", slug: "mama", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 5, archetype: "series-transform", entry: "mama", exports: ["mama"], path: "technical-indicators/trend-smoothing/mama", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/mama/", repoUrl: null, hasFixture: false }, - { id: "D07-F02-A01", title: "MACD: Read the Spreads Before You Read the Signals", slug: "macd", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 2, archetype: "series-transform", entry: "macd", exports: ["macd"], path: "technical-indicators/trend-systems/macd", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/macd/", repoUrl: "https://github.com/IslamBaraka90/Fintech-MACD-Moving-Average-Convergence-Divergence-algorithm", hasFixture: false }, + { id: "D07-F01-A01", title: "Simple Moving Average (SMA): Define the Window Before the Mean", slug: "sma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 1, archetype: "series-transform", entry: "calculateSma", exports: ["calculateSma","calculateSmaSeries"], path: "technical-indicators/trend-smoothing/sma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/sma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-SMA-Simple-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A02", title: "Exponential Moving Average (EMA)", slug: "ema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateEma", exports: ["alphaFromSpan","calculateEma","calculateAdjustedEma","calculateTimeAwareEma"], path: "technical-indicators/trend-smoothing/ema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/ema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-EMA-Exponential-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A03", title: "Weighted Moving Average (WMA): Newest-Heavy Linear Smoothing", slug: "wma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 1, archetype: "series-transform", entry: "calculateWma", exports: ["calculateWma"], path: "technical-indicators/trend-smoothing/wma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/wma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-WMA-Weighted-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A04", title: "Wilder RMA: SMA-Seeded Alpha 1/n Smoothing", slug: "wilder-rma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateRma", exports: ["calculateRma"], path: "technical-indicators/trend-smoothing/wilder-rma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/wilder-rma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-Wilder-RMA-Smoothing-algorithm", hasFixture: true }, + { id: "D07-F01-A05", title: "Double Exponential Moving Average (DEMA): Reduced Lag and Overshoot", slug: "dema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateDemaComponents", exports: ["calculateDemaComponents","calculateDema","demaSteadyStateWeights"], path: "technical-indicators/trend-smoothing/dema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/dema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-DEMA-Double-Exponential-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A06", title: "Triple Exponential Moving Average (TEMA): Layered Warm-Up and Signed Weights", slug: "tema", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateTemaComponents", exports: ["calculateTemaComponents","calculateTema","temaSteadyStateWeight"], path: "technical-indicators/trend-smoothing/tema", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/tema/", repoUrl: "https://github.com/IslamBaraka90/Fintech-TEMA-Triple-Exponential-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A07", title: "Hull MA", slug: "hull-ma", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 2, archetype: "series-transform", entry: "calculateHullMa", exports: ["calculateHullMa"], path: "technical-indicators/trend-smoothing/hull-ma", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/hull-ma/", repoUrl: "https://github.com/IslamBaraka90/Fintech-HMA-Hull-Moving-Average-algorithm", hasFixture: true }, + { id: "D07-F01-A08", title: "Kaufman Adaptive Moving Average (KAMA)", slug: "kama", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 4, archetype: "series-transform", entry: "calculateKama", exports: ["calculateKama"], path: "technical-indicators/trend-smoothing/kama", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/kama/", repoUrl: null, hasFixture: true }, + { id: "D07-F01-A09", title: "MESA Adaptive Moving Average (MAMA)", slug: "mama", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F01", family: "Trend Smoothing", difficulty: 5, archetype: "series-transform", entry: "mama", exports: ["mama"], path: "technical-indicators/trend-smoothing/mama", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-smoothing/mama/", repoUrl: null, hasFixture: true }, + { id: "D07-F02-A01", title: "MACD: Read the Spreads Before You Read the Signals", slug: "macd", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 2, archetype: "series-transform", entry: "macd", exports: ["macd"], path: "technical-indicators/trend-systems/macd", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/macd/", repoUrl: "https://github.com/IslamBaraka90/Fintech-MACD-Moving-Average-Convergence-Divergence-algorithm", hasFixture: true }, { id: "D07-F02-A02", title: "Percentage Price Oscillator (PPO): Normalize the MACD Spread", slug: "percentage-price-oscillator", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 2, archetype: "series-transform", entry: "ppo", exports: ["ppo"], path: "technical-indicators/trend-systems/percentage-price-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/percentage-price-oscillator/", repoUrl: null, hasFixture: true }, { id: "D07-F02-A03", title: "Aroon Up, Down, and Oscillator: Measure Extreme Recency", slug: "aroon", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 2, archetype: "series-transform", entry: "aroon", exports: ["aroon"], path: "technical-indicators/trend-systems/aroon", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/aroon/", repoUrl: null, hasFixture: true }, - { id: "D07-F02-A04", title: "Directional Movement: From True Range to +DI, −DI, and DX", slug: "directional-movement", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "directional_movement", exports: ["directional_movement"], path: "technical-indicators/trend-systems/directional-movement", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/directional-movement/", repoUrl: null, hasFixture: true }, + { id: "D07-F02-A04", title: "Directional Movement: From True Range to +DI, −DI, and DX", slug: "directional-movement", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "directionalMovement", exports: ["directionalMovement"], path: "technical-indicators/trend-systems/directional-movement", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/directional-movement/", repoUrl: null, hasFixture: true }, { id: "D07-F02-A05", title: "Average Directional Index (ADX): Smooth DX Without Inventing Direction", slug: "adx", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "adx", exports: ["adx"], path: "technical-indicators/trend-systems/adx", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/adx/", repoUrl: null, hasFixture: true }, { id: "D07-F02-A06", title: "Ichimoku Cloud: Separate Range Midpoints from Plot-Time Displacement", slug: "ichimoku-cloud", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "ichimoku", exports: ["ichimoku"], path: "technical-indicators/trend-systems/ichimoku-cloud", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/ichimoku-cloud/", repoUrl: null, hasFixture: true }, - { id: "D07-F02-A07", title: "Parabolic SAR: Audit the Stop, Extreme Point, and Acceleration Factor", slug: "parabolic-sar", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "parabolic_sar", exports: ["parabolic_sar"], path: "technical-indicators/trend-systems/parabolic-sar", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/parabolic-sar/", repoUrl: null, hasFixture: true }, + { id: "D07-F02-A07", title: "Parabolic SAR: Audit the Stop, Extreme Point, and Acceleration Factor", slug: "parabolic-sar", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "parabolicSar", exports: ["parabolicSar"], path: "technical-indicators/trend-systems/parabolic-sar", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/parabolic-sar/", repoUrl: null, hasFixture: true }, { id: "D07-F02-A08", title: "Supertrend: Trace ATR Bands, Ratchets, and Direction Flips", slug: "supertrend", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F02", family: "Trend Systems", difficulty: 3, archetype: "series-transform", entry: "supertrend", exports: ["supertrend"], path: "technical-indicators/trend-systems/supertrend", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/supertrend/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A01", title: "Relative Strength Index (RSI)", slug: "rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "rsi", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/rsi/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A02", title: "Stochastic Oscillator", slug: "stochastic-oscillator", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "stochastic", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/stochastic-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/stochastic-oscillator/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A03", title: "Stochastic RSI", slug: "stochastic-rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "stochastic_rsi", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/stochastic-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/stochastic-rsi/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A04", title: "Williams %R", slug: "williams-r", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "williams_r", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/williams-r", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/williams-r/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A05", title: "Commodity Channel Index (CCI)", slug: "cci", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "cci", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/cci", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/cci/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A06", title: "Ultimate Oscillator", slug: "ultimate-oscillator", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "ultimate_oscillator", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/ultimate-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/ultimate-oscillator/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A07", title: "True Strength Index (TSI)", slug: "tsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "tsi", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/tsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/tsi/", repoUrl: null, hasFixture: true }, - { id: "D07-F03-A08", title: "Connors RSI", slug: "connors-rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 4, archetype: "series-transform", entry: "connors_rsi", exports: ["rsi","stochastic","stochastic_rsi","williams_r","cci","ultimate_oscillator","tsi","connors_rsi"], path: "technical-indicators/momentum/connors-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/connors-rsi/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A01", title: "True Range", slug: "true-range", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 1, archetype: "series-transform", entry: "true_range", exports: ["true_range"], path: "technical-indicators/volatility-and-channels/true-range", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/true-range/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A02", title: "Average True Range (ATR)", slug: "atr", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "average_true_range", exports: ["true_range","average_true_range"], path: "technical-indicators/volatility-and-channels/atr", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/atr/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A03", title: "Bollinger Bands", slug: "bollinger-bands", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "bollinger_bands", exports: ["bollinger_bands"], path: "technical-indicators/volatility-and-channels/bollinger-bands", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bands/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A04", title: "Keltner Channels", slug: "keltner-channels", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 3, archetype: "series-transform", entry: "keltner_channels", exports: ["true_range","average_true_range","keltner_channels"], path: "technical-indicators/volatility-and-channels/keltner-channels", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/keltner-channels/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A05", title: "Donchian Channels", slug: "donchian-channels", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "donchian_channels", exports: ["donchian_channels"], path: "technical-indicators/volatility-and-channels/donchian-channels", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/donchian-channels/", repoUrl: null, hasFixture: true }, - { id: "D07-F04-A06", title: "Bollinger BandWidth", slug: "bollinger-bandwidth", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 3, archetype: "series-transform", entry: "bollinger_bandwidth", exports: ["bollinger_bands","bollinger_bandwidth"], path: "technical-indicators/volatility-and-channels/bollinger-bandwidth", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bandwidth/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A01", title: "On-Balance Volume (OBV)", slug: "obv", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "obv", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/obv", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/obv/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A02", title: "Accumulation/Distribution Line", slug: "accumulation-distribution-line", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "accumulation_distribution_line", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/accumulation-distribution-line", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/accumulation-distribution-line/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A03", title: "Chaikin Money Flow", slug: "chaikin-money-flow", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "chaikin_money_flow", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/chaikin-money-flow", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/chaikin-money-flow/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A04", title: "Money Flow Index", slug: "money-flow-index", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "money_flow_index", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/money-flow-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/money-flow-index/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A05", title: "Volume Price Trend", slug: "volume-price-trend", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "volume_price_trend", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/volume-price-trend", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/volume-price-trend/", repoUrl: null, hasFixture: true }, - { id: "D07-F05-A06", title: "Force Index", slug: "force-index", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "force_index", exports: ["obv","accumulation_distribution_line","chaikin_money_flow","money_flow_index","volume_price_trend","force_index"], path: "technical-indicators/volume-indicators/force-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/force-index/", repoUrl: null, hasFixture: true }, - { id: "D08-F01-A01", title: "Causal Pivot Detection", slug: "causal-pivot-detection", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 2, archetype: "row-classify", entry: "detectCausalPivots", exports: ["detectCausalPivots"], path: "geometric-chart-patterns/pivots-and-levels/causal-pivot-detection", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/", repoUrl: null, hasFixture: false }, - { id: "D08-F01-A02", title: "ZigZag Segmentation", slug: "zigzag-segmentation", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 3, archetype: "record-transform", entry: "zigzagSegment", exports: ["zigzagSegment"], path: "geometric-chart-patterns/pivots-and-levels/zigzag-segmentation", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/", repoUrl: null, hasFixture: false }, - { id: "D08-F01-A03", title: "Support/Resistance Clustering", slug: "support-resistance-clustering", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 3, archetype: "record-transform", entry: "clusterPivotLevels", exports: ["detectCausalPivots","clusterPivotLevels"], path: "geometric-chart-patterns/pivots-and-levels/support-resistance-clustering", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/", repoUrl: null, hasFixture: false }, - { id: "D08-F01-A04", title: "Robust Trendline Fitting", slug: "robust-trendline-fitting", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 4, archetype: "record-transform", entry: "fitRobustTrendline", exports: ["detectCausalPivots","fitRobustTrendline"], path: "geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A01", title: "Double Top", slug: "double-top", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 2, archetype: "record-transform", entry: "double_top", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/double-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-top/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A02", title: "Double Bottom", slug: "double-bottom", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 2, archetype: "record-transform", entry: "double_bottom", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/double-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-bottom/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A03", title: "Triple Top", slug: "triple-top", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "triple_top", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/triple-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-top/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A04", title: "Triple Bottom", slug: "triple-bottom", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "triple_bottom", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/triple-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-bottom/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A05", title: "Head and Shoulders", slug: "head-and-shoulders", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "head_and_shoulders", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/head-and-shoulders/", repoUrl: null, hasFixture: false }, - { id: "D08-F02-A06", title: "Inverse Head and Shoulders", slug: "inverse-head-and-shoulders", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "inverse_head_and_shoulders", exports: ["confirmedPivots","detectReversal","traceReversal","double_top","double_bottom","triple_top","triple_bottom","head_and_shoulders","inverse_head_and_shoulders"], path: "geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/", repoUrl: null, hasFixture: false }, + { id: "D07-F03-A01", title: "Relative Strength Index (RSI)", slug: "rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "rsi", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/rsi/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A02", title: "Stochastic Oscillator", slug: "stochastic-oscillator", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "stochastic", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/stochastic-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/stochastic-oscillator/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A03", title: "Stochastic RSI", slug: "stochastic-rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "stochasticRsi", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/stochastic-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/stochastic-rsi/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A04", title: "Williams %R", slug: "williams-r", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 2, archetype: "series-transform", entry: "williamsR", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/williams-r", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/williams-r/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A05", title: "Commodity Channel Index (CCI)", slug: "cci", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "cci", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/cci", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/cci/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A06", title: "Ultimate Oscillator", slug: "ultimate-oscillator", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "ultimateOscillator", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/ultimate-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/ultimate-oscillator/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A07", title: "True Strength Index (TSI)", slug: "tsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 3, archetype: "series-transform", entry: "tsi", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/tsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/tsi/", repoUrl: null, hasFixture: true }, + { id: "D07-F03-A08", title: "Connors RSI", slug: "connors-rsi", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F03", family: "Momentum", difficulty: 4, archetype: "series-transform", entry: "connorsRsi", exports: ["rsi","stochastic","stochasticRsi","williamsR","cci","ultimateOscillator","tsi","connorsRsi"], path: "technical-indicators/momentum/connors-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/connors-rsi/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A01", title: "True Range", slug: "true-range", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 1, archetype: "series-transform", entry: "trueRange", exports: ["trueRange"], path: "technical-indicators/volatility-and-channels/true-range", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/true-range/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A02", title: "Average True Range (ATR)", slug: "atr", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "averageTrueRange", exports: ["trueRange","averageTrueRange"], path: "technical-indicators/volatility-and-channels/atr", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/atr/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A03", title: "Bollinger Bands", slug: "bollinger-bands", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "bollingerBands", exports: ["bollingerBands"], path: "technical-indicators/volatility-and-channels/bollinger-bands", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bands/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A04", title: "Keltner Channels", slug: "keltner-channels", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 3, archetype: "series-transform", entry: "keltnerChannels", exports: ["trueRange","averageTrueRange","keltnerChannels"], path: "technical-indicators/volatility-and-channels/keltner-channels", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/keltner-channels/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A05", title: "Donchian Channels", slug: "donchian-channels", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 2, archetype: "series-transform", entry: "donchianChannels", exports: ["donchianChannels"], path: "technical-indicators/volatility-and-channels/donchian-channels", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/donchian-channels/", repoUrl: null, hasFixture: true }, + { id: "D07-F04-A06", title: "Bollinger BandWidth", slug: "bollinger-bandwidth", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F04", family: "Volatility and Channels", difficulty: 3, archetype: "series-transform", entry: "bollingerBandwidth", exports: ["bollingerBands","bollingerBandwidth"], path: "technical-indicators/volatility-and-channels/bollinger-bandwidth", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bandwidth/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A01", title: "On-Balance Volume (OBV)", slug: "obv", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "obv", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/obv", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/obv/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A02", title: "Accumulation/Distribution Line", slug: "accumulation-distribution-line", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "accumulationDistributionLine", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/accumulation-distribution-line", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/accumulation-distribution-line/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A03", title: "Chaikin Money Flow", slug: "chaikin-money-flow", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "chaikinMoneyFlow", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/chaikin-money-flow", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/chaikin-money-flow/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A04", title: "Money Flow Index", slug: "money-flow-index", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "moneyFlowIndex", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/money-flow-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/money-flow-index/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A05", title: "Volume Price Trend", slug: "volume-price-trend", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 2, archetype: "series-transform", entry: "volumePriceTrend", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/volume-price-trend", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/volume-price-trend/", repoUrl: null, hasFixture: true }, + { id: "D07-F05-A06", title: "Force Index", slug: "force-index", domainId: "D07", domain: "Technical Indicators", familyId: "D07-F05", family: "Volume Indicators", difficulty: 3, archetype: "series-transform", entry: "forceIndex", exports: ["obv","accumulationDistributionLine","chaikinMoneyFlow","moneyFlowIndex","volumePriceTrend","forceIndex"], path: "technical-indicators/volume-indicators/force-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/force-index/", repoUrl: null, hasFixture: true }, + { id: "D08-F01-A01", title: "Causal Pivot Detection", slug: "causal-pivot-detection", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 2, archetype: "row-classify", entry: "detectCausalPivots", exports: ["detectCausalPivots"], path: "geometric-chart-patterns/pivots-and-levels/causal-pivot-detection", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/", repoUrl: null, hasFixture: true }, + { id: "D08-F01-A02", title: "ZigZag Segmentation", slug: "zigzag-segmentation", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 3, archetype: "record-transform", entry: "zigzagSegment", exports: ["zigzagSegment"], path: "geometric-chart-patterns/pivots-and-levels/zigzag-segmentation", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/", repoUrl: null, hasFixture: true }, + { id: "D08-F01-A03", title: "Support/Resistance Clustering", slug: "support-resistance-clustering", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 3, archetype: "record-transform", entry: "clusterPivotLevels", exports: ["detectCausalPivots","clusterPivotLevels"], path: "geometric-chart-patterns/pivots-and-levels/support-resistance-clustering", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/", repoUrl: null, hasFixture: true }, + { id: "D08-F01-A04", title: "Robust Trendline Fitting", slug: "robust-trendline-fitting", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F01", family: "Pivots and Levels", difficulty: 4, archetype: "record-transform", entry: "fitRobustTrendline", exports: ["detectCausalPivots","fitRobustTrendline"], path: "geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/", repoUrl: null, hasFixture: true }, + { id: "D08-F02-A01", title: "Double Top", slug: "double-top", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 2, archetype: "record-transform", entry: "doubleTop", exports: ["confirmedPivots","detectReversal","traceReversal","doubleTop"], path: "geometric-chart-patterns/reversal-structures/double-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-top/", repoUrl: null, hasFixture: false }, + { id: "D08-F02-A02", title: "Double Bottom", slug: "double-bottom", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 2, archetype: "record-transform", entry: "doubleBottom", exports: ["confirmedPivots","detectReversal","traceReversal","doubleBottom"], path: "geometric-chart-patterns/reversal-structures/double-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-bottom/", repoUrl: null, hasFixture: false }, + { id: "D08-F02-A03", title: "Triple Top", slug: "triple-top", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "tripleTop", exports: ["confirmedPivots","detectReversal","traceReversal","tripleTop"], path: "geometric-chart-patterns/reversal-structures/triple-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-top/", repoUrl: null, hasFixture: false }, + { id: "D08-F02-A04", title: "Triple Bottom", slug: "triple-bottom", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "tripleBottom", exports: ["confirmedPivots","detectReversal","traceReversal","tripleBottom"], path: "geometric-chart-patterns/reversal-structures/triple-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-bottom/", repoUrl: null, hasFixture: false }, + { id: "D08-F02-A05", title: "Head and Shoulders", slug: "head-and-shoulders", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "headAndShoulders", exports: ["confirmedPivots","detectReversal","traceReversal","headAndShoulders"], path: "geometric-chart-patterns/reversal-structures/head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/head-and-shoulders/", repoUrl: null, hasFixture: false }, + { id: "D08-F02-A06", title: "Inverse Head and Shoulders", slug: "inverse-head-and-shoulders", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F02", family: "Reversal Structures", difficulty: 3, archetype: "record-transform", entry: "inverseHeadAndShoulders", exports: ["confirmedPivots","detectReversal","traceReversal","inverseHeadAndShoulders"], path: "geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/", repoUrl: null, hasFixture: false }, { id: "D08-F05-A01", title: "Price–Indicator Pivot Alignment", slug: "price-indicator-pivot-alignment", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F05", family: "Indicator Divergence Detection", difficulty: 3, archetype: "record-transform", entry: "priceIndicatorPivotAlignment", exports: ["adaptIndicator","alignPivots","detectDivergences","scoreDivergence","advanceState","combineConfluence","rankUniverse","runTopic","priceIndicatorPivotAlignment","regularBullishBearishDivergenceDetection","hiddenBullishBearishDivergenceDetection","multiIndicatorDivergenceAdapters","divergenceStrengthAndQualityScoring","divergenceConfirmationAndInvalidationStateMachine","multiIndicatorDivergenceConfluence","marketWideDivergenceScannerAndRanking"], path: "geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/", repoUrl: null, hasFixture: false }, { id: "D08-F05-A02", title: "Regular Bullish/Bearish Divergence Detection", slug: "regular-bullish-bearish-divergence-detection", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F05", family: "Indicator Divergence Detection", difficulty: 3, archetype: "record-transform", entry: "regularBullishBearishDivergenceDetection", exports: ["adaptIndicator","alignPivots","detectDivergences","scoreDivergence","advanceState","combineConfluence","rankUniverse","runTopic","priceIndicatorPivotAlignment","regularBullishBearishDivergenceDetection","hiddenBullishBearishDivergenceDetection","multiIndicatorDivergenceAdapters","divergenceStrengthAndQualityScoring","divergenceConfirmationAndInvalidationStateMachine","multiIndicatorDivergenceConfluence","marketWideDivergenceScannerAndRanking"], path: "geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/", repoUrl: null, hasFixture: false }, { id: "D08-F05-A03", title: "Hidden Bullish/Bearish Divergence Detection", slug: "hidden-bullish-bearish-divergence-detection", domainId: "D08", domain: "Geometric Chart Patterns", familyId: "D08-F05", family: "Indicator Divergence Detection", difficulty: 3, archetype: "record-transform", entry: "hiddenBullishBearishDivergenceDetection", exports: ["adaptIndicator","alignPivots","detectDivergences","scoreDivergence","advanceState","combineConfluence","rankUniverse","runTopic","priceIndicatorPivotAlignment","regularBullishBearishDivergenceDetection","hiddenBullishBearishDivergenceDetection","multiIndicatorDivergenceAdapters","divergenceStrengthAndQualityScoring","divergenceConfirmationAndInvalidationStateMachine","multiIndicatorDivergenceConfluence","marketWideDivergenceScannerAndRanking"], path: "geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/", repoUrl: null, hasFixture: false }, @@ -262,23 +262,23 @@ export const topics: readonly TopicMeta[] = [ { id: "D09-F01-A04", title: "KPSS", slug: "kpss", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F01", family: "Diagnostics", difficulty: 3, archetype: "record-transform", entry: "kpss", exports: ["acf","pacf","adf","kpss","ljungBox","zivotAndrews","runDiagnostic"], path: "statistical-time-series/diagnostics/kpss", articleUrl: "https://thefintechbuilder.com/statistical-time-series/diagnostics/kpss/", repoUrl: null, hasFixture: false }, { id: "D09-F01-A05", title: "Ljung-Box", slug: "ljung-box", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F01", family: "Diagnostics", difficulty: 3, archetype: "record-transform", entry: "ljungBox", exports: ["acf","pacf","adf","kpss","ljungBox","zivotAndrews","runDiagnostic"], path: "statistical-time-series/diagnostics/ljung-box", articleUrl: "https://thefintechbuilder.com/statistical-time-series/diagnostics/ljung-box/", repoUrl: null, hasFixture: false }, { id: "D09-F01-A06", title: "Zivot-Andrews Break Test", slug: "zivot-andrews-break-test", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F01", family: "Diagnostics", difficulty: 4, archetype: "record-transform", entry: "zivotAndrews", exports: ["acf","pacf","adf","kpss","ljungBox","zivotAndrews","runDiagnostic"], path: "statistical-time-series/diagnostics/zivot-andrews-break-test", articleUrl: "https://thefintechbuilder.com/statistical-time-series/diagnostics/zivot-andrews-break-test/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A01", title: "AutoReg", slug: "autoreg", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 2, archetype: "record-transform", entry: "forecastAutoReg", exports: ["forecastAutoReg"], path: "statistical-time-series/forecast-models/autoreg", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/autoreg/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A02", title: "ARMA", slug: "arma", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastARMA", exports: ["forecastARMA"], path: "statistical-time-series/forecast-models/arma", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/arma/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A03", title: "ARIMA", slug: "arima", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastARIMA", exports: ["forecastARIMA"], path: "statistical-time-series/forecast-models/arima", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/arima/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A04", title: "SARIMA/SARIMAX", slug: "sarima-sarimax", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 4, archetype: "record-transform", entry: "forecastSARIMAX", exports: ["forecastSARIMAX"], path: "statistical-time-series/forecast-models/sarima-sarimax", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/sarima-sarimax/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A05", title: "Holt-Winters", slug: "holt-winters", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastHoltWintersAdditive", exports: ["forecastHoltWintersAdditive"], path: "statistical-time-series/forecast-models/holt-winters", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/holt-winters/", repoUrl: null, hasFixture: false }, - { id: "D09-F02-A06", title: "Theta Forecast", slug: "theta-forecast", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastTheta", exports: ["forecastTheta"], path: "statistical-time-series/forecast-models/theta-forecast", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/theta-forecast/", repoUrl: null, hasFixture: false }, + { id: "D09-F02-A01", title: "AutoReg", slug: "autoreg", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 2, archetype: "record-transform", entry: "forecastAutoReg", exports: ["forecastAutoReg"], path: "statistical-time-series/forecast-models/autoreg", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/autoreg/", repoUrl: null, hasFixture: true }, + { id: "D09-F02-A02", title: "ARMA", slug: "arma", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastARMA", exports: ["forecastARMA"], path: "statistical-time-series/forecast-models/arma", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/arma/", repoUrl: null, hasFixture: true }, + { id: "D09-F02-A03", title: "ARIMA", slug: "arima", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastARIMA", exports: ["forecastARIMA"], path: "statistical-time-series/forecast-models/arima", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/arima/", repoUrl: null, hasFixture: true }, + { id: "D09-F02-A04", title: "SARIMA/SARIMAX", slug: "sarima-sarimax", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 4, archetype: "record-transform", entry: "forecastSARIMAX", exports: ["forecastSARIMAX"], path: "statistical-time-series/forecast-models/sarima-sarimax", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/sarima-sarimax/", repoUrl: null, hasFixture: true }, + { id: "D09-F02-A05", title: "Holt-Winters", slug: "holt-winters", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastHoltWintersAdditive", exports: ["forecastHoltWintersAdditive"], path: "statistical-time-series/forecast-models/holt-winters", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/holt-winters/", repoUrl: null, hasFixture: true }, + { id: "D09-F02-A06", title: "Theta Forecast", slug: "theta-forecast", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F02", family: "Forecast Models", difficulty: 3, archetype: "record-transform", entry: "forecastTheta", exports: ["forecastTheta"], path: "statistical-time-series/forecast-models/theta-forecast", articleUrl: "https://thefintechbuilder.com/statistical-time-series/forecast-models/theta-forecast/", repoUrl: null, hasFixture: true }, { id: "D09-F03-A01", title: "VAR", slug: "var", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F03", family: "Multivariate Systems", difficulty: 3, archetype: "record-transform", entry: "fitVAR", exports: ["companionMatrix","companionSpectralRadius","fitVAR","choleskyLower","fitRecursiveSVAR","fitVECMFixedBeta","movingAverageMatrices","impulseResponses","forecastErrorVarianceDecomposition"], path: "statistical-time-series/multivariate-systems/var", articleUrl: "https://thefintechbuilder.com/statistical-time-series/multivariate-systems/var/", repoUrl: null, hasFixture: false }, { id: "D09-F03-A02", title: "Structural VAR", slug: "structural-var", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F03", family: "Multivariate Systems", difficulty: 4, archetype: "record-transform", entry: "fitRecursiveSVAR", exports: ["companionMatrix","companionSpectralRadius","fitVAR","choleskyLower","fitRecursiveSVAR","fitVECMFixedBeta","movingAverageMatrices","impulseResponses","forecastErrorVarianceDecomposition"], path: "statistical-time-series/multivariate-systems/structural-var", articleUrl: "https://thefintechbuilder.com/statistical-time-series/multivariate-systems/structural-var/", repoUrl: null, hasFixture: false }, { id: "D09-F03-A03", title: "VECM", slug: "vecm", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F03", family: "Multivariate Systems", difficulty: 4, archetype: "record-transform", entry: "fitVECMFixedBeta", exports: ["companionMatrix","companionSpectralRadius","fitVAR","choleskyLower","fitRecursiveSVAR","fitVECMFixedBeta","movingAverageMatrices","impulseResponses","forecastErrorVarianceDecomposition"], path: "statistical-time-series/multivariate-systems/vecm", articleUrl: "https://thefintechbuilder.com/statistical-time-series/multivariate-systems/vecm/", repoUrl: null, hasFixture: false }, { id: "D09-F03-A04", title: "Impulse-Response Analysis", slug: "impulse-response-analysis", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F03", family: "Multivariate Systems", difficulty: 4, archetype: "record-transform", entry: "impulseResponses", exports: ["companionMatrix","companionSpectralRadius","fitVAR","choleskyLower","fitRecursiveSVAR","fitVECMFixedBeta","movingAverageMatrices","impulseResponses","forecastErrorVarianceDecomposition"], path: "statistical-time-series/multivariate-systems/impulse-response-analysis", articleUrl: "https://thefintechbuilder.com/statistical-time-series/multivariate-systems/impulse-response-analysis/", repoUrl: null, hasFixture: false }, { id: "D09-F03-A05", title: "Forecast-Error Variance Decomposition", slug: "forecast-error-variance-decomposition", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F03", family: "Multivariate Systems", difficulty: 4, archetype: "record-transform", entry: "forecastErrorVarianceDecomposition", exports: ["companionMatrix","companionSpectralRadius","fitVAR","choleskyLower","fitRecursiveSVAR","fitVECMFixedBeta","movingAverageMatrices","impulseResponses","forecastErrorVarianceDecomposition"], path: "statistical-time-series/multivariate-systems/forecast-error-variance-decomposition", articleUrl: "https://thefintechbuilder.com/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A01", title: "Kalman Filter", slug: "kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 3, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/kalman-filter/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A02", title: "Extended Kalman Filter", slug: "extended-kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/extended-kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/extended-kalman-filter/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A03", title: "Unscented Kalman Filter", slug: "unscented-kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/unscented-kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/unscented-kalman-filter/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A04", title: "Hidden Markov Model", slug: "hidden-markov-model", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 3, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/hidden-markov-model", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/hidden-markov-model/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A05", title: "Markov-Switching Autoregression", slug: "markov-switching-autoregression", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/markov-switching-autoregression", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/markov-switching-autoregression/", repoUrl: null, hasFixture: false }, - { id: "D09-F04-A06", title: "Bayesian Change-Point Detection", slug: "bayesian-change-point-detection", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/bayesian-change-point-detection", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/", repoUrl: null, hasFixture: false }, + { id: "D09-F04-A01", title: "Kalman Filter", slug: "kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 3, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/kalman-filter/", repoUrl: null, hasFixture: true }, + { id: "D09-F04-A02", title: "Extended Kalman Filter", slug: "extended-kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/extended-kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/extended-kalman-filter/", repoUrl: null, hasFixture: true }, + { id: "D09-F04-A03", title: "Unscented Kalman Filter", slug: "unscented-kalman-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/unscented-kalman-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/unscented-kalman-filter/", repoUrl: null, hasFixture: true }, + { id: "D09-F04-A04", title: "Hidden Markov Model", slug: "hidden-markov-model", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 3, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/hidden-markov-model", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/hidden-markov-model/", repoUrl: null, hasFixture: true }, + { id: "D09-F04-A05", title: "Markov-Switching Autoregression", slug: "markov-switching-autoregression", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/markov-switching-autoregression", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/markov-switching-autoregression/", repoUrl: null, hasFixture: true }, + { id: "D09-F04-A06", title: "Bayesian Change-Point Detection", slug: "bayesian-change-point-detection", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F04", family: "State and Regime Models", difficulty: 4, archetype: "record-transform", entry: "runFilter", exports: ["runFilter"], path: "statistical-time-series/state-and-regime-models/bayesian-change-point-detection", articleUrl: "https://thefintechbuilder.com/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/", repoUrl: null, hasFixture: true }, { id: "D09-F05-A01", title: "STL Decomposition", slug: "stl-decomposition", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F05", family: "Decomposition and Cycles", difficulty: 3, archetype: "record-transform", entry: "stlDecompose", exports: ["stlDecompose","hpFilter","bkFilter","cfFilter","fftPeriodogram","haarWavelet","runTopic"], path: "statistical-time-series/decomposition-and-cycles/stl-decomposition", articleUrl: "https://thefintechbuilder.com/statistical-time-series/decomposition-and-cycles/stl-decomposition/", repoUrl: null, hasFixture: false }, { id: "D09-F05-A02", title: "Hodrick-Prescott Filter", slug: "hodrick-prescott-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F05", family: "Decomposition and Cycles", difficulty: 3, archetype: "record-transform", entry: "hpFilter", exports: ["stlDecompose","hpFilter","bkFilter","cfFilter","fftPeriodogram","haarWavelet","runTopic"], path: "statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/", repoUrl: null, hasFixture: false }, { id: "D09-F05-A03", title: "Baxter-King Filter", slug: "baxter-king-filter", domainId: "D09", domain: "Statistical Time Series", familyId: "D09-F05", family: "Decomposition and Cycles", difficulty: 4, archetype: "record-transform", entry: "bkFilter", exports: ["stlDecompose","hpFilter","bkFilter","cfFilter","fftPeriodogram","haarWavelet","runTopic"], path: "statistical-time-series/decomposition-and-cycles/baxter-king-filter", articleUrl: "https://thefintechbuilder.com/statistical-time-series/decomposition-and-cycles/baxter-king-filter/", repoUrl: null, hasFixture: false }, diff --git a/src/_shared/momentum.ts b/src/_shared/momentum.ts index 94ddd9c..6d6c441 100644 --- a/src/_shared/momentum.ts +++ b/src/_shared/momentum.ts @@ -10,10 +10,10 @@ const sma = (x:Maybe[],p:number) => x.map((_,i)=>{if(i { period(p,"period"); const x=series(values,"values"),out:Maybe[]=Array(x.length).fill(null); if(x.length<=p)return out; let g=0,l=0; for(let i=1;i<=p;i++){const d=x[i]-x[i-1];g+=Math.max(d,0);l+=Math.max(-d,0)} g/=p;l/=p; const val=(a:number,b:number)=>a===0&&b===0?50:b===0?100:a===0?0:100-100/(1+a/b); out[p]=val(g,l); for(let i=p+1;iv!==null)){const a=w as number[],hi=Math.max(...a),lo=Math.min(...a);if(hi!==lo)raw[i]=100*((values[i] as number)-lo)/(hi-lo)}}const k=sma(raw,sk);return{rsi:values,raw_k:raw,k,d:sma(k,sd)}} -export function williams_r(high:number[],low:number[],close:number[],p=14){period(p,"period");const[h,l,c]=aligned(high,low,close),out:Maybe[]=Array(c.length).fill(null);for(let i=p-1;iv!==null)){const a=w as number[],hi=Math.max(...a),lo=Math.min(...a);if(hi!==lo)raw[i]=100*((values[i] as number)-lo)/(hi-lo)}}const k=sma(raw,sk);return{rsi:values,raw_k:raw,k,d:sma(k,sd)}} +export function williamsR(high:number[],low:number[],close:number[],p=14){period(p,"period");const[h,l,c]=aligned(high,low,close),out:Maybe[]=Array(c.length).fill(null);for(let i=p-1;i(h[i]+l[i]+v)/3),out:Maybe[]=Array(c.length).fill(null);for(let i=p-1;ia+b,0)/p,d=w.reduce((a,b)=>a+Math.abs(b-m),0)/p;if(d!==0)out[i]=(tp[i]-m)/(k*d)}return{typical_price:tp,cci:out}} -export function ultimate_oscillator(high:number[],low:number[],close:number[],s=7,m=14,g=28){[["short",s],["medium",m],["long",g]].forEach(([n,v])=>period(v as number,n as string));if(!(sa+v,0),t=(tr.slice(i-p+1,i+1) as number[]).reduce((a,v)=>a+v,0);if(t===0){ok=false;break}ratios.push(b/t)}if(ok)out[i]=100*(4*ratios[0]+2*ratios[1]+ratios[2])/7}return{buying_pressure:bp,true_range:tr,ultimate_oscillator:out}} +export function ultimateOscillator(high:number[],low:number[],close:number[],s=7,m=14,g=28){[["short",s],["medium",m],["long",g]].forEach(([n,v])=>period(v as number,n as string));if(!(sa+v,0),t=(tr.slice(i-p+1,i+1) as number[]).reduce((a,v)=>a+v,0);if(t===0){ok=false;break}ratios.push(b/t)}if(ok)out[i]=100*(4*ratios[0]+2*ratios[1]+ratios[2])/7}return{buying_pressure:bp,true_range:tr,ultimate_oscillator:out}} const emaFirst=(x:Maybe[],p:number)=>{const a=2/(p+1),out:Maybe[]=Array(x.length).fill(null);let prev:number|null=null;x.forEach((v,i)=>{if(v===null)return;prev=prev===null?v:prev+a*(v-prev);out[i]=prev});return out}; export function tsi(close:number[],g=25,s=13){period(g,"long");period(s,"short");const c=series(close,"close"),d:Maybe[]=[null,...c.slice(1).map((v,i)=>v-c[i])],n=emaFirst(emaFirst(d,g),s),q=emaFirst(emaFirst(d.map(v=>v===null?null:Math.abs(v)),g),s),out:Maybe[]=Array(c.length).fill(null);for(let i=g+s-1;ic[i-1])streak[i]=streak[i-1]>0?streak[i-1]+1:1;else if(c[i](v-c[i])/c[i])],rank:Maybe[]=Array(c.length).fill(null),out:Maybe[]=Array(c.length).fill(null);for(let i=rp+1;iv<(roc[i] as number)).length/rp;if(price[i]!==null&&srsi[i]!==null)out[i]=((price[i] as number)+(srsi[i] as number)+(rank[i] as number))/3}return{price_rsi:price,streak,streak_rsi:srsi,percent_rank:rank,connors_rsi:out}} +export function connorsRsi(close:number[],pp=3,sp=2,rp=100){period(pp,"price_period");period(sp,"streak_period");period(rp,"rank_period");const c=series(close,"close",true),price=rsiValues(c,pp),streak:number[]=Array(c.length).fill(0);for(let i=1;ic[i-1])streak[i]=streak[i-1]>0?streak[i-1]+1:1;else if(c[i](v-c[i])/c[i])],rank:Maybe[]=Array(c.length).fill(null),out:Maybe[]=Array(c.length).fill(null);for(let i=rp+1;iv<(roc[i] as number)).length/rp;if(price[i]!==null&&srsi[i]!==null)out[i]=((price[i] as number)+(srsi[i] as number)+(rank[i] as number))/3}return{price_rsi:price,streak,streak_rsi:srsi,percent_rank:rank,connors_rsi:out}} diff --git a/src/_shared/reversal.ts b/src/_shared/reversal.ts deleted file mode 100644 index 114745a..0000000 --- a/src/_shared/reversal.ts +++ /dev/null @@ -1,220 +0,0 @@ -// GENERATED by scripts/sync.mjs — do not edit. -// Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A01-double-top/implementations/typescript/reversal.ts (shared by 6 topics) -// Re-run `npm run sync` after changing the catalog implementation. - -export type Pivot = { - kind: "high" | "low"; - index: number; - confirmation_index: number; - price: number; -}; - -export type Detection = { - pattern: string; - state: "searching" | "candidate" | "confirmed" | "rejected"; - reason: string; - event: Record | null; - events: Record[]; - pivots: Pivot[]; - parameters: Record; -}; - -const PATTERNS: Record; side: "top" | "bottom" }> = { - double_top: { types: ["high", "low", "high"], side: "top" }, - double_bottom: { types: ["low", "high", "low"], side: "bottom" }, - triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, - triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, - head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, - inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, -}; - -const DEFAULTS: Record = { - pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, - max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, - shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, - min_prior_trend: 0.03, break_buffer: 0, -}; - -function validated(close: number[], pattern: string, overrides: Record) { - if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); - if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); - const values = close.map((value) => { - if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { - throw new Error("close values must be finite and strictly positive"); - } - return value; - }); - for (const key of Object.keys(overrides)) { - if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); - } - const params = { ...DEFAULTS, ...overrides }; - for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { - if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); - } - for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { - if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); - } - if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); - return { values, params }; -} - -export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { - const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); - const pivots: Pivot[] = []; - for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { - const center = values[index]; - const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); - const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; - if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); - } - return pivots; -} - -function spread(values: number[]) { - const mean = values.reduce((a, b) => a + b, 0) / values.length; - return (Math.max(...values) - Math.min(...values)) / mean; -} - -function line(a: Pivot, b: Pivot, index: number) { - if (a.index === b.index) return a.price; - return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); -} - -function metrics(pattern: string, pivots: Pivot[]) { - const prices = pivots.map((pivot) => pivot.price); - let tests: number[], retracements: number[], headDominance: number | null = null; - if (prices.length === 3) { - tests = [prices[0], prices[2]]; - const mean = (tests[0] + tests[1]) / 2; - retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; - } else { - tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; - const mean = tests.reduce((a, b) => a + b, 0) / tests.length; - retracements = PATTERNS[pattern].side === "top" - ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] - : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; - if (pattern.includes("head_and_shoulders")) { - headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; - } - } - const mean = tests.reduce((a, b) => a + b, 0) / tests.length; - return { - test_mean: mean, - level_spread: spread(tests), - retracement_min: Math.min(...retracements), - head_dominance: headDominance, - formation_bars: pivots.at(-1)!.index - pivots[0].index, - min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), - }; -} - -function shape(pattern: string, pivots: Pivot[], params: Record) { - const prices = pivots.map((pivot) => pivot.price); - if (pattern === "double_top" || pattern === "double_bottom") { - const outer = [prices[0], prices[2]]; - if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; - const mean = (outer[0] + outer[1]) / 2; - const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; - if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; - return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; - } - if (pattern === "triple_top" || pattern === "triple_bottom") { - const tests = [prices[0], prices[2], prices[4]]; - const mean = tests.reduce((a, b) => a + b, 0) / 3; - if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; - const retracements = pattern === "triple_top" - ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] - : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; - if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; - return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; - } - const shoulders = [prices[0], prices[4]]; - const mean = (shoulders[0] + shoulders[1]) / 2; - if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; - const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; - if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; - const retracements = pattern === "head_and_shoulders" - ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] - : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; - if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; - return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; -} - -function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { - const spec = PATTERNS[pattern]; - const first = pivots[0], last = pivots[pivots.length - 1]; - const base = { - pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), - pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), - confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), - }; - if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; - if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; - if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; - const prior = close[first.index - params.trend_lookback]; - const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; - const baseWithTrend = { ...base, prior_move: priorMove }; - if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; - const geometry = shape(pattern, pivots, params); - if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; - const start = baseWithTrend.candidate_available_index; - const deadline = last.index + params.max_confirmation_bars; - for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { - const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); - const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); - if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; - } - const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); - if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; - return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; -} - -export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { - const { values, params } = validated(close, pattern, overrides); - const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); - const expected = PATTERNS[pattern].types; - const evaluations: Record[] = []; - for (let start = 0; start <= pivots.length - expected.length; start += 1) { - const window = pivots.slice(start, start + expected.length); - if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); - } - const confirmed = evaluations.filter((item) => item.state === "confirmed"); - const candidates = evaluations.filter((item) => item.state === "candidate"); - const rejected = evaluations.filter((item) => item.state === "rejected"); - const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; - return { - pattern, - state: (selected?.state as Detection["state"]) ?? "searching", - reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", - event: selected, - events: confirmed, - pivots, - parameters: params, - }; -} - -export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { - validated(close, pattern, overrides); - return close.map((value, index) => { - const result = detectReversal(close.slice(0, index + 1), pattern, overrides); - const event = result.event; - return { - index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, - pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], - candidate_available_index: (event?.candidate_available_index as number | null) ?? null, - neckline: (event?.neckline as number | null) ?? null, - confirmation_index: (event?.confirmation_index as number | null) ?? null, - metrics: (event?.metrics as Record) ?? null, - prior_move: (event?.prior_move as number | null) ?? null, - known_pivots: result.pivots.map((pivot) => ({ ...pivot })), - confirmed: result.state === "confirmed", - }; - }); -} - -export const double_top = (close: number[], params: Record = {}) => detectReversal(close, "double_top", params); -export const double_bottom = (close: number[], params: Record = {}) => detectReversal(close, "double_bottom", params); -export const triple_top = (close: number[], params: Record = {}) => detectReversal(close, "triple_top", params); -export const triple_bottom = (close: number[], params: Record = {}) => detectReversal(close, "triple_bottom", params); -export const head_and_shoulders = (close: number[], params: Record = {}) => detectReversal(close, "head_and_shoulders", params); -export const inverse_head_and_shoulders = (close: number[], params: Record = {}) => detectReversal(close, "inverse_head_and_shoulders", params); diff --git a/src/_shared/volume.ts b/src/_shared/volume.ts index 17bedda..4fe16c4 100644 --- a/src/_shared/volume.ts +++ b/src/_shared/volume.ts @@ -8,8 +8,8 @@ function aligned(...items:number[][]){if(new Set(items.map(x=>x.length)).size!== function ohlcv(high:number[],low:number[],close:number[],volume:number[]){high=series(high,"high");low=series(low,"low");close=series(close,"close");volume=series(volume,"volume",true);aligned(high,low,close,volume);for(let i=0;ihigh[i]||close[i]high[i])throw new Error("require low <= close <= high");return{high,low,close,volume}} function moneyFlow(high:number[],low:number[],close:number[],volume:number[]){const x=ohlcv(high,low,close,volume),multiplier:number[]=[],mfv:number[]=[];for(let i=0;iclose[i-1]?1:close[i](running+=value));return{range:x.high.map((h,i)=>h-x.low[i]),money_flow_multiplier:x.multiplier,volume:x.volume,money_flow_volume:x.mfv,adl}} -export function chaikin_money_flow(high:number[],low:number[],close:number[],volume:number[],p=20){period(p,"period");const x=moneyFlow(high,low,close,volume),rolling_mfv:(number|null)[]=Array(x.close.length).fill(null),rolling_volume:(number|null)[]=Array(x.close.length).fill(null),cmf:(number|null)[]=Array(x.close.length).fill(null);let numerator=0,denominator=0;for(let i=0;i=p){numerator-=x.mfv[i-p];denominator-=x.volume[i-p]}if(i>=p-1){rolling_mfv[i]=numerator;rolling_volume[i]=denominator;if(denominator!==0)cmf[i]=numerator/denominator}}return{money_flow_multiplier:x.multiplier,money_flow_volume:x.mfv,rolling_mfv,rolling_volume,cmf}} -export function money_flow_index(high:number[],low:number[],close:number[],volume:number[],p=14){period(p,"period");const x=ohlcv(high,low,close,volume),typical_price=x.close.map((c,i)=>(x.high[i]+x.low[i]+c)/3),raw_money_flow=typical_price.map((v,i)=>v*x.volume[i]),positive=Array(x.close.length).fill(0),negative=Array(x.close.length).fill(0);for(let i=1;itypical_price[i-1])positive[i]=raw_money_flow[i];else if(typical_price[i]=p){ps=Math.max(0,ps-positive[i-p]);ns=Math.max(0,ns-negative[i-p])}if(iv-close[i])],raw_force:(number|null)[]=[null,...close.slice(1).map((_,i)=>(change[i+1] as number)*volume[i+1])],ema_seed:(number|null)[]=Array(close.length).fill(null),output:(number|null)[]=Array(close.length).fill(null);if(close.length>p){let value=(raw_force.slice(1,p+1) as number[]).reduce((a,b)=>a+b,0)/p;ema_seed[p]=value;output[p]=value;const alpha=2/(p+1);for(let i=p+1;i(running+=value));return{range:x.high.map((h,i)=>h-x.low[i]),money_flow_multiplier:x.multiplier,volume:x.volume,money_flow_volume:x.mfv,adl}} +export function chaikinMoneyFlow(high:number[],low:number[],close:number[],volume:number[],p=20){period(p,"period");const x=moneyFlow(high,low,close,volume),rolling_mfv:(number|null)[]=Array(x.close.length).fill(null),rolling_volume:(number|null)[]=Array(x.close.length).fill(null),cmf:(number|null)[]=Array(x.close.length).fill(null);let numerator=0,denominator=0;for(let i=0;i=p){numerator-=x.mfv[i-p];denominator-=x.volume[i-p]}if(i>=p-1){rolling_mfv[i]=numerator;rolling_volume[i]=denominator;if(denominator!==0)cmf[i]=numerator/denominator}}return{money_flow_multiplier:x.multiplier,money_flow_volume:x.mfv,rolling_mfv,rolling_volume,cmf}} +export function moneyFlowIndex(high:number[],low:number[],close:number[],volume:number[],p=14){period(p,"period");const x=ohlcv(high,low,close,volume),typical_price=x.close.map((c,i)=>(x.high[i]+x.low[i]+c)/3),raw_money_flow=typical_price.map((v,i)=>v*x.volume[i]),positive=Array(x.close.length).fill(0),negative=Array(x.close.length).fill(0);for(let i=1;itypical_price[i-1])positive[i]=raw_money_flow[i];else if(typical_price[i]=p){ps=Math.max(0,ps-positive[i-p]);ns=Math.max(0,ns-negative[i-p])}if(iv-close[i])],raw_force:(number|null)[]=[null,...close.slice(1).map((_,i)=>(change[i+1] as number)*volume[i+1])],ema_seed:(number|null)[]=Array(close.length).fill(null),output:(number|null)[]=Array(close.length).fill(null);if(close.length>p){let value=(raw_force.slice(1,p+1) as number[]).reduce((a,b)=>a+b,0)/p;ema_seed[p]=value;output[p]=value;const alpha=2/(p+1);for(let i=p+1;i | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function doubleBottom( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "double_bottom", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/double-bottom/index.ts b/src/geometric-chart-patterns/reversal-structures/double-bottom/index.ts index da27c96..406ef06 100644 --- a/src/geometric-chart-patterns/reversal-structures/double-bottom/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/double-bottom/index.ts @@ -2,7 +2,7 @@ * Double Bottom * * Topic D08-F02-A02 · Geometric Chart Patterns / Reversal Structures · difficulty 2 - * Shape: record-transform · entry: double_bottom() + * Shape: record-transform · entry: doubleBottom() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-bottom/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { double_bottom as run } from "./impl.ts"; +export { doubleBottom as run } from "./impl.ts"; export const meta = { id: "D08-F02-A02", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 2, archetype: "record-transform", - entry: "double_bottom", + entry: "doubleBottom", path: "geometric-chart-patterns/reversal-structures/double-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-bottom/", repoUrl: null, diff --git a/src/geometric-chart-patterns/reversal-structures/double-top/impl.ts b/src/geometric-chart-patterns/reversal-structures/double-top/impl.ts index 4d3c79d..c38551c 100644 --- a/src/geometric-chart-patterns/reversal-structures/double-top/impl.ts +++ b/src/geometric-chart-patterns/reversal-structures/double-top/impl.ts @@ -1,9 +1,220 @@ // GENERATED by scripts/sync.mjs — do not edit. // Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A01-double-top/implementations/typescript/reversal.ts // Re-run `npm run sync` after changing the catalog implementation. -// -// This family shares one implementation across its topics; the body lives at -// src/_shared/reversal.ts and is re-exported here so the public surface of -// this subpath is unchanged. -export * from "../../../_shared/reversal.ts"; +export type Pivot = { + kind: "high" | "low"; + index: number; + confirmation_index: number; + price: number; +}; + +export type Detection = { + pattern: string; + state: "searching" | "candidate" | "confirmed" | "rejected"; + reason: string; + event: Record | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function doubleTop( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "double_top", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/double-top/index.ts b/src/geometric-chart-patterns/reversal-structures/double-top/index.ts index ddc12f6..e052ab9 100644 --- a/src/geometric-chart-patterns/reversal-structures/double-top/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/double-top/index.ts @@ -2,7 +2,7 @@ * Double Top * * Topic D08-F02-A01 · Geometric Chart Patterns / Reversal Structures · difficulty 2 - * Shape: record-transform · entry: double_top() + * Shape: record-transform · entry: doubleTop() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-top/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { double_top as run } from "./impl.ts"; +export { doubleTop as run } from "./impl.ts"; export const meta = { id: "D08-F02-A01", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 2, archetype: "record-transform", - entry: "double_top", + entry: "doubleTop", path: "geometric-chart-patterns/reversal-structures/double-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/double-top/", repoUrl: null, diff --git a/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/impl.ts b/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/impl.ts index 356a3c6..4dea474 100644 --- a/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/impl.ts +++ b/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/impl.ts @@ -1,9 +1,220 @@ // GENERATED by scripts/sync.mjs — do not edit. // Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A05-head-and-shoulders/implementations/typescript/reversal.ts // Re-run `npm run sync` after changing the catalog implementation. -// -// This family shares one implementation across its topics; the body lives at -// src/_shared/reversal.ts and is re-exported here so the public surface of -// this subpath is unchanged. -export * from "../../../_shared/reversal.ts"; +export type Pivot = { + kind: "high" | "low"; + index: number; + confirmation_index: number; + price: number; +}; + +export type Detection = { + pattern: string; + state: "searching" | "candidate" | "confirmed" | "rejected"; + reason: string; + event: Record | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function headAndShoulders( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "head_and_shoulders", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.ts b/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.ts index de77e0f..e428db7 100644 --- a/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.ts @@ -2,7 +2,7 @@ * Head and Shoulders * * Topic D08-F02-A05 · Geometric Chart Patterns / Reversal Structures · difficulty 3 - * Shape: record-transform · entry: head_and_shoulders() + * Shape: record-transform · entry: headAndShoulders() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/head-and-shoulders/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { head_and_shoulders as run } from "./impl.ts"; +export { headAndShoulders as run } from "./impl.ts"; export const meta = { id: "D08-F02-A05", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 3, archetype: "record-transform", - entry: "head_and_shoulders", + entry: "headAndShoulders", path: "geometric-chart-patterns/reversal-structures/head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/head-and-shoulders/", repoUrl: null, diff --git a/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/impl.ts b/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/impl.ts index 6026d94..2a3432a 100644 --- a/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/impl.ts +++ b/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/impl.ts @@ -1,9 +1,220 @@ // GENERATED by scripts/sync.mjs — do not edit. // Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A06-inverse-head-and-shoulders/implementations/typescript/reversal.ts // Re-run `npm run sync` after changing the catalog implementation. -// -// This family shares one implementation across its topics; the body lives at -// src/_shared/reversal.ts and is re-exported here so the public surface of -// this subpath is unchanged. -export * from "../../../_shared/reversal.ts"; +export type Pivot = { + kind: "high" | "low"; + index: number; + confirmation_index: number; + price: number; +}; + +export type Detection = { + pattern: string; + state: "searching" | "candidate" | "confirmed" | "rejected"; + reason: string; + event: Record | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function inverseHeadAndShoulders( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "inverse_head_and_shoulders", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.ts b/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.ts index d2ed6a9..0bb6cde 100644 --- a/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.ts @@ -2,7 +2,7 @@ * Inverse Head and Shoulders * * Topic D08-F02-A06 · Geometric Chart Patterns / Reversal Structures · difficulty 3 - * Shape: record-transform · entry: inverse_head_and_shoulders() + * Shape: record-transform · entry: inverseHeadAndShoulders() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { inverse_head_and_shoulders as run } from "./impl.ts"; +export { inverseHeadAndShoulders as run } from "./impl.ts"; export const meta = { id: "D08-F02-A06", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 3, archetype: "record-transform", - entry: "inverse_head_and_shoulders", + entry: "inverseHeadAndShoulders", path: "geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/", repoUrl: null, diff --git a/src/geometric-chart-patterns/reversal-structures/triple-bottom/impl.ts b/src/geometric-chart-patterns/reversal-structures/triple-bottom/impl.ts index 898acd0..c189fa4 100644 --- a/src/geometric-chart-patterns/reversal-structures/triple-bottom/impl.ts +++ b/src/geometric-chart-patterns/reversal-structures/triple-bottom/impl.ts @@ -1,9 +1,220 @@ // GENERATED by scripts/sync.mjs — do not edit. // Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A04-triple-bottom/implementations/typescript/reversal.ts // Re-run `npm run sync` after changing the catalog implementation. -// -// This family shares one implementation across its topics; the body lives at -// src/_shared/reversal.ts and is re-exported here so the public surface of -// this subpath is unchanged. -export * from "../../../_shared/reversal.ts"; +export type Pivot = { + kind: "high" | "low"; + index: number; + confirmation_index: number; + price: number; +}; + +export type Detection = { + pattern: string; + state: "searching" | "candidate" | "confirmed" | "rejected"; + reason: string; + event: Record | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function tripleBottom( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "triple_bottom", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/triple-bottom/index.ts b/src/geometric-chart-patterns/reversal-structures/triple-bottom/index.ts index 499043c..ac687f6 100644 --- a/src/geometric-chart-patterns/reversal-structures/triple-bottom/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/triple-bottom/index.ts @@ -2,7 +2,7 @@ * Triple Bottom * * Topic D08-F02-A04 · Geometric Chart Patterns / Reversal Structures · difficulty 3 - * Shape: record-transform · entry: triple_bottom() + * Shape: record-transform · entry: tripleBottom() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-bottom/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { triple_bottom as run } from "./impl.ts"; +export { tripleBottom as run } from "./impl.ts"; export const meta = { id: "D08-F02-A04", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 3, archetype: "record-transform", - entry: "triple_bottom", + entry: "tripleBottom", path: "geometric-chart-patterns/reversal-structures/triple-bottom", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-bottom/", repoUrl: null, diff --git a/src/geometric-chart-patterns/reversal-structures/triple-top/impl.ts b/src/geometric-chart-patterns/reversal-structures/triple-top/impl.ts index ab67ab7..568d068 100644 --- a/src/geometric-chart-patterns/reversal-structures/triple-top/impl.ts +++ b/src/geometric-chart-patterns/reversal-structures/triple-top/impl.ts @@ -1,9 +1,220 @@ // GENERATED by scripts/sync.mjs — do not edit. // Source of truth: algorithms/domains/D08-geometric-chart-patterns/D08-F02-reversal-structures/D08-F02-A03-triple-top/implementations/typescript/reversal.ts // Re-run `npm run sync` after changing the catalog implementation. -// -// This family shares one implementation across its topics; the body lives at -// src/_shared/reversal.ts and is re-exported here so the public surface of -// this subpath is unchanged. -export * from "../../../_shared/reversal.ts"; +export type Pivot = { + kind: "high" | "low"; + index: number; + confirmation_index: number; + price: number; +}; + +export type Detection = { + pattern: string; + state: "searching" | "candidate" | "confirmed" | "rejected"; + reason: string; + event: Record | null; + events: Record[]; + pivots: Pivot[]; + parameters: Record; +}; + +const PATTERNS: Record; side: "top" | "bottom" }> = { + double_top: { types: ["high", "low", "high"], side: "top" }, + double_bottom: { types: ["low", "high", "low"], side: "bottom" }, + triple_top: { types: ["high", "low", "high", "low", "high"], side: "top" }, + triple_bottom: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, + head_and_shoulders: { types: ["high", "low", "high", "low", "high"], side: "top" }, + inverse_head_and_shoulders: { types: ["low", "high", "low", "high", "low"], side: "bottom" }, +}; + +const DEFAULTS: Record = { + pivot_left: 2, pivot_right: 2, min_swing_bars: 5, max_pattern_bars: 40, + max_confirmation_bars: 15, trend_lookback: 6, level_tolerance: 0.025, + shoulder_tolerance: 0.025, min_retracement: 0.05, head_margin: 0.05, + min_prior_trend: 0.03, break_buffer: 0, +}; + +function validated(close: number[], pattern: string, overrides: Record) { + if (!(pattern in PATTERNS)) throw new Error(`unsupported pattern: ${pattern}`); + if (!Array.isArray(close) || close.length === 0) throw new Error("close must be a non-empty array"); + const values = close.map((value) => { + if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) { + throw new Error("close values must be finite and strictly positive"); + } + return value; + }); + for (const key of Object.keys(overrides)) { + if (!(key in DEFAULTS)) throw new Error(`unknown parameter: ${key}`); + } + const params = { ...DEFAULTS, ...overrides }; + for (const key of ["pivot_left", "pivot_right", "min_swing_bars", "max_pattern_bars", "max_confirmation_bars", "trend_lookback"]) { + if (!Number.isInteger(params[key]) || params[key] < 1) throw new Error(`${key} must be a positive integer`); + } + for (const key of ["level_tolerance", "shoulder_tolerance", "min_retracement", "head_margin", "min_prior_trend", "break_buffer"]) { + if (!Number.isFinite(params[key]) || params[key] < 0) throw new Error(`${key} must be finite and nonnegative`); + } + if (params.level_tolerance >= 1 || params.shoulder_tolerance >= 1) throw new Error("similarity tolerances must be below 1"); + return { values, params }; +} + +export function confirmedPivots(close: number[], left = 2, right = 2): Pivot[] { + const { values, params } = validated(close, "double_top", { pivot_left: left, pivot_right: right }); + const pivots: Pivot[] = []; + for (let index = params.pivot_left; index < values.length - params.pivot_right; index += 1) { + const center = values[index]; + const neighbors = values.slice(index - params.pivot_left, index).concat(values.slice(index + 1, index + params.pivot_right + 1)); + const kind = neighbors.every((value) => center > value) ? "high" : neighbors.every((value) => center < value) ? "low" : null; + if (kind) pivots.push({ kind, index, confirmation_index: index + params.pivot_right, price: center }); + } + return pivots; +} + +function spread(values: number[]) { + const mean = values.reduce((a, b) => a + b, 0) / values.length; + return (Math.max(...values) - Math.min(...values)) / mean; +} + +function line(a: Pivot, b: Pivot, index: number) { + if (a.index === b.index) return a.price; + return a.price + ((b.price - a.price) / (b.index - a.index)) * (index - a.index); +} + +function metrics(pattern: string, pivots: Pivot[]) { + const prices = pivots.map((pivot) => pivot.price); + let tests: number[], retracements: number[], headDominance: number | null = null; + if (prices.length === 3) { + tests = [prices[0], prices[2]]; + const mean = (tests[0] + tests[1]) / 2; + retracements = [PATTERNS[pattern].side === "top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean]; + } else { + tests = pattern.startsWith("triple_") ? [prices[0], prices[2], prices[4]] : [prices[0], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + retracements = PATTERNS[pattern].side === "top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (pattern.includes("head_and_shoulders")) { + headDominance = PATTERNS[pattern].side === "top" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + } + } + const mean = tests.reduce((a, b) => a + b, 0) / tests.length; + return { + test_mean: mean, + level_spread: spread(tests), + retracement_min: Math.min(...retracements), + head_dominance: headDominance, + formation_bars: pivots.at(-1)!.index - pivots[0].index, + min_separation: Math.min(...pivots.slice(1).map((pivot, index) => pivot.index - pivots[index].index)), + }; +} + +function shape(pattern: string, pivots: Pivot[], params: Record) { + const prices = pivots.map((pivot) => pivot.price); + if (pattern === "double_top" || pattern === "double_bottom") { + const outer = [prices[0], prices[2]]; + if (spread(outer) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1]] }; + const mean = (outer[0] + outer[1]) / 2; + const retracement = pattern === "double_top" ? (mean - prices[1]) / mean : (prices[1] - mean) / mean; + if (retracement < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1]] }; + } + if (pattern === "triple_top" || pattern === "triple_bottom") { + const tests = [prices[0], prices[2], prices[4]]; + const mean = tests.reduce((a, b) => a + b, 0) / 3; + if (spread(tests) > params.level_tolerance) return { valid: false, reason: "outer-level-mismatch", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "triple_top" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; + } + const shoulders = [prices[0], prices[4]]; + const mean = (shoulders[0] + shoulders[1]) / 2; + if (spread(shoulders) > params.shoulder_tolerance) return { valid: false, reason: "shoulder-mismatch", anchors: [pivots[1], pivots[3]] }; + const dominant = pattern === "head_and_shoulders" ? (prices[2] - mean) / mean : (mean - prices[2]) / mean; + if (dominant < params.head_margin) return { valid: false, reason: "head-not-dominant", anchors: [pivots[1], pivots[3]] }; + const retracements = pattern === "head_and_shoulders" + ? [(mean - prices[1]) / mean, (mean - prices[3]) / mean] + : [(prices[1] - mean) / mean, (prices[3] - mean) / mean]; + if (Math.min(...retracements) < params.min_retracement) return { valid: false, reason: "retracement-too-shallow", anchors: [pivots[1], pivots[3]] }; + return { valid: true, reason: "geometry-valid", anchors: [pivots[1], pivots[3]] }; +} + +function evaluation(close: number[], pattern: string, pivots: Pivot[], params: Record): Record { + const spec = PATTERNS[pattern]; + const first = pivots[0], last = pivots[pivots.length - 1]; + const base = { + pattern, pivot_indices: pivots.map((p) => p.index), pivot_prices: pivots.map((p) => p.price), + pivot_types: pivots.map((p) => p.kind), candidate_available_index: Math.max(...pivots.map((p) => p.confirmation_index)), + confirmation_index: null, neckline: null, metrics: metrics(pattern, pivots), + }; + if (pivots.slice(1).some((p, i) => p.index - pivots[i].index < params.min_swing_bars)) return { ...base, state: "rejected", reason: "pivots-too-close" }; + if (last.index - first.index > params.max_pattern_bars) return { ...base, state: "rejected", reason: "formation-too-wide" }; + if (first.index < params.trend_lookback) return { ...base, state: "rejected", reason: "insufficient-prior-context" }; + const prior = close[first.index - params.trend_lookback]; + const priorMove = spec.side === "top" ? (first.price - prior) / first.price : (prior - first.price) / first.price; + const baseWithTrend = { ...base, prior_move: priorMove }; + if (priorMove < params.min_prior_trend) return { ...baseWithTrend, state: "rejected", reason: "prior-trend-too-weak" }; + const geometry = shape(pattern, pivots, params); + if (!geometry.valid) return { ...baseWithTrend, state: "rejected", reason: geometry.reason }; + const start = baseWithTrend.candidate_available_index; + const deadline = last.index + params.max_confirmation_bars; + for (let index = start; index <= Math.min(close.length - 1, deadline); index += 1) { + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], index); + const broken = spec.side === "top" ? close[index] < neckline * (1 - params.break_buffer) : close[index] > neckline * (1 + params.break_buffer); + if (broken) return { ...baseWithTrend, state: "confirmed", reason: "neckline-break-confirmed", confirmation_index: index, neckline, direction: spec.side === "top" ? "bearish" : "bullish" }; + } + const neckline = geometry.anchors.length === 1 ? geometry.anchors[0].price : line(geometry.anchors[0], geometry.anchors[1], close.length - 1); + if (close.length - 1 > deadline) return { ...baseWithTrend, state: "rejected", reason: "confirmation-window-expired", neckline }; + return { ...baseWithTrend, state: "candidate", reason: "geometry-valid-awaiting-neckline-break", neckline }; +} + +export function detectReversal(close: number[], pattern: string, overrides: Record = {}): Detection { + const { values, params } = validated(close, pattern, overrides); + const pivots = confirmedPivots(values, params.pivot_left, params.pivot_right); + const expected = PATTERNS[pattern].types; + const evaluations: Record[] = []; + for (let start = 0; start <= pivots.length - expected.length; start += 1) { + const window = pivots.slice(start, start + expected.length); + if (window.every((pivot, index) => pivot.kind === expected[index])) evaluations.push(evaluation(values, pattern, window, params)); + } + const confirmed = evaluations.filter((item) => item.state === "confirmed"); + const candidates = evaluations.filter((item) => item.state === "candidate"); + const rejected = evaluations.filter((item) => item.state === "rejected"); + const selected = confirmed.at(-1) ?? candidates.at(-1) ?? rejected.at(-1) ?? null; + return { + pattern, + state: (selected?.state as Detection["state"]) ?? "searching", + reason: (selected?.reason as string) ?? "required confirmed pivot sequence not yet available", + event: selected, + events: confirmed, + pivots, + parameters: params, + }; +} + +export function traceReversal(close: number[], pattern: string, overrides: Record = {}) { + validated(close, pattern, overrides); + return close.map((value, index) => { + const result = detectReversal(close.slice(0, index + 1), pattern, overrides); + const event = result.event; + return { + index, close: value, state: result.state, reason: result.reason, pivot_count: result.pivots.length, + pivot_indices: (event?.pivot_indices as number[]) ?? [], pivot_prices: (event?.pivot_prices as number[]) ?? [], + candidate_available_index: (event?.candidate_available_index as number | null) ?? null, + neckline: (event?.neckline as number | null) ?? null, + confirmation_index: (event?.confirmation_index as number | null) ?? null, + metrics: (event?.metrics as Record) ?? null, + prior_move: (event?.prior_move as number | null) ?? null, + known_pivots: result.pivots.map((pivot) => ({ ...pivot })), + confirmed: result.state === "confirmed", + }; + }); +} + +export function tripleTop( + close: number[], + params: Record = {}, +): Detection { + return detectReversal(close, "triple_top", params); +} diff --git a/src/geometric-chart-patterns/reversal-structures/triple-top/index.ts b/src/geometric-chart-patterns/reversal-structures/triple-top/index.ts index 9ffd19f..682cf96 100644 --- a/src/geometric-chart-patterns/reversal-structures/triple-top/index.ts +++ b/src/geometric-chart-patterns/reversal-structures/triple-top/index.ts @@ -2,7 +2,7 @@ * Triple Top * * Topic D08-F02-A03 · Geometric Chart Patterns / Reversal Structures · difficulty 3 - * Shape: record-transform · entry: triple_top() + * Shape: record-transform · entry: tripleTop() * Article: https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-top/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { triple_top as run } from "./impl.ts"; +export { tripleTop as run } from "./impl.ts"; export const meta = { id: "D08-F02-A03", @@ -22,7 +22,7 @@ export const meta = { family: "Reversal Structures", difficulty: 3, archetype: "record-transform", - entry: "triple_top", + entry: "tripleTop", path: "geometric-chart-patterns/reversal-structures/triple-top", articleUrl: "https://thefintechbuilder.com/geometric-chart-patterns/reversal-structures/triple-top/", repoUrl: null, diff --git a/src/technical-indicators/momentum/connors-rsi/index.ts b/src/technical-indicators/momentum/connors-rsi/index.ts index 00d92a5..d3cad73 100644 --- a/src/technical-indicators/momentum/connors-rsi/index.ts +++ b/src/technical-indicators/momentum/connors-rsi/index.ts @@ -2,7 +2,7 @@ * Connors RSI * * Topic D07-F03-A08 · Technical Indicators / Momentum · difficulty 4 - * Shape: series-transform · entry: connors_rsi() + * Shape: series-transform · entry: connorsRsi() * Article: https://thefintechbuilder.com/technical-indicators/momentum/connors-rsi/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { connors_rsi as run } from "./impl.ts"; +export { connorsRsi as run } from "./impl.ts"; export const meta = { id: "D07-F03-A08", @@ -22,7 +22,7 @@ export const meta = { family: "Momentum", difficulty: 4, archetype: "series-transform", - entry: "connors_rsi", + entry: "connorsRsi", path: "technical-indicators/momentum/connors-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/connors-rsi/", repoUrl: null, diff --git a/src/technical-indicators/momentum/stochastic-rsi/index.ts b/src/technical-indicators/momentum/stochastic-rsi/index.ts index 142d46c..06c30cc 100644 --- a/src/technical-indicators/momentum/stochastic-rsi/index.ts +++ b/src/technical-indicators/momentum/stochastic-rsi/index.ts @@ -2,7 +2,7 @@ * Stochastic RSI * * Topic D07-F03-A03 · Technical Indicators / Momentum · difficulty 3 - * Shape: series-transform · entry: stochastic_rsi() + * Shape: series-transform · entry: stochasticRsi() * Article: https://thefintechbuilder.com/technical-indicators/momentum/stochastic-rsi/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { stochastic_rsi as run } from "./impl.ts"; +export { stochasticRsi as run } from "./impl.ts"; export const meta = { id: "D07-F03-A03", @@ -22,7 +22,7 @@ export const meta = { family: "Momentum", difficulty: 3, archetype: "series-transform", - entry: "stochastic_rsi", + entry: "stochasticRsi", path: "technical-indicators/momentum/stochastic-rsi", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/stochastic-rsi/", repoUrl: null, diff --git a/src/technical-indicators/momentum/ultimate-oscillator/index.ts b/src/technical-indicators/momentum/ultimate-oscillator/index.ts index 00aa3c0..06393e5 100644 --- a/src/technical-indicators/momentum/ultimate-oscillator/index.ts +++ b/src/technical-indicators/momentum/ultimate-oscillator/index.ts @@ -2,7 +2,7 @@ * Ultimate Oscillator * * Topic D07-F03-A06 · Technical Indicators / Momentum · difficulty 3 - * Shape: series-transform · entry: ultimate_oscillator() + * Shape: series-transform · entry: ultimateOscillator() * Article: https://thefintechbuilder.com/technical-indicators/momentum/ultimate-oscillator/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { ultimate_oscillator as run } from "./impl.ts"; +export { ultimateOscillator as run } from "./impl.ts"; export const meta = { id: "D07-F03-A06", @@ -22,7 +22,7 @@ export const meta = { family: "Momentum", difficulty: 3, archetype: "series-transform", - entry: "ultimate_oscillator", + entry: "ultimateOscillator", path: "technical-indicators/momentum/ultimate-oscillator", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/ultimate-oscillator/", repoUrl: null, diff --git a/src/technical-indicators/momentum/williams-r/index.ts b/src/technical-indicators/momentum/williams-r/index.ts index e1fda6d..f98f633 100644 --- a/src/technical-indicators/momentum/williams-r/index.ts +++ b/src/technical-indicators/momentum/williams-r/index.ts @@ -2,7 +2,7 @@ * Williams %R * * Topic D07-F03-A04 · Technical Indicators / Momentum · difficulty 2 - * Shape: series-transform · entry: williams_r() + * Shape: series-transform · entry: williamsR() * Article: https://thefintechbuilder.com/technical-indicators/momentum/williams-r/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { williams_r as run } from "./impl.ts"; +export { williamsR as run } from "./impl.ts"; export const meta = { id: "D07-F03-A04", @@ -22,7 +22,7 @@ export const meta = { family: "Momentum", difficulty: 2, archetype: "series-transform", - entry: "williams_r", + entry: "williamsR", path: "technical-indicators/momentum/williams-r", articleUrl: "https://thefintechbuilder.com/technical-indicators/momentum/williams-r/", repoUrl: null, diff --git a/src/technical-indicators/trend-systems/adx/impl.ts b/src/technical-indicators/trend-systems/adx/impl.ts index 9ba125d..8815bbf 100644 --- a/src/technical-indicators/trend-systems/adx/impl.ts +++ b/src/technical-indicators/trend-systems/adx/impl.ts @@ -26,7 +26,7 @@ throw new TypeError(`${name} must contain only finite numbers`); throw new RangeError("close must lie inside each high-low range"); } } -function directional_movement(high: number[], low: number[], close: number[], period = 14) { +function directionalMovement(high: number[], low: number[], close: number[], period = 14) { validateHLC(high, low, close); if (!Number.isInteger(period) || period < 1) throw new RangeError("period must be a positive integer"); const size = high.length; @@ -69,7 +69,7 @@ function directional_movement(high: number[], low: number[], close: number[], pe return { true_range, plus_dm, minus_dm, smoothed_tr, smoothed_plus_dm, smoothed_minus_dm, atr, plus_di, minus_di, dx }; } export function adx(high: number[], low: number[], close: number[], period = 14) { - const movement = directional_movement(high, low, close, period); + const movement = directionalMovement(high, low, close, period); const values: Numeric[] = Array(high.length).fill(null); const first = 2 * period - 1; if (high.length > first) { diff --git a/src/technical-indicators/trend-systems/directional-movement/impl.ts b/src/technical-indicators/trend-systems/directional-movement/impl.ts index ed3e2fa..f7d4467 100644 --- a/src/technical-indicators/trend-systems/directional-movement/impl.ts +++ b/src/technical-indicators/trend-systems/directional-movement/impl.ts @@ -26,7 +26,7 @@ throw new TypeError(`${name} must contain only finite numbers`); throw new RangeError("close must lie inside each high-low range"); } } -export function directional_movement(high: number[], low: number[], close: number[], period = 14) { +export function directionalMovement(high: number[], low: number[], close: number[], period = 14) { validateHLC(high, low, close); if (!Number.isInteger(period) || period < 1) throw new RangeError("period must be a positive integer"); const size = high.length; diff --git a/src/technical-indicators/trend-systems/directional-movement/index.ts b/src/technical-indicators/trend-systems/directional-movement/index.ts index 84ce058..381fb17 100644 --- a/src/technical-indicators/trend-systems/directional-movement/index.ts +++ b/src/technical-indicators/trend-systems/directional-movement/index.ts @@ -2,7 +2,7 @@ * Directional Movement: From True Range to +DI, −DI, and DX * * Topic D07-F02-A04 · Technical Indicators / Trend Systems · difficulty 3 - * Shape: series-transform · entry: directional_movement() + * Shape: series-transform · entry: directionalMovement() * Article: https://thefintechbuilder.com/technical-indicators/trend-systems/directional-movement/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { directional_movement as run } from "./impl.ts"; +export { directionalMovement as run } from "./impl.ts"; export const meta = { id: "D07-F02-A04", @@ -22,7 +22,7 @@ export const meta = { family: "Trend Systems", difficulty: 3, archetype: "series-transform", - entry: "directional_movement", + entry: "directionalMovement", path: "technical-indicators/trend-systems/directional-movement", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/directional-movement/", repoUrl: null, diff --git a/src/technical-indicators/trend-systems/parabolic-sar/impl.ts b/src/technical-indicators/trend-systems/parabolic-sar/impl.ts index a1b14a5..92f31cd 100644 --- a/src/technical-indicators/trend-systems/parabolic-sar/impl.ts +++ b/src/technical-indicators/trend-systems/parabolic-sar/impl.ts @@ -26,7 +26,7 @@ throw new TypeError(`${name} must contain only finite numbers`); throw new RangeError("close must lie inside each high-low range"); } } -export function parabolic_sar(high: number[], low: number[], initialDirection: "long" | "short" = "long", accelerationStep = 0.02, accelerationMax = 0.2) { +export function parabolicSar(high: number[], low: number[], initialDirection: "long" | "short" = "long", accelerationStep = 0.02, accelerationMax = 0.2) { validateHL(high, low); if (high.length < 2) throw new RangeError("at least two observations are required"); if (!["long", "short"].includes(initialDirection)) throw new RangeError("initialDirection must be long or short"); diff --git a/src/technical-indicators/trend-systems/parabolic-sar/index.ts b/src/technical-indicators/trend-systems/parabolic-sar/index.ts index 2945b02..d2d3fd0 100644 --- a/src/technical-indicators/trend-systems/parabolic-sar/index.ts +++ b/src/technical-indicators/trend-systems/parabolic-sar/index.ts @@ -2,7 +2,7 @@ * Parabolic SAR: Audit the Stop, Extreme Point, and Acceleration Factor * * Topic D07-F02-A07 · Technical Indicators / Trend Systems · difficulty 3 - * Shape: series-transform · entry: parabolic_sar() + * Shape: series-transform · entry: parabolicSar() * Article: https://thefintechbuilder.com/technical-indicators/trend-systems/parabolic-sar/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { parabolic_sar as run } from "./impl.ts"; +export { parabolicSar as run } from "./impl.ts"; export const meta = { id: "D07-F02-A07", @@ -22,7 +22,7 @@ export const meta = { family: "Trend Systems", difficulty: 3, archetype: "series-transform", - entry: "parabolic_sar", + entry: "parabolicSar", path: "technical-indicators/trend-systems/parabolic-sar", articleUrl: "https://thefintechbuilder.com/technical-indicators/trend-systems/parabolic-sar/", repoUrl: null, diff --git a/src/technical-indicators/volatility-and-channels/atr/impl.ts b/src/technical-indicators/volatility-and-channels/atr/impl.ts index 55d4959..1636443 100644 --- a/src/technical-indicators/volatility-and-channels/atr/impl.ts +++ b/src/technical-indicators/volatility-and-channels/atr/impl.ts @@ -4,8 +4,8 @@ function finite(v:number[],n:string){if(!Array.isArray(v)||!v.length||v.some(x=>!Number.isFinite(x)))throw new Error(`${n} must contain finite numbers`)} function hlc(h:number[],l:number[],c:number[]){finite(h,"high");finite(l,"low");finite(c,"close");if(h.length!==l.length||h.length!==c.length)throw new Error("high, low, and close lengths must match");if(h.some((x,i)=>xx))throw new Error("each bar requires low <= close <= high")} -export function true_range(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} +export function trueRange(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} function period(v:number,n="period"){if(!Number.isInteger(v)||v<1)throw new Error(`${n} must be a positive integer`)} -export function average_true_range(high:number[],low:number[],close:number[],p=14){period(p);const tr=true_range(high,low,close).true_range,atr:(number|null)[]=Array(tr.length).fill(null);if(tr.length>=p){let value=tr.slice(0,p).reduce((a,b)=>a+b,0)/p;atr[p-1]=value;for(let i=p;i=p){let value=tr.slice(0,p).reduce((a,b)=>a+b,0)/p;atr[p-1]=value;for(let i=p;ia+b,0)/p;middle[i]=m;stddev[i]=Math.sqrt(w.reduce((a,b)=>a+(b-m)**2,0)/p)}return{middle,stddev}} -export function bollinger_bands(close:number[],p=20,multiplier=2){if(!Number.isFinite(multiplier)||multiplier<=0)throw new Error("multiplier must be finite and positive");const r=rolling(close,p),upper:(number|null)[]=Array(close.length).fill(null),lower:(number|null)[]=Array(close.length).fill(null),percent_b:(number|null)[]=Array(close.length).fill(null);for(let i=0;ia+b,0)/p;middle[i]=m;stddev[i]=Math.sqrt(w.reduce((a,b)=>a+(b-m)**2,0)/p)}return{middle,stddev}} -export function bollinger_bands(close:number[],p=20,multiplier=2){if(!Number.isFinite(multiplier)||multiplier<=0)throw new Error("multiplier must be finite and positive");const r=rolling(close,p),upper:(number|null)[]=Array(close.length).fill(null),lower:(number|null)[]=Array(close.length).fill(null),percent_b:(number|null)[]=Array(close.length).fill(null);for(let i=0;i0)bandwidth[i]=100*((b.upper[i] as number)-(b.lower[i] as number))/(b.middle[i] as number);return{middle:b.middle,stddev:b.stddev,upper:b.upper,lower:b.lower,bandwidth}} +export function bollingerBandwidth(close:number[],p=20,multiplier=2){const b=bollingerBands(close,p,multiplier),bandwidth:(number|null)[]=Array(close.length).fill(null);for(let i=0;i0)bandwidth[i]=100*((b.upper[i] as number)-(b.lower[i] as number))/(b.middle[i] as number);return{middle:b.middle,stddev:b.stddev,upper:b.upper,lower:b.lower,bandwidth}} diff --git a/src/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.ts b/src/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.ts index c595a69..293fac3 100644 --- a/src/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.ts +++ b/src/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.ts @@ -2,7 +2,7 @@ * Bollinger BandWidth * * Topic D07-F04-A06 · Technical Indicators / Volatility and Channels · difficulty 3 - * Shape: series-transform · entry: bollinger_bandwidth() + * Shape: series-transform · entry: bollingerBandwidth() * Article: https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bandwidth/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { bollinger_bandwidth as run } from "./impl.ts"; +export { bollingerBandwidth as run } from "./impl.ts"; export const meta = { id: "D07-F04-A06", @@ -22,7 +22,7 @@ export const meta = { family: "Volatility and Channels", difficulty: 3, archetype: "series-transform", - entry: "bollinger_bandwidth", + entry: "bollingerBandwidth", path: "technical-indicators/volatility-and-channels/bollinger-bandwidth", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/bollinger-bandwidth/", repoUrl: null, diff --git a/src/technical-indicators/volatility-and-channels/donchian-channels/impl.ts b/src/technical-indicators/volatility-and-channels/donchian-channels/impl.ts index a97d633..fce2c6a 100644 --- a/src/technical-indicators/volatility-and-channels/donchian-channels/impl.ts +++ b/src/technical-indicators/volatility-and-channels/donchian-channels/impl.ts @@ -4,4 +4,4 @@ function finite(v:number[],n:string){if(!Array.isArray(v)||!v.length||v.some(x=>!Number.isFinite(x)))throw new Error(`${n} must contain finite numbers`)} function period(v:number,n="period"){if(!Number.isInteger(v)||v<1)throw new Error(`${n} must be a positive integer`)} -export function donchian_channels(high:number[],low:number[],p=20){finite(high,"high");finite(low,"low");period(p);if(high.length!==low.length||high.some((h,i)=>h= low");const upper:(number|null)[]=Array(high.length).fill(null),lower:(number|null)[]=Array(high.length).fill(null),middle:(number|null)[]=Array(high.length).fill(null),width:(number|null)[]=Array(high.length).fill(null);for(let i=p-1;ih= low");const upper:(number|null)[]=Array(high.length).fill(null),lower:(number|null)[]=Array(high.length).fill(null),middle:(number|null)[]=Array(high.length).fill(null),width:(number|null)[]=Array(high.length).fill(null);for(let i=p-1;i!Number.isFinite(x)))throw new Error(`${n} must contain finite numbers`)} function hlc(h:number[],l:number[],c:number[]){finite(h,"high");finite(l,"low");finite(c,"close");if(h.length!==l.length||h.length!==c.length)throw new Error("high, low, and close lengths must match");if(h.some((x,i)=>xx))throw new Error("each bar requires low <= close <= high")} -export function true_range(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} +export function trueRange(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} function period(v:number,n="period"){if(!Number.isInteger(v)||v<1)throw new Error(`${n} must be a positive integer`)} -export function average_true_range(high:number[],low:number[],close:number[],p=14){period(p);const tr=true_range(high,low,close).true_range,atr:(number|null)[]=Array(tr.length).fill(null);if(tr.length>=p){let value=tr.slice(0,p).reduce((a,b)=>a+b,0)/p;atr[p-1]=value;for(let i=p;i=p){let value=tr.slice(0,p).reduce((a,b)=>a+b,0)/p;atr[p-1]=value;for(let i=p;ia+b,0)/p;out[p-1]=value;const alpha=2/(p+1);for(let i=p;i!Number.isFinite(x)))throw new Error(`${n} must contain finite numbers`)} function hlc(h:number[],l:number[],c:number[]){finite(h,"high");finite(l,"low");finite(c,"close");if(h.length!==l.length||h.length!==c.length)throw new Error("high, low, and close lengths must match");if(h.some((x,i)=>xx))throw new Error("each bar requires low <= close <= high")} -export function true_range(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} +export function trueRange(high:number[],low:number[],close:number[]){hlc(high,low,close);const true_range:number[]=[],high_low:number[]=[],high_gap:(number|null)[]=[],low_gap:(number|null)[]=[],driver:string[]=[];for(let i=0;iy[0]>x[0]?y:x);true_range.push(best[0]);high_low.push(a);high_gap.push(b);low_gap.push(c);driver.push(best[1])}return{true_range,high_low,high_gap,low_gap,driver}} diff --git a/src/technical-indicators/volatility-and-channels/true-range/index.ts b/src/technical-indicators/volatility-and-channels/true-range/index.ts index 8ecd6fc..3e74c1c 100644 --- a/src/technical-indicators/volatility-and-channels/true-range/index.ts +++ b/src/technical-indicators/volatility-and-channels/true-range/index.ts @@ -2,7 +2,7 @@ * True Range * * Topic D07-F04-A01 · Technical Indicators / Volatility and Channels · difficulty 1 - * Shape: series-transform · entry: true_range() + * Shape: series-transform · entry: trueRange() * Article: https://thefintechbuilder.com/technical-indicators/volatility-and-channels/true-range/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { true_range as run } from "./impl.ts"; +export { trueRange as run } from "./impl.ts"; export const meta = { id: "D07-F04-A01", @@ -22,7 +22,7 @@ export const meta = { family: "Volatility and Channels", difficulty: 1, archetype: "series-transform", - entry: "true_range", + entry: "trueRange", path: "technical-indicators/volatility-and-channels/true-range", articleUrl: "https://thefintechbuilder.com/technical-indicators/volatility-and-channels/true-range/", repoUrl: null, diff --git a/src/technical-indicators/volume-indicators/accumulation-distribution-line/index.ts b/src/technical-indicators/volume-indicators/accumulation-distribution-line/index.ts index cb76277..0efcf26 100644 --- a/src/technical-indicators/volume-indicators/accumulation-distribution-line/index.ts +++ b/src/technical-indicators/volume-indicators/accumulation-distribution-line/index.ts @@ -2,7 +2,7 @@ * Accumulation/Distribution Line * * Topic D07-F05-A02 · Technical Indicators / Volume Indicators · difficulty 2 - * Shape: series-transform · entry: accumulation_distribution_line() + * Shape: series-transform · entry: accumulationDistributionLine() * Article: https://thefintechbuilder.com/technical-indicators/volume-indicators/accumulation-distribution-line/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { accumulation_distribution_line as run } from "./impl.ts"; +export { accumulationDistributionLine as run } from "./impl.ts"; export const meta = { id: "D07-F05-A02", @@ -22,7 +22,7 @@ export const meta = { family: "Volume Indicators", difficulty: 2, archetype: "series-transform", - entry: "accumulation_distribution_line", + entry: "accumulationDistributionLine", path: "technical-indicators/volume-indicators/accumulation-distribution-line", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/accumulation-distribution-line/", repoUrl: null, diff --git a/src/technical-indicators/volume-indicators/chaikin-money-flow/index.ts b/src/technical-indicators/volume-indicators/chaikin-money-flow/index.ts index 35d45e6..fc67c61 100644 --- a/src/technical-indicators/volume-indicators/chaikin-money-flow/index.ts +++ b/src/technical-indicators/volume-indicators/chaikin-money-flow/index.ts @@ -2,7 +2,7 @@ * Chaikin Money Flow * * Topic D07-F05-A03 · Technical Indicators / Volume Indicators · difficulty 3 - * Shape: series-transform · entry: chaikin_money_flow() + * Shape: series-transform · entry: chaikinMoneyFlow() * Article: https://thefintechbuilder.com/technical-indicators/volume-indicators/chaikin-money-flow/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { chaikin_money_flow as run } from "./impl.ts"; +export { chaikinMoneyFlow as run } from "./impl.ts"; export const meta = { id: "D07-F05-A03", @@ -22,7 +22,7 @@ export const meta = { family: "Volume Indicators", difficulty: 3, archetype: "series-transform", - entry: "chaikin_money_flow", + entry: "chaikinMoneyFlow", path: "technical-indicators/volume-indicators/chaikin-money-flow", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/chaikin-money-flow/", repoUrl: null, diff --git a/src/technical-indicators/volume-indicators/force-index/index.ts b/src/technical-indicators/volume-indicators/force-index/index.ts index 5632bdc..0516b39 100644 --- a/src/technical-indicators/volume-indicators/force-index/index.ts +++ b/src/technical-indicators/volume-indicators/force-index/index.ts @@ -2,7 +2,7 @@ * Force Index * * Topic D07-F05-A06 · Technical Indicators / Volume Indicators · difficulty 3 - * Shape: series-transform · entry: force_index() + * Shape: series-transform · entry: forceIndex() * Article: https://thefintechbuilder.com/technical-indicators/volume-indicators/force-index/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { force_index as run } from "./impl.ts"; +export { forceIndex as run } from "./impl.ts"; export const meta = { id: "D07-F05-A06", @@ -22,7 +22,7 @@ export const meta = { family: "Volume Indicators", difficulty: 3, archetype: "series-transform", - entry: "force_index", + entry: "forceIndex", path: "technical-indicators/volume-indicators/force-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/force-index/", repoUrl: null, diff --git a/src/technical-indicators/volume-indicators/money-flow-index/index.ts b/src/technical-indicators/volume-indicators/money-flow-index/index.ts index 775d2c9..934292a 100644 --- a/src/technical-indicators/volume-indicators/money-flow-index/index.ts +++ b/src/technical-indicators/volume-indicators/money-flow-index/index.ts @@ -2,7 +2,7 @@ * Money Flow Index * * Topic D07-F05-A04 · Technical Indicators / Volume Indicators · difficulty 3 - * Shape: series-transform · entry: money_flow_index() + * Shape: series-transform · entry: moneyFlowIndex() * Article: https://thefintechbuilder.com/technical-indicators/volume-indicators/money-flow-index/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { money_flow_index as run } from "./impl.ts"; +export { moneyFlowIndex as run } from "./impl.ts"; export const meta = { id: "D07-F05-A04", @@ -22,7 +22,7 @@ export const meta = { family: "Volume Indicators", difficulty: 3, archetype: "series-transform", - entry: "money_flow_index", + entry: "moneyFlowIndex", path: "technical-indicators/volume-indicators/money-flow-index", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/money-flow-index/", repoUrl: null, diff --git a/src/technical-indicators/volume-indicators/volume-price-trend/index.ts b/src/technical-indicators/volume-indicators/volume-price-trend/index.ts index 607ea76..20510cc 100644 --- a/src/technical-indicators/volume-indicators/volume-price-trend/index.ts +++ b/src/technical-indicators/volume-indicators/volume-price-trend/index.ts @@ -2,7 +2,7 @@ * Volume Price Trend * * Topic D07-F05-A05 · Technical Indicators / Volume Indicators · difficulty 2 - * Shape: series-transform · entry: volume_price_trend() + * Shape: series-transform · entry: volumePriceTrend() * Article: https://thefintechbuilder.com/technical-indicators/volume-indicators/volume-price-trend/ */ // GENERATED by scripts/sync.mjs — do not edit. @@ -10,7 +10,7 @@ // Re-run `npm run sync` after changing the catalog implementation. export * from "./impl.ts"; -export { volume_price_trend as run } from "./impl.ts"; +export { volumePriceTrend as run } from "./impl.ts"; export const meta = { id: "D07-F05-A05", @@ -22,7 +22,7 @@ export const meta = { family: "Volume Indicators", difficulty: 2, archetype: "series-transform", - entry: "volume_price_trend", + entry: "volumePriceTrend", path: "technical-indicators/volume-indicators/volume-price-trend", articleUrl: "https://thefintechbuilder.com/technical-indicators/volume-indicators/volume-price-trend/", repoUrl: null, diff --git a/test/_examples.json b/test/_examples.json index fd0f3ff..ad304a7 100644 --- a/test/_examples.json +++ b/test/_examples.json @@ -27000,6 +27000,133 @@ ] } }, + "D02-F02-A04": { + "args": [ + { + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "asOf": "2026-03-16T20:10:00Z", + "methodology": { + "id": "SYNTHETIC-NET-RETURN-POLICY", + "version": "1.0", + "sourceId": "SYNTHETIC-METHODOLOGY-NOTE", + "classificationMode": "source-designated", + "priceAdjustmentCashBasis": "net", + "referenceAnchor": "previous-session-official-close", + "outputDecimals": 8 + }, + "eventRevisions": [ + { + "revisionId": "R1", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 15, + "currency": "EUR", + "announcedAt": "2026-02-02T12:00:00Z", + "availableAt": "2026-02-02T12:05:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R1" + }, + { + "revisionId": "R2", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 16, + "currency": "EUR", + "announcedAt": "2026-02-05T14:00:00Z", + "availableAt": "2026-02-05T14:10:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R2" + } + ], + "referencePrice": { + "value": 100, + "currency": "USD", + "anchorType": "previous-session-official-close", + "anchorAt": "2026-03-13T20:00:00Z", + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-OFFICIAL-CLOSE" + }, + "precedingActions": [ + { + "actionId": "SYNTHETIC-2-FOR-1-SPLIT", + "actionOrder": 10, + "priceFactor": 0.5, + "perShareAmountFactor": 0.5, + "effectiveAt": "2026-03-16T13:30:00Z", + "observedAt": "2026-02-01T10:00:00Z", + "availableAt": "2026-02-01T10:05:00Z", + "sourceId": "SYNTHETIC-ACTION-SOURCE" + } + ], + "fxRate": { + "baseCurrency": "EUR", + "quoteCurrency": "USD", + "rate": 1.1, + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-FX-CLOSE" + }, + "taxProfile": { + "withholdingRate": 0.25, + "jurisdiction": "SYNTHETIC-JURISDICTION", + "investorCategory": "SYNTHETIC-NONRESIDENT", + "observedAt": "2026-01-05T09:00:00Z", + "availableAt": "2026-01-05T09:05:00Z", + "sourceId": "SYNTHETIC-TAX-RULE" + }, + "exPriceObservation": { + "value": 43.75, + "currency": "USD", + "observedAt": "2026-03-16T20:00:00Z", + "availableAt": "2026-03-16T20:00:05Z", + "sourceId": "SYNTHETIC-EX-CLOSE" + } + } + ], + "value": { + "eventState": "effective", + "selectedRevisionId": "R2", + "classificationDecision": "special", + "classificationReason": "source designation: special", + "adjustmentApplied": true, + "referencePriceOnEventBasis": 50, + "grossDividendOnEventBasis": 8.8, + "netDividendOnEventBasis": 6.6, + "adjustmentCashAmount": 6.6, + "theoreticalExPrice": 43.4, + "adjustmentFactor": 0.868, + "grossDistributionYield": 0.176, + "methodologyId": "SYNTHETIC-NET-RETURN-POLICY", + "methodologyVersion": "1.0", + "lineage": { + "eventSourceId": "SYNTHETIC-ISSUER-NOTICE-R2", + "eventAvailableAt": "2026-02-05T14:10:00Z", + "referenceSourceId": "SYNTHETIC-OFFICIAL-CLOSE", + "methodologySourceId": "SYNTHETIC-METHODOLOGY-NOTE", + "fxSourceId": "SYNTHETIC-FX-CLOSE", + "taxSourceId": "SYNTHETIC-TAX-RULE", + "exPriceSourceId": "SYNTHETIC-EX-CLOSE" + }, + "returns": { + "priceReturn": -0.125, + "grossTotalReturn": 0.051, + "netTotalReturn": 0.007, + "adjustedPriceReturn": 0.00806452 + } + } + }, "D02-F02-A05": { "args": [ { @@ -93704,8 +93831,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F02-A02": { "args": [ @@ -93890,8 +94016,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F02-A03": { "args": [ @@ -94100,8 +94225,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F02-A04": { "args": [ @@ -94310,8 +94434,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F02-A05": { "args": [ @@ -94520,8 +94643,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F02-A06": { "args": [ @@ -94730,8 +94852,7 @@ "min_prior_trend": 0.03, "break_buffer": 0 } - }, - "derived": true + } }, "D08-F05-A01": { "args": [ diff --git a/test/_manifest.json b/test/_manifest.json index 94ca469..9eb1283 100644 --- a/test/_manifest.json +++ b/test/_manifest.json @@ -8,13 +8,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "dataStatus", "canonicalRule", "config", @@ -28,13 +30,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "canonicalRule", "explanation", "config", @@ -48,13 +52,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "description", "canonicalRule", "config", @@ -68,13 +74,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "sourceType", "config", "trades", @@ -91,13 +99,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "evidenceClass", "config", "openingThreshold", @@ -113,13 +123,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "evidenceClass", "config", "trades", @@ -133,13 +145,15 @@ "entry": "constructBars", "archetype": "tape-aggregate", "fixture": "D01-F01-A07.json", - "convention": "none", + "convention": "A", "entryParams": [ "trades", "config" ], "fixtureKeys": [ "topicId", + "input", + "expected", "dataLicense", "config", "trades", @@ -475,11 +489,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "note", "ratioConvention", "ratio", @@ -495,12 +512,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F01-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ "topicId", + "input", + "expected", "source", "headline", "note" @@ -512,19 +531,22 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F01-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ "topicId", + "input", + "expected", "evidenceClass", "warning", "crspConvention", "crspBaseDate", "crspExdt", "crspFacpr", - "rows" + "rows", + "fixtureLicense" ] }, { @@ -533,15 +555,19 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F01-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "notice", "crspField", "crspBasisDate", - "rows" + "rows", + "evidenceScope" ] }, { @@ -550,15 +576,19 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F02-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "event", "sourcedFacts", "derivation", - "interpretation" + "interpretation", + "caseLabel" ] }, { @@ -567,11 +597,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F02-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "description", "parentCumPriceUSD", "children", @@ -590,11 +623,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F02-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "classification", "ratesNewSharesPerOld", "shareFactors", @@ -612,11 +648,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F02-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "rawData" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "notice", "selectedRevision", "steps", @@ -629,15 +668,19 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F02-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "payload" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "label", "marketData", "observedReturns", - "usTaxIllustration" + "usTaxIllustration", + "caseLabel" ] }, { @@ -646,18 +689,22 @@ "entry": "resolveIdentifier", "archetype": "row-classify", "fixture": "D02-F03-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "notice", "query", "validAt", "knowledgeAt", "selectedRevision", "excluded", - "result" + "result", + "license" ] }, { @@ -666,16 +713,19 @@ "entry": "resolveTickerChain", "archetype": "row-classify", "fixture": "D02-F03-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ "topicId", + "input", + "expected", "synthetic", "question", "answer", - "counterfactualKnowledgeCutoff" + "counterfactualKnowledgeCutoff", + "license" ] }, { @@ -684,14 +734,18 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F03-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "notice", "query", - "result" + "result", + "license" ] }, { @@ -700,11 +754,14 @@ "entry": "resolveMerger", "archetype": "row-classify", "fixture": "D02-F03-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "payload" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "label", "license", "inputs", @@ -719,12 +776,14 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F03-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ "topicId", + "input", + "expected", "case", "license", "arithmetic", @@ -737,15 +796,19 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F04-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "description", "fixture", "queryName", - "result" + "result", + "evidenceNote" ] }, { @@ -754,11 +817,14 @@ "entry": "guardSurvivorship", "archetype": "row-classify", "fixture": "D02-F04-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "input" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "note", "effectiveAt", "knownAt", @@ -770,7 +836,8 @@ "historicalEqualWeightedReturn", "laterRosterSubsetEqualWeightedReturn", "signedDifference", - "interpretation" + "interpretation", + "evidenceNote" ] }, { @@ -779,16 +846,19 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F04-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ "topicId", + "input", + "expected", "description", "beforeLocalIngestion", "afterLocalIngestion", - "boundary" + "boundary", + "evidenceNote" ] }, { @@ -797,17 +867,20 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D02-F04-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "data" ], "fixtureKeys": [ "topicId", + "input", + "expected", "source", "case", "historicalFacts", "syntheticAvailabilityAssumptions", - "derivedDifference" + "derivedDifference", + "evidenceNote" ] }, { @@ -1468,12 +1541,14 @@ "entry": "calculateNetAdvances", "archetype": "record-transform", "fixture": "D04-F01-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "request" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "fixture", "query_before_correction", "query_after_correction", @@ -1486,14 +1561,15 @@ "entry": "calculateAdvanceDeclineRatio", "archetype": "record-transform", "fixture": "D04-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "snapshot" ], "fixtureKeys": [ - "topic_id", + "topicId", "synthetic", "input", + "expected", "derivation" ] }, @@ -1503,13 +1579,16 @@ "entry": "calculateCumulativeAdvanceDeclineLine", "archetype": "record-transform", "fixture": "D04-F01-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "contract", "events", "knowledgeCutoff" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "data_class", "seed", "original", @@ -1523,12 +1602,15 @@ "entry": "calculateNormalizedAdLine", "archetype": "record-transform", "fixture": "D04-F01-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "options" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "classification", "initial_value", "scale", @@ -1543,12 +1625,14 @@ "entry": "evaluateAbsoluteBreadthIndex", "archetype": "snapshot-evaluate", "fixture": "D04-F01-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "request" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "label", "note", "rows" @@ -1560,12 +1644,14 @@ "entry": "calculateMcClellanValues", "archetype": "record-transform", "fixture": "D04-F02-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "netAdvances" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "metric", "convention", "series_identity", @@ -1579,13 +1665,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F02-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "cutoff" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "first_ready", "stress_path", @@ -1598,13 +1686,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F02-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "cutoff" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "first_ready", "stress_path", @@ -1617,13 +1707,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F02-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "cutoff" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "first_ready", "stress_path", @@ -1636,13 +1728,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F02-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "cutoff" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "first_ready", "stress_path", @@ -1655,13 +1749,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F02-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "cutoff" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "first_ready", "stress_path", @@ -1674,13 +1770,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F03-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1693,13 +1791,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F03-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1712,13 +1812,15 @@ "entry": "calculate", "archetype": "record-transform", "fixture": "D04-F03-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "records", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1731,13 +1833,15 @@ "entry": "evaluateSnapshot", "archetype": "snapshot-evaluate", "fixture": "D04-F03-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "snapshot", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1750,13 +1854,15 @@ "entry": "evaluateSnapshot", "archetype": "snapshot-evaluate", "fixture": "D04-F03-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "snapshot", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1769,13 +1875,15 @@ "entry": "evaluateSnapshot", "archetype": "snapshot-evaluate", "fixture": "D04-F03-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "snapshot", "decisionTime" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "source_class", "canonical_display_state", "formula", @@ -1993,7 +2101,7 @@ "entry": "analyzeCandle", "archetype": "record-transform", "fixture": "D06-F01-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "candle", "directionEpsilon" @@ -2001,6 +2109,7 @@ "fixtureKeys": [ "topic_id", "input", + "expected", "direction_epsilon", "output", "checks" @@ -2012,7 +2121,7 @@ "entry": "classifyBody", "archetype": "row-classify", "fixture": "D06-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "observation", "priorClosedBodies", @@ -2021,6 +2130,7 @@ "fixtureKeys": [ "topic_id", "input", + "expected", "derivation", "comparison_only" ] @@ -2490,16 +2600,17 @@ "entry": "calculateSma", "archetype": "series-transform", "fixture": "D07-F01-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "window" ], "fixtureKeys": [ - "topic_id", + "topicId", "title", "window", "values", + "input", "expected", "steps" ] @@ -2510,13 +2621,15 @@ "entry": "calculateEma", "archetype": "series-transform", "fixture": "D07-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "span" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "metric", "convention", "series_identity", @@ -2529,18 +2642,19 @@ "entry": "calculateWma", "archetype": "series-transform", "fixture": "D07-F01-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "window" ], "fixtureKeys": [ - "topic_id", + "topicId", "title", "window", "weights_oldest_to_newest", "denominator", "values", + "input", "expected", "steps" ] @@ -2551,13 +2665,15 @@ "entry": "calculateRma", "archetype": "series-transform", "fixture": "D07-F01-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "period" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "series_id", "unit", "frequency", @@ -2574,13 +2690,15 @@ "entry": "calculateDemaComponents", "archetype": "series-transform", "fixture": "D07-F01-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "span" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "convention", "observations" ] @@ -2591,13 +2709,15 @@ "entry": "calculateTemaComponents", "archetype": "series-transform", "fixture": "D07-F01-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "span" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "series_id", "unit", "frequency", @@ -2616,20 +2736,18 @@ "entry": "calculateHullMa", "archetype": "series-transform", "fixture": "D07-F01-A07.json", - "convention": "none", + "convention": "C", "entryParams": [ "values", "window" ], "fixtureKeys": [ - "topic_id", - "window", - "rounding_policy", - "half_length", - "root_length", - "values", - "first_ready_observation", - "first_ready_components" + "topicId", + "bars", + "canonical_parameters", + "checkpoints", + "contract", + "cases" ] }, { @@ -2638,7 +2756,7 @@ "entry": "calculateKama", "archetype": "series-transform", "fixture": "D07-F01-A08.json", - "convention": "none", + "convention": "C", "entryParams": [ "values", "efficiencyPeriod", @@ -2646,12 +2764,12 @@ "slowPeriod" ], "fixtureKeys": [ - "classification", - "values", - "parameters", - "internal_seed", - "rows", - "rounding" + "topicId", + "bars", + "canonical_parameters", + "checkpoints", + "contract", + "cases" ] }, { @@ -2660,18 +2778,26 @@ "entry": "mama", "archetype": "series-transform", "fixture": "D07-F01-A09.json", - "convention": "none", + "convention": "C", "entryParams": [ "values", "fastLimit", "slowLimit" ], "fixtureKeys": [ - "classification", - "fixture", - "parameters", + "topicId", + "bars", + "canonical_parameters", "checkpoints", - "independent_reference" + "topic_id", + "variant", + "generated_at", + "parameters", + "lookback", + "processing_start", + "rounding", + "source_and_license", + "scenarios" ] }, { @@ -2680,7 +2806,7 @@ "entry": "macd", "archetype": "series-transform", "fixture": "D07-F02-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "fastSpan", @@ -2688,6 +2814,9 @@ "signalSpan" ], "fixtureKeys": [ + "topicId", + "input", + "expected", "title", "spans", "alphas", @@ -2743,7 +2872,7 @@ { "id": "D07-F02-A04", "path": "technical-indicators/trend-systems/directional-movement", - "entry": "directional_movement", + "entry": "directionalMovement", "archetype": "series-transform", "fixture": "D07-F02-A04.json", "convention": "C", @@ -2815,7 +2944,7 @@ { "id": "D07-F02-A07", "path": "technical-indicators/trend-systems/parabolic-sar", - "entry": "parabolic_sar", + "entry": "parabolicSar", "archetype": "series-transform", "fixture": "D07-F02-A07.json", "convention": "C", @@ -2911,7 +3040,7 @@ { "id": "D07-F03-A03", "path": "technical-indicators/momentum/stochastic-rsi", - "entry": "stochastic_rsi", + "entry": "stochasticRsi", "archetype": "series-transform", "fixture": "D07-F03-A03.json", "convention": "C", @@ -2936,7 +3065,7 @@ { "id": "D07-F03-A04", "path": "technical-indicators/momentum/williams-r", - "entry": "williams_r", + "entry": "williamsR", "archetype": "series-transform", "fixture": "D07-F03-A04.json", "convention": "C", @@ -2985,7 +3114,7 @@ { "id": "D07-F03-A06", "path": "technical-indicators/momentum/ultimate-oscillator", - "entry": "ultimate_oscillator", + "entry": "ultimateOscillator", "archetype": "series-transform", "fixture": "D07-F03-A06.json", "convention": "C", @@ -3034,7 +3163,7 @@ { "id": "D07-F03-A08", "path": "technical-indicators/momentum/connors-rsi", - "entry": "connors_rsi", + "entry": "connorsRsi", "archetype": "series-transform", "fixture": "D07-F03-A08.json", "convention": "C", @@ -3058,7 +3187,7 @@ { "id": "D07-F04-A01", "path": "technical-indicators/volatility-and-channels/true-range", - "entry": "true_range", + "entry": "trueRange", "archetype": "series-transform", "fixture": "D07-F04-A01.json", "convention": "C", @@ -3080,7 +3209,7 @@ { "id": "D07-F04-A02", "path": "technical-indicators/volatility-and-channels/atr", - "entry": "average_true_range", + "entry": "averageTrueRange", "archetype": "series-transform", "fixture": "D07-F04-A02.json", "convention": "C", @@ -3103,7 +3232,7 @@ { "id": "D07-F04-A03", "path": "technical-indicators/volatility-and-channels/bollinger-bands", - "entry": "bollinger_bands", + "entry": "bollingerBands", "archetype": "series-transform", "fixture": "D07-F04-A03.json", "convention": "C", @@ -3125,7 +3254,7 @@ { "id": "D07-F04-A04", "path": "technical-indicators/volatility-and-channels/keltner-channels", - "entry": "keltner_channels", + "entry": "keltnerChannels", "archetype": "series-transform", "fixture": "D07-F04-A04.json", "convention": "C", @@ -3150,7 +3279,7 @@ { "id": "D07-F04-A05", "path": "technical-indicators/volatility-and-channels/donchian-channels", - "entry": "donchian_channels", + "entry": "donchianChannels", "archetype": "series-transform", "fixture": "D07-F04-A05.json", "convention": "C", @@ -3172,7 +3301,7 @@ { "id": "D07-F04-A06", "path": "technical-indicators/volatility-and-channels/bollinger-bandwidth", - "entry": "bollinger_bandwidth", + "entry": "bollingerBandwidth", "archetype": "series-transform", "fixture": "D07-F04-A06.json", "convention": "C", @@ -3218,7 +3347,7 @@ { "id": "D07-F05-A02", "path": "technical-indicators/volume-indicators/accumulation-distribution-line", - "entry": "accumulation_distribution_line", + "entry": "accumulationDistributionLine", "archetype": "series-transform", "fixture": "D07-F05-A02.json", "convention": "C", @@ -3244,7 +3373,7 @@ { "id": "D07-F05-A03", "path": "technical-indicators/volume-indicators/chaikin-money-flow", - "entry": "chaikin_money_flow", + "entry": "chaikinMoneyFlow", "archetype": "series-transform", "fixture": "D07-F05-A03.json", "convention": "C", @@ -3270,7 +3399,7 @@ { "id": "D07-F05-A04", "path": "technical-indicators/volume-indicators/money-flow-index", - "entry": "money_flow_index", + "entry": "moneyFlowIndex", "archetype": "series-transform", "fixture": "D07-F05-A04.json", "convention": "C", @@ -3296,7 +3425,7 @@ { "id": "D07-F05-A05", "path": "technical-indicators/volume-indicators/volume-price-trend", - "entry": "volume_price_trend", + "entry": "volumePriceTrend", "archetype": "series-transform", "fixture": "D07-F05-A05.json", "convention": "C", @@ -3320,7 +3449,7 @@ { "id": "D07-F05-A06", "path": "technical-indicators/volume-indicators/force-index", - "entry": "force_index", + "entry": "forceIndex", "archetype": "series-transform", "fixture": "D07-F05-A06.json", "convention": "C", @@ -3347,7 +3476,7 @@ "entry": "detectCausalPivots", "archetype": "row-classify", "fixture": "D08-F01-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "bars", "leftSpan", @@ -3355,7 +3484,9 @@ "minSeparation" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "formulae", @@ -3372,14 +3503,16 @@ "entry": "zigzagSegment", "archetype": "record-transform", "fixture": "D08-F01-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "closes", "threshold", "minBars" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "formulae", @@ -3396,14 +3529,16 @@ "entry": "clusterPivotLevels", "archetype": "record-transform", "fixture": "D08-F01-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "pivots", "epsBps", "minTouches" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "formulae", @@ -3420,7 +3555,7 @@ "entry": "fitRobustTrendline", "archetype": "record-transform", "fixture": "D08-F01-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "pivots", "kind", @@ -3429,7 +3564,9 @@ "maxPoints" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "formulae", @@ -3443,61 +3580,79 @@ { "id": "D08-F02-A01", "path": "geometric-chart-patterns/reversal-structures/double-top", - "entry": "double_top", + "entry": "doubleTop", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { "id": "D08-F02-A02", "path": "geometric-chart-patterns/reversal-structures/double-bottom", - "entry": "double_bottom", + "entry": "doubleBottom", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { "id": "D08-F02-A03", "path": "geometric-chart-patterns/reversal-structures/triple-top", - "entry": "triple_top", + "entry": "tripleTop", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { "id": "D08-F02-A04", "path": "geometric-chart-patterns/reversal-structures/triple-bottom", - "entry": "triple_bottom", + "entry": "tripleBottom", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { "id": "D08-F02-A05", "path": "geometric-chart-patterns/reversal-structures/head-and-shoulders", - "entry": "head_and_shoulders", + "entry": "headAndShoulders", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { "id": "D08-F02-A06", "path": "geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders", - "entry": "inverse_head_and_shoulders", + "entry": "inverseHeadAndShoulders", "archetype": "record-transform", "fixture": null, "convention": "none", - "entryParams": [], + "entryParams": [ + "close", + "params" + ], "fixtureKeys": [] }, { @@ -3794,7 +3949,7 @@ "entry": "forecastAutoReg", "archetype": "record-transform", "fixture": "D09-F02-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "ar", @@ -3802,7 +3957,9 @@ "horizon" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -3819,7 +3976,7 @@ "entry": "forecastARMA", "archetype": "record-transform", "fixture": "D09-F02-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "ar", @@ -3828,7 +3985,9 @@ "horizon" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -3845,7 +4004,7 @@ "entry": "forecastARIMA", "archetype": "record-transform", "fixture": "D09-F02-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "ar", @@ -3855,7 +4014,9 @@ "horizon" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -3872,7 +4033,7 @@ "entry": "forecastSARIMAX", "archetype": "record-transform", "fixture": "D09-F02-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "exog", @@ -3889,7 +4050,9 @@ "horizon" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -3906,7 +4069,7 @@ "entry": "forecastHoltWintersAdditive", "archetype": "record-transform", "fixture": "D09-F02-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "alpha", @@ -3919,7 +4082,9 @@ "initialSeasonals" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -3936,14 +4101,16 @@ "entry": "forecastTheta", "archetype": "record-transform", "fixture": "D09-F02-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "values", "alpha", "horizon" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "selected_variant", "values", @@ -4029,13 +4196,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A01.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", @@ -4049,13 +4218,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A02.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", @@ -4069,13 +4240,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A03.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", @@ -4089,13 +4262,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A04.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", @@ -4109,13 +4284,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A05.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", @@ -4129,13 +4306,15 @@ "entry": "runFilter", "archetype": "record-transform", "fixture": "D09-F04-A06.json", - "convention": "none", + "convention": "A", "entryParams": [ "observations", "config" ], "fixtureKeys": [ - "topic_id", + "topicId", + "input", + "expected", "classification", "configuration", "observations", diff --git a/test/conformance.test.ts b/test/conformance.test.ts index fcca7aa..bef0ed1 100644 --- a/test/conformance.test.ts +++ b/test/conformance.test.ts @@ -84,6 +84,52 @@ function closeEnough(actual: unknown, expected: unknown, label: string): void { assert.deepStrictEqual(actual, expected, label); } +/** + * Assert a published expected value recursively. Object fixtures may document + * a deliberate subset; arrays are complete ordered values. + */ +function expectedSubset(actual: unknown, expected: unknown, label: string): void { + if (Array.isArray(expected)) { + assert.ok(Array.isArray(actual), `${label}: expected an array, got ${typeof actual}`); + assert.equal(actual.length, expected.length, `${label}: array length`); + expected.forEach((want, index) => expectedSubset(actual[index], want, `${label}[${index}]`)); + return; + } + if (expected !== null && typeof expected === "object") { + assert.ok(actual !== null && typeof actual === "object", `${label}: expected an object, got ${typeof actual}`); + for (const [field, want] of Object.entries(expected as Record)) { + assert.ok(Object.hasOwn(actual as object, field), `${label}: missing field \`${field}\``); + expectedSubset((actual as Record)[field], want, `${label}.${field}`); + } + return; + } + closeEnough(actual, expected, label); +} + +const flattenedName = (name: string) => name.toLowerCase().replace(/[-_]/g, ""); + +/** Bind Convention A's named input object to a multi-argument entry function. */ +function conventionAArgs(topic: ManifestTopic, input: unknown): unknown[] { + const cloned = structuredClone(input); + if (topic.entryParams.length <= 1 || cloned === null || typeof cloned !== "object" || Array.isArray(cloned)) { + return [cloned]; + } + + const named = cloned as Record; + const supplied = Object.entries(named); + const hasDeclaredName = topic.entryParams.some((name) => + supplied.some(([key]) => flattenedName(key) === flattenedName(name)), + ); + if (!hasDeclaredName) return [cloned]; + + const args = topic.entryParams.map((name) => { + if (Object.hasOwn(named, name)) return named[name]; + return supplied.find(([key]) => flattenedName(key) === flattenedName(name))?.[1]; + }); + while (args.length && args.at(-1) === undefined) args.pop(); + return args; +} + describe("conformance: catalog worked examples", () => { test("the catalog still ships fixtures to check", () => { assert.ok(runnable.length > 0, "no runnable fixtures found — did scripts/sync.mjs run?"); @@ -94,16 +140,11 @@ describe("conformance: catalog worked examples", () => { describe("A · { input, expected }", () => { for (const topic of runnable.filter((t) => t.convention === "A")) { test(`${topic.id} — ${topic.path}`, async () => { - const fixture = loadFixture(topic) as { input: unknown; expected: Record }; + const fixture = loadFixture(topic) as { input: unknown; expected: unknown }; const run = await loadEntry(topic); - // structuredClone guards against an implementation mutating its input. - const actual = run(structuredClone(fixture.input)) as Record; - assert.ok(actual !== null && typeof actual === "object", `${topic.id} returned ${typeof actual}`); - // `expected` is asserted as a subset: some fixtures document only the - // fields the article walks through, not the whole payload. - for (const [field, want] of Object.entries(fixture.expected)) { - assert.deepStrictEqual(actual[field], want, `${topic.id}: field \`${field}\``); - } + // conventionAArgs clones input to guard against implementations that mutate it. + const actual = run(...conventionAArgs(topic, fixture.input)); + expectedSubset(actual, fixture.expected, topic.id); }); } }); @@ -173,7 +214,7 @@ describe("conformance: catalog worked examples", () => { /** Price-series columns a parameter name can be bound to. */ const SERIES_PARAMS = new Set(["open", "high", "low", "close", "volume", "values", "price", "prices"]); - const flatten = (name: string) => name.toLowerCase().replace(/[-_]/g, ""); + const flatten = flattenedName; /** * Fixtures express parameters either as an object or as prose — several write diff --git a/test/fixtures/D01-F01-A01.json b/test/fixtures/D01-F01-A01.json index 535fbf9..f1f88be 100644 --- a/test/fixtures/D01-F01-A01.json +++ b/test/fixtures/D01-F01-A01.json @@ -1,5 +1,81 @@ { "topicId": "D01-F01-A01", + "input": { + "trades": [ + {"tradeId": "W1", "timestamp": "2026-01-05T14:30:00.000Z", "session": "S1", "symbol": "SYNTH", "price": 100.0, "volume": 10, "currency": "USD"}, + {"tradeId": "W2", "timestamp": "2026-01-05T14:30:59.999Z", "session": "S1", "symbol": "SYNTH", "price": 101.0, "volume": 5, "currency": "USD"}, + {"tradeId": "W3", "timestamp": "2026-01-05T14:31:00.000Z", "session": "S1", "symbol": "SYNTH", "price": 99.0, "volume": 8, "currency": "USD"}, + {"tradeId": "W4", "timestamp": "2026-01-05T14:33:15.000Z", "session": "S1", "symbol": "SYNTH", "price": 102.0, "volume": 2, "currency": "USD"} + ], + "config": { + "intervalSeconds": 60, + "sessionStarts": {"S1": "2026-01-05T14:30:00.000Z"}, + "emptyBarPolicy": "omit", + "closePartial": true + } + }, + "expected": [ + { + "barIndex": 0, + "session": "S1", + "intervalIndex": 0, + "startTime": "2026-01-05T14:30:00.000Z", + "endTime": "2026-01-05T14:31:00.000Z", + "firstTradeTime": "2026-01-05T14:30:00.000Z", + "lastTradeTime": "2026-01-05T14:30:59.999Z", + "open": 100, + "high": 101, + "low": 100, + "close": 101, + "volume": 15, + "dollarValue": 1505, + "tickCount": 2, + "firstTradeId": "W1", + "lastTradeId": "W2", + "emptyIntervalsBefore": 0, + "closeReason": "interval" + }, + { + "barIndex": 1, + "session": "S1", + "intervalIndex": 1, + "startTime": "2026-01-05T14:31:00.000Z", + "endTime": "2026-01-05T14:32:00.000Z", + "firstTradeTime": "2026-01-05T14:31:00.000Z", + "lastTradeTime": "2026-01-05T14:31:00.000Z", + "open": 99, + "high": 99, + "low": 99, + "close": 99, + "volume": 8, + "dollarValue": 792, + "tickCount": 1, + "firstTradeId": "W3", + "lastTradeId": "W3", + "emptyIntervalsBefore": 0, + "closeReason": "interval" + }, + { + "barIndex": 2, + "session": "S1", + "intervalIndex": 3, + "startTime": "2026-01-05T14:33:00.000Z", + "endTime": "2026-01-05T14:34:00.000Z", + "firstTradeTime": "2026-01-05T14:33:15.000Z", + "lastTradeTime": "2026-01-05T14:33:15.000Z", + "open": 102, + "high": 102, + "low": 102, + "close": 102, + "volume": 2, + "dollarValue": 204, + "tickCount": 1, + "firstTradeId": "W4", + "lastTradeId": "W4", + "emptyIntervalsBefore": 1, + "closeReason": "stream_end" + } + ], "dataStatus": "synthetic", "canonicalRule": "k(t)=floor((t-a_s)/Delta), I_(s,k)=[a_s+k*Delta, a_s+(k+1)*Delta)", "config": { diff --git a/test/fixtures/D01-F01-A02.json b/test/fixtures/D01-F01-A02.json index a4ffb2a..be0e0ca 100644 --- a/test/fixtures/D01-F01-A02.json +++ b/test/fixtures/D01-F01-A02.json @@ -1,5 +1,25 @@ { "topicId": "D01-F01-A02", + "input": { + "trades": [ + {"tradeId":"E01","timestamp":"2026-01-05T14:30:00.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.00,"volume":10,"currency":"USD"}, + {"tradeId":"E02","timestamp":"2026-01-05T14:30:01.000Z","session":"2026-01-05","symbol":"SYNTH","price":101.00,"volume":20,"currency":"USD"}, + {"tradeId":"E03","timestamp":"2026-01-05T14:30:02.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.00,"volume":15,"currency":"USD"}, + {"tradeId":"E04","timestamp":"2026-01-05T14:30:03.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.00,"volume":25,"currency":"USD"}, + {"tradeId":"E05","timestamp":"2026-01-05T14:30:04.000Z","session":"2026-01-05","symbol":"SYNTH","price":102.00,"volume":10,"currency":"USD"}, + {"tradeId":"E06","timestamp":"2026-01-05T14:30:05.000Z","session":"2026-01-05","symbol":"SYNTH","price":101.00,"volume":30,"currency":"USD"}, + {"tradeId":"E07","timestamp":"2026-01-05T14:30:06.000Z","session":"2026-01-05","symbol":"SYNTH","price":103.00,"volume":5,"currency":"USD"} + ], + "config": { + "targetTicks": 3, + "closePartial": true + } + }, + "expected": [ + {"barIndex":0,"session":"2026-01-05","startTime":"2026-01-05T14:30:00.000Z","endTime":"2026-01-05T14:30:02.000Z","lastTradeTime":"2026-01-05T14:30:02.000Z","open":100.0,"high":101.0,"low":99.0,"close":99.0,"volume":45.0,"dollarValue":4505.0,"tickCount":3,"firstTradeId":"E01","lastTradeId":"E03","closeReason":"threshold"}, + {"barIndex":1,"session":"2026-01-05","startTime":"2026-01-05T14:30:03.000Z","endTime":"2026-01-05T14:30:05.000Z","lastTradeTime":"2026-01-05T14:30:05.000Z","open":100.0,"high":102.0,"low":100.0,"close":101.0,"volume":65.0,"dollarValue":6550.0,"tickCount":3,"firstTradeId":"E04","lastTradeId":"E06","closeReason":"threshold"}, + {"barIndex":2,"session":"2026-01-05","startTime":"2026-01-05T14:30:06.000Z","endTime":"2026-01-05T14:30:06.000Z","lastTradeTime":"2026-01-05T14:30:06.000Z","open":103.0,"high":103.0,"low":103.0,"close":103.0,"volume":5.0,"dollarValue":515.0,"tickCount":1,"firstTradeId":"E07","lastTradeId":"E07","closeReason":"stream_end"} + ], "canonicalRule": "T_j=\\sum_{i\\in B_j}1,\\qquad \\text{close }B_j\\text{ when }T_j=N", "explanation": "With targetTicks=3, E01-E03 and E04-E06 close complete bars. E07 is emitted only under the explicit closePartial=true stream-end policy.", "config": { diff --git a/test/fixtures/D01-F01-A03.json b/test/fixtures/D01-F01-A03.json index 8106d5b..a7b6aed 100644 --- a/test/fixtures/D01-F01-A03.json +++ b/test/fixtures/D01-F01-A03.json @@ -1,5 +1,24 @@ { "topicId": "D01-F01-A03", + "input": { + "trades": [ + {"tradeId":"W001","timestamp":"2026-01-05T14:30:00.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.00,"volume":400,"currency":"USD"}, + {"tradeId":"W002","timestamp":"2026-01-05T14:30:01.000Z","session":"2026-01-05","symbol":"SYNTH","price":101.00,"volume":350,"currency":"USD"}, + {"tradeId":"W003","timestamp":"2026-01-05T14:30:02.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.00,"volume":500,"currency":"USD"}, + {"tradeId":"W004","timestamp":"2026-01-05T14:30:03.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.50,"volume":600,"currency":"USD"}, + {"tradeId":"W005","timestamp":"2026-01-05T14:30:04.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.50,"volume":400,"currency":"USD"}, + {"tradeId":"W006","timestamp":"2026-01-05T14:30:05.000Z","session":"2026-01-05","symbol":"SYNTH","price":101.00,"volume":250,"currency":"USD"} + ], + "config": { + "targetVolume": 1000, + "closePartial": true + } + }, + "expected": [ + {"barIndex":0,"session":"2026-01-05","startTime":"2026-01-05T14:30:00.000Z","endTime":"2026-01-05T14:30:02.000Z","lastTradeTime":"2026-01-05T14:30:02.000Z","open":100.0,"high":101.0,"low":99.0,"close":99.0,"volume":1250.0,"dollarValue":124850.0,"tickCount":3,"firstTradeId":"W001","lastTradeId":"W003","closeReason":"threshold"}, + {"barIndex":1,"session":"2026-01-05","startTime":"2026-01-05T14:30:03.000Z","endTime":"2026-01-05T14:30:04.000Z","lastTradeTime":"2026-01-05T14:30:04.000Z","open":99.5,"high":100.5,"low":99.5,"close":100.5,"volume":1000.0,"dollarValue":99900.0,"tickCount":2,"firstTradeId":"W004","lastTradeId":"W005","closeReason":"threshold"}, + {"barIndex":2,"session":"2026-01-05","startTime":"2026-01-05T14:30:05.000Z","endTime":"2026-01-05T14:30:05.000Z","lastTradeTime":"2026-01-05T14:30:05.000Z","open":101.0,"high":101.0,"low":101.0,"close":101.0,"volume":250.0,"dollarValue":25250.0,"tickCount":1,"firstTradeId":"W006","lastTradeId":"W006","closeReason":"stream_end"} + ], "description": "Synthetic six-trade example covering whole-trade overshoot, exact equality, and a final partial bar.", "canonicalRule": "V_j=\\sum_{i\\in B_j}v_i,\\qquad \\text{close }B_j\\text{ at the first }i\\text{ for which }V_j\\ge V^*", "config": { diff --git a/test/fixtures/D01-F01-A04.json b/test/fixtures/D01-F01-A04.json index 932d8fb..a083eeb 100644 --- a/test/fixtures/D01-F01-A04.json +++ b/test/fixtures/D01-F01-A04.json @@ -1,5 +1,57 @@ { "topicId": "D01-F01-A04", + "input": { + "trades": [ + { + "tradeId": "W1", + "timestamp": "2026-01-05T14:30:00.000Z", + "session": "2026-01-05", + "symbol": "SYNTH", + "price": 100, + "volume": 40, + "currency": "USD" + }, + { + "tradeId": "W2", + "timestamp": "2026-01-05T14:30:01.000Z", + "session": "2026-01-05", + "symbol": "SYNTH", + "price": 90, + "volume": 70, + "currency": "USD" + } + ], + "config": { + "targetDollar": 10000, + "currency": "USD", + "priceDecimals": 2, + "quantityDecimals": 0, + "closePartial": true + } + }, + "expected": [ + { + "barIndex": 0, + "session": "2026-01-05", + "symbol": "SYNTH", + "currency": "USD", + "startTime": "2026-01-05T14:30:00.000Z", + "endTime": "2026-01-05T14:30:01.000Z", + "lastTradeTime": "2026-01-05T14:30:01.000Z", + "open": 100, + "high": 100, + "low": 90, + "close": 90, + "volume": 110, + "dollarValue": 10300, + "targetDollar": 10000, + "excessDollar": 300, + "tickCount": 2, + "firstTradeId": "W1", + "lastTradeId": "W2", + "closeReason": "threshold" + } + ], "sourceType": "deterministic synthetic example", "config": { "targetDollar": 10000, diff --git a/test/fixtures/D01-F01-A05.json b/test/fixtures/D01-F01-A05.json index 6992c7d..4366d1f 100644 --- a/test/fixtures/D01-F01-A05.json +++ b/test/fixtures/D01-F01-A05.json @@ -1,5 +1,46 @@ { "topicId": "D01-F01-A05", + "input": { + "trades": [ + {"tradeId":"W1","timestamp":"2026-01-05T14:30:00.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.0,"volume":10,"currency":"USD"}, + {"tradeId":"W2","timestamp":"2026-01-05T14:30:01.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.0,"volume":10,"currency":"USD"}, + {"tradeId":"W3","timestamp":"2026-01-05T14:30:02.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.1,"volume":10,"currency":"USD"}, + {"tradeId":"W4","timestamp":"2026-01-05T14:30:03.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.05,"volume":10,"currency":"USD"}, + {"tradeId":"W5","timestamp":"2026-01-05T14:30:04.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.1,"volume":10,"currency":"USD"}, + {"tradeId":"W6","timestamp":"2026-01-05T14:30:05.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.15,"volume":10,"currency":"USD"} + ], + "config": { + "closePartial": true, + "initialTickSign": 1, + "initialExpectedTicks": 8, + "initialExpectedTickImbalance": 0.5, + "alphaTicks": 0.25, + "alphaTickImbalance": 0.5, + "thresholdFloor": 3, + "thresholdMultiplier": 1 + } + }, + "expected": [ + { + "barIndex": 0, + "session": "2026-01-05", + "startTime": "2026-01-05T14:30:00.000Z", + "endTime": "2026-01-05T14:30:05.000Z", + "lastTradeTime": "2026-01-05T14:30:05.000Z", + "open": 100, + "high": 100.15, + "low": 100, + "close": 100.15, + "volume": 60, + "dollarValue": 6004, + "tickCount": 6, + "firstTradeId": "W1", + "lastTradeId": "W6", + "closeReason": "threshold", + "imbalance": 4, + "threshold": 4 + } + ], "evidenceClass": "deterministic package derivation", "config": { "closePartial": true, diff --git a/test/fixtures/D01-F01-A06.json b/test/fixtures/D01-F01-A06.json index b2620ad..de4907f 100644 --- a/test/fixtures/D01-F01-A06.json +++ b/test/fixtures/D01-F01-A06.json @@ -1,5 +1,75 @@ { "topicId": "D01-F01-A06", + "input": { + "trades": [ + {"tradeId":"W01","timestamp":"2026-01-05T14:30:00.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.00,"volume":60,"currency":"USD"}, + {"tradeId":"W02","timestamp":"2026-01-05T14:30:00.000Z","session":"2026-01-05","symbol":"SYNTH","price":100.00,"volume":40,"currency":"USD"}, + {"tradeId":"W03","timestamp":"2026-01-05T14:30:01.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.99,"volume":70,"currency":"USD"}, + {"tradeId":"W04","timestamp":"2026-01-05T14:30:02.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.98,"volume":90,"currency":"USD"}, + {"tradeId":"W05","timestamp":"2026-01-05T14:30:03.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.98,"volume":50,"currency":"USD"}, + {"tradeId":"W06","timestamp":"2026-01-05T14:30:04.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.97,"volume":95,"currency":"USD"}, + {"tradeId":"W07","timestamp":"2026-01-05T14:30:05.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.98,"volume":80,"currency":"USD"}, + {"tradeId":"W08","timestamp":"2026-01-05T14:30:06.000Z","session":"2026-01-05","symbol":"SYNTH","price":99.99,"volume":55,"currency":"USD"} + ], + "config": { + "closePartial": true, + "initialTickSign": 1, + "initialExpectedTicks": 4, + "initialExpectedSignedVolume": 50, + "alphaTicks": 0.25, + "alphaSignedVolume": 0.25, + "thresholdFloorShares": 120, + "thresholdScale": 1 + } + }, + "expected": [ + { + "barIndex": 0, + "session": "2026-01-05", + "startTime": "2026-01-05T14:30:00.000Z", + "endTime": "2026-01-05T14:30:04.000Z", + "open": 100, + "high": 100, + "low": 99.97, + "close": 99.97, + "volume": 405, + "dollarValue": 40493.65, + "tickCount": 6, + "firstTradeId": "W01", + "lastTradeId": "W06", + "closeReason": "threshold", + "isComplete": true, + "signedVolume": -205, + "thresholdShares": 200, + "expectedTicksBefore": 4, + "expectedSignedVolumeBefore": 50, + "overshootShares": 5, + "thresholdMet": true + }, + { + "barIndex": 1, + "session": "2026-01-05", + "startTime": "2026-01-05T14:30:05.000Z", + "endTime": "2026-01-05T14:30:06.000Z", + "open": 99.98, + "high": 99.99, + "low": 99.98, + "close": 99.99, + "volume": 135, + "dollarValue": 13497.85, + "tickCount": 2, + "firstTradeId": "W07", + "lastTradeId": "W08", + "closeReason": "threshold", + "isComplete": true, + "signedVolume": 135, + "thresholdShares": 130.3125, + "expectedTicksBefore": 4.5, + "expectedSignedVolumeBefore": 28.95833333, + "overshootShares": 4.6875, + "thresholdMet": true + } + ], "evidenceClass": "synthetic mechanics example", "config": { "closePartial": true, diff --git a/test/fixtures/D01-F01-A07.json b/test/fixtures/D01-F01-A07.json index dabeeae..11966f7 100644 --- a/test/fixtures/D01-F01-A07.json +++ b/test/fixtures/D01-F01-A07.json @@ -1,5 +1,31 @@ { "topicId": "D01-F01-A07", + "input": { + "trades": [ + {"tradeId":"W01","timestamp":"2026-01-05T14:30:00.000Z","session":"S1","symbol":"SYNTH","price":100.00,"volume":10,"currency":"USD"}, + {"tradeId":"W02","timestamp":"2026-01-05T14:30:01.000Z","session":"S1","symbol":"SYNTH","price":100.00,"volume":20,"currency":"USD"}, + {"tradeId":"W03","timestamp":"2026-01-05T14:30:02.000Z","session":"S1","symbol":"SYNTH","price":99.90,"volume":15,"currency":"USD"}, + {"tradeId":"W04","timestamp":"2026-01-05T14:30:03.000Z","session":"S1","symbol":"SYNTH","price":100.00,"volume":25,"currency":"USD"}, + {"tradeId":"W05","timestamp":"2026-01-05T14:30:04.000Z","session":"S1","symbol":"SYNTH","price":100.00,"volume":10,"currency":"USD"}, + {"tradeId":"W06","timestamp":"2026-01-05T14:30:05.000Z","session":"S1","symbol":"SYNTH","price":99.90,"volume":12,"currency":"USD"}, + {"tradeId":"W07","timestamp":"2026-01-05T14:30:06.000Z","session":"S1","symbol":"SYNTH","price":99.90,"volume":18,"currency":"USD"}, + {"tradeId":"W08","timestamp":"2026-01-05T14:30:07.000Z","session":"S1","symbol":"SYNTH","price":99.80,"volume":14,"currency":"USD"} + ], + "config": { + "closePartial": true, + "initialTickSign": 1, + "initialExpectedTicks": 4, + "initialBuyProbability": 0.625, + "alphaTicks": 0.5, + "alphaBuyProbability": 0.5, + "thresholdFloorTicks": 2, + "thresholdMultiplier": 1 + } + }, + "expected": [ + {"firstTradeId":"W01","lastTradeId":"W04","tickCount":4,"buyTicks":3,"sellTicks":1,"dominantSide":"buy","thresholdTicks":2.5,"overshootTicks":0.5,"closeReason":"threshold"}, + {"firstTradeId":"W05","lastTradeId":"W08","tickCount":4,"buyTicks":1,"sellTicks":3,"dominantSide":"sell","thresholdTicks":2.75,"overshootTicks":0.25,"closeReason":"threshold"} + ], "dataLicense": "CC0-style synthetic teaching data; no real market event", "config": { "closePartial": true, diff --git a/test/fixtures/D02-F01-A02.json b/test/fixtures/D02-F01-A02.json index 47113d2..5c0a47c 100644 --- a/test/fixtures/D02-F01-A02.json +++ b/test/fixtures/D02-F01-A02.json @@ -1,9 +1,131 @@ { - "note": "Synthetic arithmetic using the sourced four-for-one ratio; values are not Apple market observations.", - "ratioConvention": "new_shares_per_old_share", - "ratio": "4 / 1", - "targetBasis": "pre-split share basis", - "boundary": "effectiveAt is inclusive", - "beforeBoundary": {"rawPrice": 120, "rawVolume": 1000, "adjustedPrice": 120, "adjustedVolume": 1000}, - "atBoundary": {"rawPrice": 30, "rawVolume": 4000, "priceFactor": 4, "quantityFactor": 0.25, "adjustedPrice": 120, "adjustedVolume": 1000} + "topicId": "D02-F01-A02", + "input": { + "targetBasisAt": "2020-08-30T23:59:59Z", + "knowledgeAt": "2020-09-02T00:00:00Z", + "roundDecimalPlaces": 6, + "observations": [ + { + "timestamp": "2020-08-28T20:00:00Z", + "price": 120, + "volume": 1000, + "sharesOutstanding": 1000000 + }, + { + "timestamp": "2020-08-31T00:00:00Z", + "price": 30, + "volume": 4000, + "sharesOutstanding": 4000000 + }, + { + "timestamp": "2020-09-01T00:00:00Z", + "price": 31, + "volume": 3600, + "sharesOutstanding": 4000000 + } + ], + "eventRevisions": [ + { + "eventId": "SYNTH-SPLIT-2020", + "revisionId": "SYNTH-SPLIT-2020-R1", + "supersedesRevisionId": null, + "publishedAt": "2020-07-30T20:30:00Z", + "effectiveAt": "2020-08-31T00:00:00Z", + "newShares": 4, + "oldShares": 1, + "status": "active", + "sourceId": "synthetic-fixture" + } + ] + }, + "expected": { + "basis": { + "targetBasisAt": "2020-08-30T23:59:59Z", + "knowledgeAt": "2020-09-02T00:00:00Z", + "ratioConvention": "new_shares_per_old_share", + "boundaryRule": "targetBasisAt \u003c effectiveAt \u003c= observation.timestamp", + "priceDirection": "multiply_post_boundary_values_to_earlier_basis", + "quantityDirection": "divide_post_boundary_share_quantities_to_earlier_basis", + "roundDecimalPlaces": 6 + }, + "selectedRevisions": [ + { + "eventId": "SYNTH-SPLIT-2020", + "revisionId": "SYNTH-SPLIT-2020-R1", + "supersedesRevisionId": null, + "publishedAt": "2020-07-30T20:30:00Z", + "effectiveAt": "2020-08-31T00:00:00Z", + "newShares": 4, + "oldShares": 1, + "status": "active", + "sourceId": "synthetic-fixture" + } + ], + "observations": [ + { + "timestamp": "2020-08-28T20:00:00Z", + "rawPrice": 120, + "adjustedPrice": 120, + "rawVolume": 1000, + "adjustedVolume": 1000, + "rawSharesOutstanding": 1000000, + "adjustedSharesOutstanding": 1000000, + "cumulativePriceFactor": 1, + "cumulativeQuantityFactor": 1, + "appliedEventIds": [ + + ] + }, + { + "timestamp": "2020-08-31T00:00:00Z", + "rawPrice": 30, + "adjustedPrice": 120, + "rawVolume": 4000, + "adjustedVolume": 1000, + "rawSharesOutstanding": 4000000, + "adjustedSharesOutstanding": 1000000, + "cumulativePriceFactor": 4, + "cumulativeQuantityFactor": 0.25, + "appliedEventIds": [ + "SYNTH-SPLIT-2020" + ] + }, + { + "timestamp": "2020-09-01T00:00:00Z", + "rawPrice": 31, + "adjustedPrice": 124, + "rawVolume": 3600, + "adjustedVolume": 900, + "rawSharesOutstanding": 4000000, + "adjustedSharesOutstanding": 1000000, + "cumulativePriceFactor": 4, + "cumulativeQuantityFactor": 0.25, + "appliedEventIds": [ + "SYNTH-SPLIT-2020" + ] + } + ], + "warnings": [ + "rounded outputs may not reverse exactly" + ] + }, + "note": "Synthetic arithmetic using the sourced four-for-one ratio; values are not Apple market observations.", + "ratioConvention": "new_shares_per_old_share", + "ratio": "4 / 1", + "targetBasis": "pre-split share basis", + "boundary": "effectiveAt is inclusive", + "beforeBoundary": { + "rawPrice": 120, + "rawVolume": 1000, + "adjustedPrice": 120, + "adjustedVolume": 1000 + }, + "atBoundary": { + "rawPrice": 30, + "rawVolume": 4000, + "priceFactor": 4, + "quantityFactor": 0.25, + "adjustedPrice": 120, + "adjustedVolume": 1000 + } } diff --git a/test/fixtures/D02-F01-A03.json b/test/fixtures/D02-F01-A03.json index 5c7d3b4..0375caa 100644 --- a/test/fixtures/D02-F01-A03.json +++ b/test/fixtures/D02-F01-A03.json @@ -1,13 +1,221 @@ { - "topicId": "D02-F01-A03", - "source": "../../tests/shared_fixture.json", - "headline": { - "priorClose": 102, - "exDateClose": 99, - "grossDividend": 3, - "priceReturn": -0.029411764706, - "grossTotalReturn": 0, - "backwardFactor": 0.970588235294 - }, - "note": "All values are synthetic. The factor uses the ex-date close and is applied only to earlier observations." + "topicId": "D02-F01-A03", + "input": { + "asOf": "2026-01-09T23:00:00Z", + "returnVariant": "gross", + "priceCurrency": "USD", + "anchorBasis": "latest_raw_close", + "specialDistributionPolicy": "exclude", + "observations": [ + { + "date": "2026-01-02", + "close": 100, + "availableAt": "2026-01-02T21:01:00Z" + }, + { + "date": "2026-01-05", + "close": 102, + "availableAt": "2026-01-05T21:01:00Z" + }, + { + "date": "2026-01-06", + "close": 99, + "availableAt": "2026-01-06T21:01:00Z" + }, + { + "date": "2026-01-07", + "close": 101, + "availableAt": "2026-01-07T21:01:00Z" + }, + { + "date": "2026-01-08", + "close": 98, + "availableAt": "2026-01-08T21:01:00Z" + }, + { + "date": "2026-01-09", + "close": 100, + "availableAt": "2026-01-09T21:01:00Z" + } + ], + "eventRevisions": [ + { + "eventId": "SYNTH-DIV-A", + "revision": 1, + "status": "confirmed", + "classification": "ordinary", + "exDate": "2026-01-06", + "grossDividend": 2.5, + "dividendCurrency": "USD", + "withholdingRate": 0.15, + "fxRateToPriceCurrency": 1, + "fxObservedAt": null, + "availableAt": "2026-01-05T15:00:00Z", + "sourceId": "SYNTHETIC-ACTION-FEED" + }, + { + "eventId": "SYNTH-DIV-A", + "revision": 2, + "status": "confirmed", + "classification": "ordinary", + "exDate": "2026-01-06", + "grossDividend": 3, + "dividendCurrency": "USD", + "withholdingRate": 0.15, + "fxRateToPriceCurrency": 1, + "fxObservedAt": null, + "availableAt": "2026-01-05T18:00:00Z", + "sourceId": "SYNTHETIC-ACTION-FEED" + }, + { + "eventId": "SYNTH-SPECIAL-B", + "revision": 1, + "status": "confirmed", + "classification": "special", + "exDate": "2026-01-08", + "grossDividend": 3, + "dividendCurrency": "USD", + "withholdingRate": 0.15, + "fxRateToPriceCurrency": 1, + "fxObservedAt": null, + "availableAt": "2026-01-07T18:00:00Z", + "sourceId": "SYNTHETIC-ACTION-FEED" + }, + { + "eventId": "SYNTH-CANCELLED-C", + "revision": 1, + "status": "confirmed", + "classification": "ordinary", + "exDate": "2026-01-08", + "grossDividend": 1, + "dividendCurrency": "USD", + "withholdingRate": 0.15, + "fxRateToPriceCurrency": 1, + "fxObservedAt": null, + "availableAt": "2026-01-06T18:00:00Z", + "sourceId": "SYNTHETIC-ACTION-FEED" + }, + { + "eventId": "SYNTH-CANCELLED-C", + "revision": 2, + "status": "cancelled", + "classification": "ordinary", + "exDate": "2026-01-08", + "grossDividend": 1, + "dividendCurrency": "USD", + "withholdingRate": 0.15, + "fxRateToPriceCurrency": 1, + "fxObservedAt": null, + "availableAt": "2026-01-07T19:00:00Z", + "sourceId": "SYNTHETIC-ACTION-FEED" + } + ] + }, + "expected": { + "methodology": "backward_adjusted_ex_date_close_total_return", + "returnVariant": "gross", + "priceCurrency": "USD", + "asOf": "2026-01-09T23:00:00Z", + "anchor": { + "basis": "latest_raw_close", + "date": "2026-01-09", + "rawClose": 100 + }, + "adjustedPrices": [ + 97.058823529412, + 99, + 99, + 101, + 98, + 100 + ], + "cumulativeFactors": [ + 0.970588235294, + 0.970588235294, + 1, + 1, + 1, + 1 + ], + "eventAdjustments": [ + { + "exDate": "2026-01-06", + "exIndex": 2, + "eventIds": [ + "SYNTH-DIV-A" + ], + "selectedRevisions": [ + 2 + ], + "sourceIds": [ + "SYNTHETIC-ACTION-FEED" + ], + "priorClose": 102, + "exDateClose": 99, + "grossDividendPriceCurrency": 3, + "effectiveDividend": 3, + "backwardFactor": 0.970588235294, + "factorAppliesTo": "indices \u003c 2" + } + ], + "returnLinks": [ + { + "date": "2026-01-05", + "priceReturn": 0.02, + "totalReturn": 0.02, + "effectiveDividend": 0 + }, + { + "date": "2026-01-06", + "priceReturn": -0.029411764706, + "totalReturn": 0, + "effectiveDividend": 3 + }, + { + "date": "2026-01-07", + "priceReturn": 0.020202020202, + "totalReturn": 0.020202020202, + "effectiveDividend": 0 + }, + { + "date": "2026-01-08", + "priceReturn": -0.029702970297, + "totalReturn": -0.029702970297, + "effectiveDividend": 0 + }, + { + "date": "2026-01-09", + "priceReturn": 0.020408163265, + "totalReturn": 0.020408163265, + "effectiveDividend": 0 + } + ], + "excludedEvents": [ + { + "eventId": "SYNTH-CANCELLED-C", + "selectedRevision": 2, + "reason": "cancelled" + }, + { + "eventId": "SYNTH-SPECIAL-B", + "selectedRevision": 1, + "reason": "special_excluded_by_policy" + } + ], + "rounding": { + "internal": "unrounded IEEE-754 binary64", + "serializedDecimalPlaces": 12, + "factorCompounding": "multiply unrounded factors, round only serialized output" + } + }, + "source": "../../tests/shared_fixture.json", + "headline": { + "priorClose": 102, + "exDateClose": 99, + "grossDividend": 3, + "priceReturn": -0.029411764706, + "grossTotalReturn": 0, + "backwardFactor": 0.970588235294 + }, + "note": "All values are synthetic. The factor uses the ex-date close and is applied only to earlier observations." } diff --git a/test/fixtures/D02-F01-A04.json b/test/fixtures/D02-F01-A04.json index 52c937d..41b3640 100644 --- a/test/fixtures/D02-F01-A04.json +++ b/test/fixtures/D02-F01-A04.json @@ -1,14 +1,195 @@ { - "topicId": "D02-F01-A04", - "evidenceClass": "synthetic CRSPAccess-compatible illustration", - "warning": "No licensed CRSP observation is redistributed or claimed as a historical issuer event.", - "crspConvention": "CRSPAccess-ts_print-cumfacpr-archived", - "crspBaseDate": "2024-06-10", - "crspExdt": "2024-06-10", - "crspFacpr": 1, - "rows": [ - {"date": "2024-06-06", "crspPrc": 120, "crspCumfacpr": 0.5, "crspAdjustedPrice": 60}, - {"date": "2024-06-07", "crspPrc": -123, "crspCumfacpr": 0.5, "crspAdjustedPrice": -61.5, "note": "negative sign marks a CRSP bid/ask average"}, - {"date": "2024-06-10", "crspPrc": 60, "crspCumfacpr": 1, "crspAdjustedPrice": 60} - ] + "topicId": "D02-F01-A04", + "input": { + "crspConvention": "CRSPAccess-ts_print-cumfacpr-archived", + "crspSourceVersion": "Archived CRSP Stock and Index Data Description Guide convention; synthetic extract v1", + "packageSecurityKey": "SYNTHETIC-SECURITY-001", + "crspBaseDate": "2024-06-10", + "crspGapPolicy": "stop-at-unknown-exchange", + "roundingDecimals": 6, + "crspFactorEvents": [ + { + "crspExdt": "2024-06-10", + "crspFacpr": 1, + "syntheticLabel": "Synthetic 2-for-1 split-like CRSP event" + } + ], + "records": [ + { + "date": "2024-06-06", + "crspPrc": 120, + "crspCumfacpr": 0.5, + "crspPriceKind": "trade", + "coverageStatus": "observed" + }, + { + "date": "2024-06-07", + "crspPrc": -123, + "crspCumfacpr": 0.5, + "crspPriceKind": "bid_ask_average", + "coverageStatus": "observed" + }, + { + "date": "2024-06-10", + "crspPrc": 60, + "crspCumfacpr": 1, + "crspPriceKind": "trade", + "coverageStatus": "observed" + }, + { + "date": "2024-06-11", + "crspPrc": 62, + "crspCumfacpr": 1, + "crspPriceKind": "trade", + "coverageStatus": "observed" + }, + { + "date": "2024-06-12", + "crspPrc": 0, + "crspCumfacpr": 1, + "crspPriceKind": "missing", + "coverageStatus": "observed" + }, + { + "date": "2024-06-13", + "crspPrc": null, + "crspCumfacpr": null, + "crspPriceKind": "missing", + "coverageStatus": "unknown_exchange_gap" + }, + { + "date": "2024-06-14", + "crspPrc": null, + "crspCumfacpr": null, + "crspPriceKind": "missing", + "coverageStatus": "post_delisting_unpriced" + } + ] + }, + "expected": { + "crspConvention": "CRSPAccess-ts_print-cumfacpr-archived", + "crspSourceVersion": "Archived CRSP Stock and Index Data Description Guide convention; synthetic extract v1", + "packageSecurityKey": "SYNTHETIC-SECURITY-001", + "crspBaseDate": "2024-06-10", + "crspGapPolicy": "stop-at-unknown-exchange", + "crspPriceFormula": "CRSP adjusted price = CRSP PRC * CRSP CUMFACPR", + "crspFactorEvents": [ + { + "crspExdt": "2024-06-10", + "crspFacpr": 1, + "syntheticLabel": "Synthetic 2-for-1 split-like CRSP event" + } + ], + "crspFactorChangeDates": [ + "2024-06-10" + ], + "roundingDecimals": 6, + "records": [ + { + "date": "2024-06-06", + "crspPrc": 120, + "crspCumfacpr": 0.5, + "crspAdjustedPrice": 60, + "crspAdjustedMagnitude": 60, + "crspRecoveredPrc": 120, + "crspPriceKind": "trade", + "coverageStatus": "observed", + "status": "CRSP_ADJUSTED_TRADE" + }, + { + "date": "2024-06-07", + "crspPrc": -123, + "crspCumfacpr": 0.5, + "crspAdjustedPrice": -61.5, + "crspAdjustedMagnitude": 61.5, + "crspRecoveredPrc": -123, + "crspPriceKind": "bid_ask_average", + "coverageStatus": "observed", + "status": "CRSP_ADJUSTED_BID_ASK_AVERAGE" + }, + { + "date": "2024-06-10", + "crspPrc": 60, + "crspCumfacpr": 1, + "crspAdjustedPrice": 60, + "crspAdjustedMagnitude": 60, + "crspRecoveredPrc": 60, + "crspPriceKind": "trade", + "coverageStatus": "observed", + "status": "CRSP_ADJUSTED_TRADE" + }, + { + "date": "2024-06-11", + "crspPrc": 62, + "crspCumfacpr": 1, + "crspAdjustedPrice": 62, + "crspAdjustedMagnitude": 62, + "crspRecoveredPrc": 62, + "crspPriceKind": "trade", + "coverageStatus": "observed", + "status": "CRSP_ADJUSTED_TRADE" + }, + { + "date": "2024-06-12", + "crspPrc": 0, + "crspCumfacpr": 1, + "crspAdjustedPrice": null, + "crspAdjustedMagnitude": null, + "crspRecoveredPrc": null, + "crspPriceKind": "missing", + "coverageStatus": "observed", + "status": "CRSP_PRICE_MISSING" + }, + { + "date": "2024-06-13", + "crspPrc": null, + "crspCumfacpr": null, + "crspAdjustedPrice": null, + "crspAdjustedMagnitude": null, + "crspRecoveredPrc": null, + "crspPriceKind": "missing", + "coverageStatus": "unknown_exchange_gap", + "status": "CRSP_FACTOR_GAP" + }, + { + "date": "2024-06-14", + "crspPrc": null, + "crspCumfacpr": null, + "crspAdjustedPrice": null, + "crspAdjustedMagnitude": null, + "crspRecoveredPrc": null, + "crspPriceKind": "missing", + "coverageStatus": "post_delisting_unpriced", + "status": "CRSP_POST_DELISTING_UNPRICED" + } + ] + }, + "evidenceClass": "synthetic CRSPAccess-compatible illustration", + "warning": "No licensed CRSP observation is redistributed or claimed as a historical issuer event.", + "crspConvention": "CRSPAccess-ts_print-cumfacpr-archived", + "crspBaseDate": "2024-06-10", + "crspExdt": "2024-06-10", + "crspFacpr": 1, + "rows": [ + { + "date": "2024-06-06", + "crspPrc": 120, + "crspCumfacpr": 0.5, + "crspAdjustedPrice": 60 + }, + { + "date": "2024-06-07", + "crspPrc": -123, + "crspCumfacpr": 0.5, + "crspAdjustedPrice": -61.5, + "note": "negative sign marks a CRSP bid/ask average" + }, + { + "date": "2024-06-10", + "crspPrc": 60, + "crspCumfacpr": 1, + "crspAdjustedPrice": 60 + } + ], + "fixtureLicense": "CC0 synthetic teaching fixture; no CRSP observations" } diff --git a/test/fixtures/D02-F01-A05.json b/test/fixtures/D02-F01-A05.json index c365e5b..4a83ad9 100644 --- a/test/fixtures/D02-F01-A05.json +++ b/test/fixtures/D02-F01-A05.json @@ -1,10 +1,129 @@ { - "notice": "Synthetic CRSP CIZ 2.0-shaped values; not licensed CRSP observations.", - "crspField": "DlyCumFacShr", - "crspBasisDate": "2024-09-05", - "rows": [ - {"date": "2024-08-28", "rawSharesOutstandingThousands": 250, "rawVolumeShares": 100, "DlyCumFacShr": 4, "crspAdjustedSharesOutstandingThousands": 1000, "crspAdjustedVolumeShares": 400}, - {"date": "2024-08-29", "rawSharesOutstandingThousands": 250, "rawVolumeShares": 125, "DlyCumFacShr": 4, "crspAdjustedSharesOutstandingThousands": 1000, "crspAdjustedVolumeShares": 500}, - {"date": "2024-08-30", "rawSharesOutstandingThousands": 1000, "rawVolumeShares": 460, "DlyCumFacShr": 1, "crspAdjustedSharesOutstandingThousands": 1000, "crspAdjustedVolumeShares": 460} - ] + "topicId": "D02-F01-A05", + "input": { + "schemaVersion": "CRSP_US_STOCK_CIZ_2_0", + "sourceRelease": "synthetic-ciz-2.0-fixture-v1", + "crspBasisDate": "2024-09-05", + "extractCoverage": "full_history", + "records": [ + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-08-28", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 4, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 250, + "rawVolumeShares": 100 + }, + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-08-29", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 4, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 250, + "rawVolumeShares": 125 + }, + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-08-30", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 1, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 1000, + "rawVolumeShares": 460 + }, + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-09-03", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 1, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 1000, + "rawVolumeShares": 520 + }, + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-09-04", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 1, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 1000, + "rawVolumeShares": null + }, + { + "packageSecurityKey": "SYNTHETIC-CRSP-CIZ-001", + "date": "2024-09-05", + "frequency": "daily", + "crspFactorField": "DlyCumFacShr", + "crspCumulativeShareFactor": 1, + "crspFactorStatus": "observed", + "rawSharesOutstandingThousands": 1000, + "rawVolumeShares": 510 + } + ] + }, + "expected": { + "rows": [ + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 400 + }, + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 500 + }, + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 460 + }, + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 520 + }, + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": null + }, + { + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 510 + } + ] + }, + "notice": "Synthetic CRSP CIZ 2.0-shaped values; not licensed CRSP observations.", + "crspField": "DlyCumFacShr", + "crspBasisDate": "2024-09-05", + "rows": [ + { + "date": "2024-08-28", + "rawSharesOutstandingThousands": 250, + "rawVolumeShares": 100, + "DlyCumFacShr": 4, + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 400 + }, + { + "date": "2024-08-29", + "rawSharesOutstandingThousands": 250, + "rawVolumeShares": 125, + "DlyCumFacShr": 4, + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 500 + }, + { + "date": "2024-08-30", + "rawSharesOutstandingThousands": 1000, + "rawVolumeShares": 460, + "DlyCumFacShr": 1, + "crspAdjustedSharesOutstandingThousands": 1000, + "crspAdjustedVolumeShares": 460 + } + ], + "evidenceScope": "Synthetic values shaped like CRSP CIZ 2.0 fields; no CRSP observations are redistributed." } diff --git a/test/fixtures/D02-F02-A01.json b/test/fixtures/D02-F02-A01.json index 42057c2..d37de23 100644 --- a/test/fixtures/D02-F02-A01.json +++ b/test/fixtures/D02-F02-A01.json @@ -1,21 +1,82 @@ { - "event": "National Grid plc 2024 rights issue", - "sourcedFacts": { - "terms": "7 new shares for 24 existing shares", - "subscriptionPrice": "645 GBp per new share", - "closingMiddleMarketPrice": "1127.5 GBp on 2024-05-22", - "cashDisadvantage": "39.12 GBp FY24 final dividend not payable on new shares", - "recordDate": "2024-05-20 18:00 Europe/London", - "exRightsAndNilPaidTradingStart": "2024-05-24 08:00 Europe/London", - "acceptanceAndPaymentDeadline": "2024-06-10 11:00 Europe/London", - "newSharesTradingStart": "2024-06-12 08:00 Europe/London" - }, - "derivation": { - "referencePrice": "1127.5 - 39.12 = 1088.38 GBp", - "terp": "(24 x 1088.38 + 7 x 645) / 31 = 988.261935 GBp", - "valuePerOldShare": "1088.38 - 988.261935 = 100.118065 GBp", - "valuePerNewShareRight": "988.261935 - 645 = 343.261935 GBp", - "adjustmentFactor": "988.261935 / 1088.38 = 0.908012" - }, - "interpretation": "The calculation reproduces the issuer's rounded 34.7% issue-price discount to TERP. It does not claim that 988.261935 GBp traded on the ex-rights date." + "topicId": "D02-F02-A01", + "input": { + "asOf": "2024-05-24T00:00:00Z", + "revisions": [ + { + "eventId": "NG-2024-RIGHTS", + "revisionId": "NG-PROSPECTUS-2024-05-23", + "revisionSequence": 1, + "availableAt": "2024-05-23T23:59:59Z", + "status": "confirmed", + "recordAt": "2024-05-20T18:00:00+01:00", + "exAt": "2024-05-24T08:00:00+01:00", + "rightsTradingStartAt": "2024-05-24T08:00:00+01:00", + "paymentDeadlineAt": "2024-06-10T11:00:00+01:00", + "newSharesTradeAt": "2024-06-12T08:00:00+01:00", + "terms": { + "oldShares": 24, + "newShares": 7, + "rawCumRightsPrice": 1127.5, + "cashDisadvantage": 39.12, + "quoteCurrency": "GBp", + "subscriptionPrice": 645, + "subscriptionCurrency": "GBp", + "fxQuotePerSubscription": 1, + "feesPerNewShareQuote": 0, + "taxesPerNewShareQuote": 0, + "holdingOldShares": 100, + "outOfMoneyPolicy": "reject", + "priceSourceId": "NG-PROSPECTUS-P52-LSE-DOL-QUOTE", + "priceDate": "2024-05-22", + "referencePriceConvention": "raw_cum_price_less_cash_disadvantage", + "renounceable": true, + "nilPaidRights": true, + "oversubscriptionPolicy": "not_documented_in_teaching_extract", + "fractionalPolicy": "round_down_company_benefit_with_nominee_exception" + } + } + ] + }, + "expected": { + "eventId": "NG-2024-RIGHTS", + "revisionId": "NG-PROSPECTUS-2024-05-23", + "availableAt": "2024-05-23T23:59:59Z", + "quoteCurrency": "GBp", + "referencePrice": 1088.38, + "subscriptionCashQuote": 645, + "terp": 988.261935, + "valuePerOldShare": 100.118065, + "valuePerNewShareRight": 343.261935, + "adjustmentFactor": 0.908012, + "issueDiscountToTerp": 0.347339, + "inTheMoney": true, + "applied": true, + "entitlement": { + "exactNewShares": 29.166667, + "wholeNewShares": 29, + "fractionalNewShare": 0.166667 + }, + "referencePriceIsTradedFact": false + }, + "event": "National Grid plc 2024 rights issue", + "sourcedFacts": { + "terms": "7 new shares for 24 existing shares", + "subscriptionPrice": "645 GBp per new share", + "closingMiddleMarketPrice": "1127.5 GBp on 2024-05-22", + "cashDisadvantage": "39.12 GBp FY24 final dividend not payable on new shares", + "recordDate": "2024-05-20 18:00 Europe/London", + "exRightsAndNilPaidTradingStart": "2024-05-24 08:00 Europe/London", + "acceptanceAndPaymentDeadline": "2024-06-10 11:00 Europe/London", + "newSharesTradingStart": "2024-06-12 08:00 Europe/London" + }, + "derivation": { + "referencePrice": "1127.5 - 39.12 = 1088.38 GBp", + "terp": "(24 x 1088.38 + 7 x 645) / 31 = 988.261935 GBp", + "valuePerOldShare": "1088.38 - 988.261935 = 100.118065 GBp", + "valuePerNewShareRight": "988.261935 - 645 = 343.261935 GBp", + "adjustmentFactor": "988.261935 / 1088.38 = 0.908012" + }, + "interpretation": "The calculation reproduces the issuer\u0027s rounded 34.7% issue-price discount to TERP. It does not claim that 988.261935 GBp traded on the ex-rights date.", + "caseLabel": "National Grid 2024 issuer-fact terms plus an explicitly derived reference price" } diff --git a/test/fixtures/D02-F02-A02.json b/test/fixtures/D02-F02-A02.json index 12b7045..666edf9 100644 --- a/test/fixtures/D02-F02-A02.json +++ b/test/fixtures/D02-F02-A02.json @@ -1,15 +1,167 @@ { - "description": "Synthetic multi-child example; not an issuer or provider observation", - "parentCumPriceUSD": 120, - "children": [ - {"securityId": "SYNTH-CHILD-A", "ratio": "1:4", "priceEUR": 40, "USDPerEUR": 1.1, "valuePerParentUSD": 11}, - {"securityId": "SYNTH-CHILD-B", "ratio": "1:10", "priceUSD": 25, "valuePerParentUSD": 2.5} - ], - "distributedValuePerParentUSD": 13.5, - "theoreticalParentExReferenceUSD": 106.5, - "backwardAdjustmentFactor": 0.8875, - "factorDirection": "multiply pre-event parent-only prices", - "parentExObservedUSD": 108, - "grossCombinedValueUSD": 121.5, - "grossReturn": 0.0125 + "topicId": "D02-F02-A02", + "input": { + "asOf": "2026-06-02T20:00:00Z", + "revisions": [ + { + "eventId": "SYNTH-SPIN-2026", + "revisionId": "SYNTH-SPIN-2026-R1", + "revisionSequence": 1, + "availableAt": "2026-05-21T12:00:00Z", + "status": "confirmed", + "quoteCurrency": "USD", + "recordAt": "2026-05-20T20:00:00Z", + "whenIssuedStartAt": "2026-05-27T13:30:00Z", + "distributionAt": "2026-06-01T12:00:00Z", + "parentExAt": "2026-06-01T13:30:00Z", + "childRegularWayAt": "2026-06-01T13:30:00Z", + "unavailableChildPricePolicy": "pending", + "parentCumObservation": { + "price": 120, + "currency": "USD", + "priceType": "regular_way_cum_distribution", + "observedAt": "2026-05-29T20:00:00Z", + "availableAt": "2026-05-29T20:00:05Z", + "sourceId": "SYNTH-PARENT-CLOSE" + }, + "parentExObservation": { + "price": 108, + "currency": "USD", + "priceType": "regular_way_ex_distribution", + "observedAt": "2026-06-01T20:00:00Z", + "availableAt": "2026-06-01T20:00:05Z", + "sourceId": "SYNTH-PARENT-EX-CLOSE" + }, + "feesPerParentQuote": 0.2, + "taxesPerParentQuote": 0.3, + "holdingParentShares": 23, + "children": [ + { + "securityId": "SYNTH-CHILD-A", + "childShares": 1, + "parentShares": 4, + "reference": { + "status": "available", + "price": 40, + "currency": "EUR", + "priceType": "when_issued", + "observedAt": "2026-05-29T20:00:00Z", + "availableAt": "2026-05-29T20:00:05Z", + "sourceId": "SYNTH-CHILD-A-WI", + "fxQuotePerChildCurrency": 1.1, + "fxObservedAt": "2026-05-29T20:00:00Z", + "fxAvailableAt": "2026-05-29T20:00:05Z", + "fxSourceId": "SYNTH-EURUSD" + } + }, + { + "securityId": "SYNTH-CHILD-B", + "childShares": 1, + "parentShares": 10, + "reference": { + "status": "available", + "price": 25, + "currency": "USD", + "priceType": "regular_way", + "observedAt": "2026-06-01T20:00:00Z", + "availableAt": "2026-06-01T20:00:05Z", + "sourceId": "SYNTH-CHILD-B-RW", + "fxQuotePerChildCurrency": 1 + } + } + ] + } + ] + }, + "expected": { + "eventId": "SYNTH-SPIN-2026", + "revisionId": "SYNTH-SPIN-2026-R1", + "availableAt": "2026-05-21T12:00:00Z", + "status": "ready", + "quoteCurrency": "USD", + "parentCumPrice": 120, + "distributedValuePerParent": 13.5, + "theoreticalParentExReference": 106.5, + "backwardAdjustmentFactor": 0.8875, + "factorDirection": "multiply_pre_event_parent_prices", + "factorAnchor": "post_event_parent_only_basis", + "rounding": "shortest_decimal_half_up_6_on_output_only", + "components": [ + { + "securityId": "SYNTH-CHILD-A", + "entitlementRatio": 0.25, + "priceType": "when_issued", + "priceQuote": 44, + "valuePerParent": 11, + "holderEntitlement": { + "exactChildShares": 5.75, + "wholeChildShares": 5, + "fractionalChildShare": 0.75, + "fractionalReferenceValue": 33, + "actualCashInLieuKnown": false + } + }, + { + "securityId": "SYNTH-CHILD-B", + "entitlementRatio": 0.1, + "priceType": "regular_way", + "priceQuote": 25, + "valuePerParent": 2.5, + "holderEntitlement": { + "exactChildShares": 2.3, + "wholeChildShares": 2, + "fractionalChildShare": 0.3, + "fractionalReferenceValue": 7.5, + "actualCashInLieuKnown": false + } + } + ], + "economicValueAllocation": { + "parentWeight": 0.8875, + "children": [ + { + "securityId": "SYNTH-CHILD-A", + "weight": 0.091667 + }, + { + "securityId": "SYNTH-CHILD-B", + "weight": 0.020833 + } + ] + }, + "totalReturnBridge": { + "parentExObserved": 108, + "grossCombinedValue": 121.5, + "grossReturn": 0.0125, + "netCombinedValue": 121, + "netReturn": 0.008333, + "feesPerParentQuote": 0.2, + "taxesPerParentQuote": 0.3 + }, + "referenceIsTradedParentExFact": false + }, + "description": "Synthetic multi-child example; not an issuer or provider observation", + "parentCumPriceUSD": 120, + "children": [ + { + "securityId": "SYNTH-CHILD-A", + "ratio": "1:4", + "priceEUR": 40, + "USDPerEUR": 1.1, + "valuePerParentUSD": 11 + }, + { + "securityId": "SYNTH-CHILD-B", + "ratio": "1:10", + "priceUSD": 25, + "valuePerParentUSD": 2.5 + } + ], + "distributedValuePerParentUSD": 13.5, + "theoreticalParentExReferenceUSD": 106.5, + "backwardAdjustmentFactor": 0.8875, + "factorDirection": "multiply pre-event parent-only prices", + "parentExObservedUSD": 108, + "grossCombinedValueUSD": 121.5, + "grossReturn": 0.0125 } diff --git a/test/fixtures/D02-F02-A03.json b/test/fixtures/D02-F02-A03.json index 3874650..864ac65 100644 --- a/test/fixtures/D02-F02-A03.json +++ b/test/fixtures/D02-F02-A03.json @@ -1,11 +1,185 @@ { - "classification": "synthetic teaching arithmetic", - "ratesNewSharesPerOld": [0.1, 0.2], - "shareFactors": [1.1, 1.2], - "cumulativeShareFactor": 1.32, - "rawObservation": {"price": 50, "shares": 200, "volume": 80}, - "volumePolicy": "adjust_to_anchor_basis", - "adjustedObservation": {"price": 37.878787878788, "shares": 264, "volume": 105.6}, - "valueBeforeOutputRounding": {"raw": 10000, "adjusted": 10000}, - "canonicalSource": "../tests/shared_fixture.json" + "topicId": "D02-F02-A03", + "input": { + "method": "backward_post_event_same_class", + "securityId": "SYNTH-CLASS-A", + "asOf": "2026-02-04T12:00:00Z", + "anchorAt": "2026-02-03T21:00:00Z", + "volumePolicy": "adjust_to_anchor_basis", + "events": [ + { + "eventId": "SD-001", + "subjectSecurityId": "SYNTH-CLASS-A", + "distributedSecurityId": "SYNTH-CLASS-A", + "exAt": "2026-01-15T14:30:00Z", + "recordDate": "2026-01-15", + "payableDate": "2026-01-20", + "revisions": [ + { + "publishedAt": "2026-01-05T18:00:00Z", + "status": "confirmed", + "rateNewSharesPerOld": 0.1, + "sourceId": "SYNTH-NOTICE-1" + } + ] + }, + { + "eventId": "SD-002", + "subjectSecurityId": "SYNTH-CLASS-A", + "distributedSecurityId": "SYNTH-CLASS-A", + "exAt": "2026-02-03T14:30:00Z", + "recordDate": "2026-01-30", + "payableDate": "2026-02-02", + "revisions": [ + { + "publishedAt": "2026-01-20T18:00:00Z", + "status": "confirmed", + "rateNewSharesPerOld": 0.15, + "sourceId": "SYNTH-NOTICE-2-R1" + }, + { + "publishedAt": "2026-01-25T18:00:00Z", + "status": "confirmed", + "rateNewSharesPerOld": 0.2, + "sourceId": "SYNTH-NOTICE-2-R2" + } + ] + } + ], + "observations": [ + { + "at": "2026-01-02T21:00:00Z", + "availableAt": "2026-01-02T21:00:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "price": 50, + "shares": 200, + "volume": 80 + }, + { + "at": "2026-02-02T21:00:00Z", + "availableAt": "2026-02-02T21:00:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "price": 55, + "shares": 220, + "volume": 90 + }, + { + "at": "2026-02-03T14:30:00Z", + "availableAt": "2026-02-03T14:30:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "price": 46, + "shares": 264, + "volume": 100 + } + ] + }, + "expected": { + "method": "backward_post_event_same_class", + "securityId": "SYNTH-CLASS-A", + "asOf": "2026-02-04T12:00:00Z", + "anchorAt": "2026-02-03T21:00:00Z", + "volumePolicy": "adjust_to_anchor_basis", + "appliedEvents": [ + { + "eventId": "SD-001", + "exAt": "2026-01-15T14:30:00Z", + "revisionPublishedAt": "2026-01-05T18:00:00Z", + "knownByExDate": true, + "rateNewSharesPerOld": 0.1, + "shareFactor": 1.1, + "priceFactor": 0.909090909091, + "sourceId": "SYNTH-NOTICE-1" + }, + { + "eventId": "SD-002", + "exAt": "2026-02-03T14:30:00Z", + "revisionPublishedAt": "2026-01-25T18:00:00Z", + "knownByExDate": true, + "rateNewSharesPerOld": 0.2, + "shareFactor": 1.2, + "priceFactor": 0.833333333333, + "sourceId": "SYNTH-NOTICE-2-R2" + } + ], + "unavailableEventIds": [ + + ], + "cancelledEventIds": [ + + ], + "rows": [ + { + "at": "2026-01-02T21:00:00Z", + "availableAt": "2026-01-02T21:00:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "rawPrice": 50, + "adjustedPrice": 37.878787878788, + "rawShares": 200, + "adjustedShares": 264, + "rawVolume": 80, + "adjustedVolume": 105.6, + "cumulativeShareFactor": 1.32, + "appliedEventIds": [ + "SD-001", + "SD-002" + ] + }, + { + "at": "2026-02-02T21:00:00Z", + "availableAt": "2026-02-02T21:00:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "rawPrice": 55, + "adjustedPrice": 45.833333333333, + "rawShares": 220, + "adjustedShares": 264, + "rawVolume": 90, + "adjustedVolume": 108, + "cumulativeShareFactor": 1.2, + "appliedEventIds": [ + "SD-002" + ] + }, + { + "at": "2026-02-03T14:30:00Z", + "availableAt": "2026-02-03T14:30:05Z", + "sourceId": "SYNTH-CLOSES-V1", + "rawPrice": 46, + "adjustedPrice": 46, + "rawShares": 264, + "adjustedShares": 264, + "rawVolume": 100, + "adjustedVolume": 100, + "cumulativeShareFactor": 1, + "appliedEventIds": [ + + ] + } + ] + }, + "classification": "synthetic teaching arithmetic", + "ratesNewSharesPerOld": [ + 0.1, + 0.2 + ], + "shareFactors": [ + 1.1, + 1.2 + ], + "cumulativeShareFactor": 1.32, + "rawObservation": { + "price": 50, + "shares": 200, + "volume": 80 + }, + "volumePolicy": "adjust_to_anchor_basis", + "adjustedObservation": { + "price": 37.878787878788, + "shares": 264, + "volume": 105.6 + }, + "valueBeforeOutputRounding": { + "raw": 10000, + "adjusted": 10000 + }, + "canonicalSource": "../tests/shared_fixture.json" } diff --git a/test/fixtures/D02-F02-A04.json b/test/fixtures/D02-F02-A04.json index 4d37322..7e6aca3 100644 --- a/test/fixtures/D02-F02-A04.json +++ b/test/fixtures/D02-F02-A04.json @@ -1,4 +1,128 @@ { + "topicId": "D02-F02-A04", + "input": { + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "asOf": "2026-03-16T20:10:00Z", + "methodology": { + "id": "SYNTHETIC-NET-RETURN-POLICY", + "version": "1.0", + "sourceId": "SYNTHETIC-METHODOLOGY-NOTE", + "classificationMode": "source-designated", + "priceAdjustmentCashBasis": "net", + "referenceAnchor": "previous-session-official-close", + "outputDecimals": 8 + }, + "eventRevisions": [ + { + "revisionId": "R1", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 15, + "currency": "EUR", + "announcedAt": "2026-02-02T12:00:00Z", + "availableAt": "2026-02-02T12:05:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R1" + }, + { + "revisionId": "R2", + "securityId": "SYNTHETIC-SECURITY-004", + "eventId": "SYNTHETIC-SPECIAL-DIVIDEND-2026-01", + "status": "announced", + "issuerClassification": "special", + "grossAmount": 16, + "currency": "EUR", + "announcedAt": "2026-02-05T14:00:00Z", + "availableAt": "2026-02-05T14:10:00Z", + "exAt": "2026-03-16T13:30:00Z", + "paymentAt": "2026-03-20T12:00:00Z", + "actionOrder": 20, + "amountBasisOrder": 0, + "sourceId": "SYNTHETIC-ISSUER-NOTICE-R2" + } + ], + "referencePrice": { + "value": 100, + "currency": "USD", + "anchorType": "previous-session-official-close", + "anchorAt": "2026-03-13T20:00:00Z", + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-OFFICIAL-CLOSE" + }, + "precedingActions": [ + { + "actionId": "SYNTHETIC-2-FOR-1-SPLIT", + "actionOrder": 10, + "priceFactor": 0.5, + "perShareAmountFactor": 0.5, + "effectiveAt": "2026-03-16T13:30:00Z", + "observedAt": "2026-02-01T10:00:00Z", + "availableAt": "2026-02-01T10:05:00Z", + "sourceId": "SYNTHETIC-ACTION-SOURCE" + } + ], + "fxRate": { + "baseCurrency": "EUR", + "quoteCurrency": "USD", + "rate": 1.1, + "observedAt": "2026-03-13T20:00:00Z", + "availableAt": "2026-03-13T20:00:05Z", + "sourceId": "SYNTHETIC-FX-CLOSE" + }, + "taxProfile": { + "withholdingRate": 0.25, + "jurisdiction": "SYNTHETIC-JURISDICTION", + "investorCategory": "SYNTHETIC-NONRESIDENT", + "observedAt": "2026-01-05T09:00:00Z", + "availableAt": "2026-01-05T09:05:00Z", + "sourceId": "SYNTHETIC-TAX-RULE" + }, + "exPriceObservation": { + "value": 43.75, + "currency": "USD", + "observedAt": "2026-03-16T20:00:00Z", + "availableAt": "2026-03-16T20:00:05Z", + "sourceId": "SYNTHETIC-EX-CLOSE" + } + }, + "expected": { + "eventState": "effective", + "selectedRevisionId": "R2", + "classificationDecision": "special", + "classificationReason": "source designation: special", + "adjustmentApplied": true, + "referencePriceOnEventBasis": 50, + "grossDividendOnEventBasis": 8.8, + "netDividendOnEventBasis": 6.6, + "adjustmentCashAmount": 6.6, + "theoreticalExPrice": 43.4, + "adjustmentFactor": 0.868, + "grossDistributionYield": 0.176, + "methodologyId": "SYNTHETIC-NET-RETURN-POLICY", + "methodologyVersion": "1.0", + "lineage": { + "eventSourceId": "SYNTHETIC-ISSUER-NOTICE-R2", + "eventAvailableAt": "2026-02-05T14:10:00Z", + "referenceSourceId": "SYNTHETIC-OFFICIAL-CLOSE", + "methodologySourceId": "SYNTHETIC-METHODOLOGY-NOTE", + "fxSourceId": "SYNTHETIC-FX-CLOSE", + "taxSourceId": "SYNTHETIC-TAX-RULE", + "exPriceSourceId": "SYNTHETIC-EX-CLOSE" + }, + "returns": { + "priceReturn": -0.125, + "grossTotalReturn": 0.051, + "netTotalReturn": 0.007, + "adjustedPriceReturn": 0.00806452 + } + }, "notice": "All values and identifiers are synthetic. The executable source is tests/shared_fixture.json.", "selectedRevision": "R2", "steps": [ diff --git a/test/fixtures/D02-F02-A05.json b/test/fixtures/D02-F02-A05.json index 97574db..9c46474 100644 --- a/test/fixtures/D02-F02-A05.json +++ b/test/fixtures/D02-F02-A05.json @@ -1,6 +1,107 @@ { - "label": "Synthetic three-view worked result; full auditable input is tests/shared_fixture.json", - "marketData": {"referencePrice":"25.00000000","grossCash":"2.00000000","theoreticalExPrice":"23.00000000","backwardFactor":"0.92000000"}, - "observedReturns": {"observedExPrice":"23.15000000","rawPriceReturn":"-0.07400000","grossTotalReturn":"0.00600000","netCashReturn":"0.00120000"}, - "usTaxIllustration": {"scope":"US_FEDERAL_INDIVIDUAL_TAXABLE_2025","basisBefore":"1.50000000","confirmedNondividendAmount":"1.20000000","basisAfter":"0.30000000"} + "topicId": "D02-F02-A05", + "input": { + "asOf": "2025-02-03T21:05:00Z", + "revisions": [ + { + "eventId": "SYN-ROC-2025-001", + "revisionId": "SYN-ANNOUNCEMENT-R1", + "revisionSequence": 1, + "observedAt": "2025-01-20T14:00:00Z", + "availableAt": "2025-01-20T14:02:00Z", + "sourceId": "SYN-ISSUER-NOTICE", + "status": "confirmed", + "exAt": "2025-02-03T14:30:00Z", + "sameDayOrdering": { + "sequence": 1, + "priorEventIds": [ + + ] + }, + "terms": { + "eventCurrency": "USD", + "grossCapitalReturnPerShare": "2.00000000", + "withholdingPerShare": "0.10000000", + "feesPerShare": "0.02000000" + } + } + ], + "referenceObservation": { + "price": "25.00000000", + "currency": "USD", + "observedAt": "2025-01-31T21:00:00Z", + "availableAt": "2025-01-31T21:00:05Z", + "sourceId": "SYN-OFFICIAL-CLOSE" + }, + "fxObservation": { + "priceCurrencyPerEventCurrency": "1.00000000", + "pair": "USD/USD", + "anchorPolicy": "ON_OR_BEFORE_REFERENCE_OBSERVATION", + "observedAt": "2025-01-31T21:00:00Z", + "availableAt": "2025-01-31T21:00:00Z", + "sourceId": "IDENTITY-FX" + }, + "exObservation": { + "price": "23.15000000", + "currency": "USD", + "observedAt": "2025-02-03T21:00:00Z", + "availableAt": "2025-02-03T21:00:04Z", + "sourceId": "SYN-OFFICIAL-CLOSE" + }, + "taxIllustration": { + "jurisdiction": "US_FEDERAL_INDIVIDUAL_TAXABLE_2025", + "currency": "USD", + "basisPerShareBefore": "1.50000000", + "confirmedReturnOfCapitalPerShare": "1.20000000", + "sourceId": "SYN-FINAL-ISSUER-TAX-CLASSIFICATION", + "observedAt": "2025-02-03T20:00:00Z", + "availableAt": "2025-02-03T20:05:00Z" + } + }, + "expected": { + "eventId": "SYN-ROC-2025-001", + "revisionId": "SYN-ANNOUNCEMENT-R1", + "state": "confirmed", + "applied": true, + "priceCurrency": "USD", + "marketDataAdjustment": { + "referencePrice": "25.00000000", + "grossDistributionInPriceCurrency": "2.00000000", + "theoreticalExPrice": "23.00000000", + "backwardHistoryFactor": "0.92000000", + "forwardPostEventFactor": "1.08695652", + "factorDirection": "multiply_pre_ex_history_by_backwardHistoryFactor", + "theoreticalPriceIsObservedTrade": false + }, + "investorReturnDiagnostics": { + "rawPriceReturn": "-0.07400000", + "grossTotalReturn": "0.00600000", + "netCashReturn": "0.00120000" + }, + "usFederalTaxIllustration": { + "basisPerShareAfter": "0.30000000", + "basisReductionPerShare": "1.20000000", + "excessOverBasisPerShare": "0.00000000" + } + }, + "label": "Synthetic three-view worked result; full auditable input is tests/shared_fixture.json", + "marketData": { + "referencePrice": "25.00000000", + "grossCash": "2.00000000", + "theoreticalExPrice": "23.00000000", + "backwardFactor": "0.92000000" + }, + "observedReturns": { + "observedExPrice": "23.15000000", + "rawPriceReturn": "-0.07400000", + "grossTotalReturn": "0.00600000", + "netCashReturn": "0.00120000" + }, + "usTaxIllustration": { + "scope": "US_FEDERAL_INDIVIDUAL_TAXABLE_2025", + "basisBefore": "1.50000000", + "confirmedNondividendAmount": "1.20000000", + "basisAfter": "0.30000000" + }, + "caseLabel": "Explicitly synthetic USD capital return with separate price, return, and US-tax views" } diff --git a/test/fixtures/D02-F03-A01.json b/test/fixtures/D02-F03-A01.json index 5374f8b..f313d95 100644 --- a/test/fixtures/D02-F03-A01.json +++ b/test/fixtures/D02-F03-A01.json @@ -1,13 +1,152 @@ { - "notice": "Every value is synthetic and is not a real identifier assignment.", - "query": "TICKER ALP / XNAS / trading_line", - "validAt": "2024-06-15T14:30:00Z", - "knowledgeAt": "2024-06-20T12:00:00Z", - "selectedRevision": "SYN-MAP-001 revision 1", - "excluded": [ - "revision 2: unavailable until 2024-06-25T09:05:00Z", - "July mapping: validity has not started", - "ALP / XLON: different venue-qualified source key" - ], - "result": {"status": "resolved", "canonicalId": "SYN-LINE-ALPHA-XNAS-USD"} + "topicId": "D02-F03-A01", + "input": { + "query": { + "source": { + "scheme": "TICKER", + "value": "alp", + "entityLevel": "trading_line", + "venueMic": "xnas" + }, + "validAt": "2024-06-15T14:30:00Z", + "knowledgeAt": "2024-06-20T12:00:00Z" + }, + "assertions": [ + { + "assertionId": "SYN-MAP-001", + "revision": 1, + "source": { + "scheme": "TICKER", + "value": "ALP", + "entityLevel": "trading_line", + "venueMic": "XNAS" + }, + "target": { + "canonicalId": "SYN-LINE-ALPHA-XNAS-USD", + "entityLevel": "trading_line" + }, + "validFrom": "2024-01-02T14:30:00Z", + "validTo": "2024-07-01T13:30:00Z", + "observedAt": "2023-12-20T18:00:00Z", + "availableAt": "2023-12-20T18:05:00Z", + "status": "active", + "confidence": "authoritative", + "checkDigitStatus": "not_applicable", + "assignmentAuthority": "SYNTHETIC EXCHANGE NOTICE SERVICE", + "sourceDocumentId": "SYN-NOTICE-100-R1" + }, + { + "assertionId": "SYN-MAP-001", + "revision": 2, + "source": { + "scheme": "TICKER", + "value": "ALP", + "entityLevel": "trading_line", + "venueMic": "XNAS" + }, + "target": { + "canonicalId": "SYN-LINE-BETA-XNAS-USD", + "entityLevel": "trading_line" + }, + "validFrom": "2024-01-02T14:30:00Z", + "validTo": "2024-07-01T13:30:00Z", + "observedAt": "2024-06-25T09:00:00Z", + "availableAt": "2024-06-25T09:05:00Z", + "status": "active", + "confidence": "authoritative", + "checkDigitStatus": "not_applicable", + "assignmentAuthority": "SYNTHETIC EXCHANGE NOTICE SERVICE", + "sourceDocumentId": "SYN-CORRECTION-100-R2" + }, + { + "assertionId": "SYN-MAP-002", + "revision": 1, + "source": { + "scheme": "TICKER", + "value": "ALP", + "entityLevel": "trading_line", + "venueMic": "XNAS" + }, + "target": { + "canonicalId": "SYN-LINE-GAMMA-XNAS-USD", + "entityLevel": "trading_line" + }, + "validFrom": "2024-07-01T13:30:00Z", + "validTo": null, + "observedAt": "2024-06-10T16:00:00Z", + "availableAt": "2024-06-10T16:03:00Z", + "status": "active", + "confidence": "authoritative", + "checkDigitStatus": "not_applicable", + "assignmentAuthority": "SYNTHETIC EXCHANGE NOTICE SERVICE", + "sourceDocumentId": "SYN-NOTICE-101-R1" + }, + { + "assertionId": "SYN-MAP-003", + "revision": 1, + "source": { + "scheme": "TICKER", + "value": "ALP", + "entityLevel": "trading_line", + "venueMic": "XLON" + }, + "target": { + "canonicalId": "SYN-LINE-DELTA-XLON-GBP", + "entityLevel": "trading_line" + }, + "validFrom": "2024-01-02T08:00:00Z", + "validTo": null, + "observedAt": "2023-12-21T10:00:00Z", + "availableAt": "2023-12-21T10:04:00Z", + "status": "active", + "confidence": "authoritative", + "checkDigitStatus": "not_applicable", + "assignmentAuthority": "SYNTHETIC MARKET OPERATOR", + "sourceDocumentId": "SYN-LONDON-NOTICE-9" + } + ] + }, + "expected": { + "status": "resolved", + "source": { + "scheme": "TICKER", + "value": "ALP", + "entityLevel": "trading_line", + "venueMic": "XNAS" + }, + "validAt": "2024-06-15T14:30:00Z", + "knowledgeAt": "2024-06-20T12:00:00Z", + "canonicalId": "SYN-LINE-ALPHA-XNAS-USD", + "candidateCanonicalIds": [ + "SYN-LINE-ALPHA-XNAS-USD" + ], + "confidence": "authoritative", + "evidence": [ + { + "assertionId": "SYN-MAP-001", + "revision": 1, + "availableAt": "2023-12-20T18:05:00Z", + "assignmentAuthority": "SYNTHETIC EXCHANGE NOTICE SERVICE", + "sourceDocumentId": "SYN-NOTICE-100-R1", + "confidence": "authoritative", + "checkDigitStatus": "not_applicable" + } + ], + "reason": "Exactly one canonical entity is supported at both requested clocks." + }, + "notice": "Every value is synthetic and is not a real identifier assignment.", + "query": "TICKER ALP / XNAS / trading_line", + "validAt": "2024-06-15T14:30:00Z", + "knowledgeAt": "2024-06-20T12:00:00Z", + "selectedRevision": "SYN-MAP-001 revision 1", + "excluded": [ + "revision 2: unavailable until 2024-06-25T09:05:00Z", + "July mapping: validity has not started", + "ALP / XLON: different venue-qualified source key" + ], + "result": { + "status": "resolved", + "canonicalId": "SYN-LINE-ALPHA-XNAS-USD" + }, + "license": "CC0 synthetic educational fixture; no identifier is asserted to be assigned by a real authority" } diff --git a/test/fixtures/D02-F03-A02.json b/test/fixtures/D02-F03-A02.json index 12041e7..70861be 100644 --- a/test/fixtures/D02-F03-A02.json +++ b/test/fixtures/D02-F03-A02.json @@ -1,17 +1,205 @@ { - "topicId": "D02-F03-A02", - "synthetic": true, - "question": "Which symbol did listing SYN-LST-001 use at 2024-07-01T15:00:00Z, using only assignment revisions available by 2024-08-01T12:00:00Z?", - "answer": { - "symbol": "NXT", - "listingId": "SYN-LST-001", - "instrumentId": "SYN-INS-001", - "issuerId": "SYN-ISS-001", - "venueMic": "XNAS", - "currency": "USD", - "shareClassId": "SYN-CLS-A", - "selectedAssignment": "SYN-ASG-200 revision 1", - "pathVisibleAsOf": ["ALP", "NXT"] - }, - "counterfactualKnowledgeCutoff": "A correction available on 2024-12-20 must not appear in the 2024-08-01 answer." + "topicId": "D02-F03-A02", + "input": { + "issuers": [ + { + "issuerId": "SYN-ISS-001" + }, + { + "issuerId": "SYN-ISS-002" + } + ], + "instruments": [ + { + "instrumentId": "SYN-INS-001", + "issuerId": "SYN-ISS-001", + "shareClassId": "SYN-CLS-A" + }, + { + "instrumentId": "SYN-INS-002", + "issuerId": "SYN-ISS-002", + "shareClassId": "SYN-CLS-COM" + } + ], + "listings": [ + { + "listingId": "SYN-LST-001", + "instrumentId": "SYN-INS-001", + "venueMic": "XNAS", + "currency": "USD" + }, + { + "listingId": "SYN-LST-002", + "instrumentId": "SYN-INS-001", + "venueMic": "XLON", + "currency": "GBP" + }, + { + "listingId": "SYN-LST-099", + "instrumentId": "SYN-INS-002", + "venueMic": "XNAS", + "currency": "USD" + } + ], + "assignments": [ + { + "assignmentId": "SYN-ASG-100", + "revision": 1, + "status": "active", + "listingId": "SYN-LST-001", + "symbol": "ALP", + "effectiveAt": "2020-01-02T14:30:00Z", + "validTo": "2024-06-10T13:30:00Z", + "announcedAt": "2019-12-18T15:00:00Z", + "availableAt": "2019-12-18T15:05:00Z", + "changeKind": "initial_listing", + "sourceId": "SYN-SRC-XNAS-100" + }, + { + "assignmentId": "SYN-ASG-200", + "revision": 1, + "status": "active", + "listingId": "SYN-LST-001", + "symbol": "NXT", + "effectiveAt": "2024-06-10T13:30:00Z", + "validTo": "2025-01-10T14:30:00Z", + "announcedAt": "2024-05-15T12:00:00Z", + "availableAt": "2024-05-15T12:07:00Z", + "changeKind": "administrative", + "sourceId": "SYN-SRC-XNAS-200-R1" + }, + { + "assignmentId": "SYN-ASG-200", + "revision": 2, + "status": "active", + "listingId": "SYN-LST-001", + "symbol": "NXT", + "effectiveAt": "2024-06-10T13:30:00Z", + "validTo": "2025-01-15T14:30:00Z", + "announcedAt": "2024-05-15T12:00:00Z", + "availableAt": "2024-12-20T16:10:00Z", + "changeKind": "administrative", + "sourceId": "SYN-SRC-XNAS-200-R2" + }, + { + "assignmentId": "SYN-ASG-300", + "revision": 1, + "status": "active", + "listingId": "SYN-LST-001", + "symbol": "NVA", + "effectiveAt": "2025-01-15T14:30:00Z", + "validTo": null, + "announcedAt": "2024-12-18T13:00:00Z", + "availableAt": "2024-12-20T16:12:00Z", + "changeKind": "corporate_action", + "sourceId": "SYN-SRC-XNAS-300" + }, + { + "assignmentId": "SYN-ASG-400", + "revision": 1, + "status": "active", + "listingId": "SYN-LST-002", + "symbol": "ALP.L", + "effectiveAt": "2020-01-03T08:00:00Z", + "validTo": null, + "announcedAt": "2019-12-19T10:00:00Z", + "availableAt": "2019-12-19T10:04:00Z", + "changeKind": "initial_listing", + "sourceId": "SYN-SRC-XLON-400" + }, + { + "assignmentId": "SYN-ASG-900", + "revision": 1, + "status": "active", + "listingId": "SYN-LST-099", + "symbol": "ALP", + "effectiveAt": "2026-03-02T14:30:00Z", + "validTo": null, + "announcedAt": "2026-02-12T14:00:00Z", + "availableAt": "2026-02-12T14:06:00Z", + "changeKind": "initial_listing", + "sourceId": "SYN-SRC-XNAS-900" + } + ], + "query": { + "direction": "listing_to_symbol", + "listingId": "SYN-LST-001", + "queryAt": "2024-07-01T15:00:00Z", + "asOf": "2024-08-01T12:00:00Z" + } + }, + "expected": { + "status": "resolved", + "direction": "listing_to_symbol", + "queryAt": "2024-07-01T15:00:00Z", + "asOf": "2024-08-01T12:00:00Z", + "symbol": "NXT", + "listingId": "SYN-LST-001", + "instrumentId": "SYN-INS-001", + "issuerId": "SYN-ISS-001", + "shareClassId": "SYN-CLS-A", + "venueMic": "XNAS", + "currency": "USD", + "assignmentId": "SYN-ASG-200", + "revision": 1, + "changeKind": "administrative", + "sourceId": "SYN-SRC-XNAS-200-R1", + "announcedAt": "2024-05-15T12:00:00Z", + "availableAt": "2024-05-15T12:07:00Z", + "effectiveAt": "2024-06-10T13:30:00Z", + "validTo": "2025-01-10T14:30:00Z", + "chain": [ + { + "assignmentId": "SYN-ASG-100", + "revision": 1, + "symbol": "ALP", + "effectiveAt": "2020-01-02T14:30:00Z", + "validTo": "2024-06-10T13:30:00Z", + "changeKind": "initial_listing", + "sourceId": "SYN-SRC-XNAS-100", + "announcedAt": "2019-12-18T15:00:00Z", + "availableAt": "2019-12-18T15:05:00Z" + }, + { + "assignmentId": "SYN-ASG-200", + "revision": 1, + "symbol": "NXT", + "effectiveAt": "2024-06-10T13:30:00Z", + "validTo": "2025-01-10T14:30:00Z", + "changeKind": "administrative", + "sourceId": "SYN-SRC-XNAS-200-R1", + "announcedAt": "2024-05-15T12:00:00Z", + "availableAt": "2024-05-15T12:07:00Z" + } + ], + "diagnostics": { + "visibleAssignmentCount": 3, + "chainSegmentCount": 2, + "gapCount": 0, + "gaps": [ + + ], + "reusedSymbolsWithinListing": [ + + ] + } + }, + "synthetic": true, + "question": "Which symbol did listing SYN-LST-001 use at 2024-07-01T15:00:00Z, using only assignment revisions available by 2024-08-01T12:00:00Z?", + "answer": { + "symbol": "NXT", + "listingId": "SYN-LST-001", + "instrumentId": "SYN-INS-001", + "issuerId": "SYN-ISS-001", + "venueMic": "XNAS", + "currency": "USD", + "shareClassId": "SYN-CLS-A", + "selectedAssignment": "SYN-ASG-200 revision 1", + "pathVisibleAsOf": [ + "ALP", + "NXT" + ] + }, + "counterfactualKnowledgeCutoff": "A correction available on 2024-12-20 must not appear in the 2024-08-01 answer.", + "license": "Synthetic educational fixture; no issuer, exchange, or vendor records" } diff --git a/test/fixtures/D02-F03-A03.json b/test/fixtures/D02-F03-A03.json index dc32776..5aa0090 100644 --- a/test/fixtures/D02-F03-A03.json +++ b/test/fixtures/D02-F03-A03.json @@ -1,21 +1,790 @@ { - "notice": "Synthetic educational output derived from tests/shared_fixture.json; not a real issuer or provider record.", - "query": { - "validAt": "2026-03-01T12:00:00Z", - "knownAt": "2026-03-05T12:00:00Z", - "leftShareClassId": "SYN-CLASS-FOUNDER", - "rightShareClassId": "SYN-CLASS-PUBLIC" - }, - "result": { - "state": "RESOLVED", - "sameIssuerShareClassIds": ["SYN-CLASS-FOUNDER", "SYN-CLASS-PREFERRED", "SYN-CLASS-PUBLIC"], - "votingRightsRatioLeftToRight": {"status":"ESTABLISHED","numerator":10,"denominator":1,"unit":"votes_per_share"}, - "economicRightsRatioLeftToRight": {"status":"ESTABLISHED","numerator":1,"denominator":1,"unit":"distribution_units_per_share"}, - "equalEconomics": true, - "conversion": {"status":"ESTABLISHED","direction":"SYN-CLASS-FOUNDER->SYN-CLASS-PUBLIC","ratio":{"numerator":1,"denominator":1},"conditions":["qualifying_transfer"]}, - "classFungibility": {"status":"NOT_ESTABLISHED"}, - "priceConvertibility": "NOT_ESTABLISHED", - "excludedFutureRevisionCount": 1, - "cancelledAssertionIds": ["R-LIST-OLD"] - } + "topicId": "D02-F03-A03", + "input": { + "query": { + "rootEntityId": "SYN-CLASS-FOUNDER", + "validAt": "2026-03-01T12:00:00Z", + "knownAt": "2026-03-05T12:00:00Z", + "compareShareClassIds": [ + "SYN-CLASS-FOUNDER", + "SYN-CLASS-PUBLIC" + ] + }, + "entities": [ + { + "entityId": "SYN-ISSUER-ALPHA", + "entityType": "ISSUER", + "label": "Synthetic Alpha Holdings" + }, + { + "entityId": "SYN-INSTRUMENT-COMMON", + "entityType": "LEGAL_INSTRUMENT", + "label": "Synthetic Alpha Common Equity" + }, + { + "entityId": "SYN-INSTRUMENT-PREFERRED", + "entityType": "LEGAL_INSTRUMENT", + "label": "Synthetic Alpha Preferred Equity" + }, + { + "entityId": "SYN-CLASS-FOUNDER", + "entityType": "SHARE_CLASS", + "label": "Founder Class" + }, + { + "entityId": "SYN-CLASS-PUBLIC", + "entityType": "SHARE_CLASS", + "label": "Public Class" + }, + { + "entityId": "SYN-CLASS-PREFERRED", + "entityType": "SHARE_CLASS", + "label": "Preferred Class" + }, + { + "entityId": "SYN-LISTING-US", + "entityType": "LISTING", + "label": "Synthetic US Listing" + }, + { + "entityId": "SYN-LISTING-EU", + "entityType": "LISTING", + "label": "Synthetic EU Listing" + }, + { + "entityId": "SYN-LISTING-OLD", + "entityType": "LISTING", + "label": "Cancelled Legacy Listing" + }, + { + "entityId": "SYN-LINE-US", + "entityType": "TRADING_LINE", + "label": "Synthetic USD Trading Line" + }, + { + "entityId": "SYN-LINE-EU", + "entityType": "TRADING_LINE", + "label": "Synthetic EUR Trading Line" + }, + { + "entityId": "SYN-VENUE-PRIMARY", + "entityType": "VENUE", + "label": "Synthetic Primary Venue" + }, + { + "entityId": "SYN-VENUE-ALT", + "entityType": "VENUE", + "label": "Synthetic Alternate Venue" + } + ], + "relationships": [ + { + "assertionId": "R-ISSUE-COMMON", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "ISSUED_BY", + "sourceEntityId": "SYN-INSTRUMENT-COMMON", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article IV" + }, + "terms": { + "basis": "legal-issuer" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-ISSUE-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "ISSUED_BY", + "sourceEntityId": "SYN-INSTRUMENT-PREFERRED", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article IV" + }, + "terms": { + "basis": "legal-issuer" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-CLASS-FOUNDER", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "CLASS_OF", + "sourceEntityId": "SYN-CLASS-FOUNDER", + "targetEntityId": "SYN-INSTRUMENT-COMMON", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article IV.1" + }, + "terms": { + "classCode": "F" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-CLASS-PUBLIC", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "CLASS_OF", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-INSTRUMENT-COMMON", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article IV.2" + }, + "terms": { + "classCode": "P" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-CLASS-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "CLASS_OF", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-INSTRUMENT-PREFERRED", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article IV.3" + }, + "terms": { + "classCode": "PR" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-LIST-US", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "LISTED_AS", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-LISTING-US", + "effectiveFrom": "2026-01-10T14:30:00Z", + "effectiveTo": null, + "observedAt": "2026-01-05T14:00:00Z", + "availableAt": "2026-01-05T15:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-US", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-05", + "locator": "listing table row 1" + }, + "terms": { + "listingCurrency": "USD" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-LIST-EU", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "LISTED_AS", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-LISTING-EU", + "effectiveFrom": "2026-02-01T08:00:00Z", + "effectiveTo": null, + "observedAt": "2026-01-20T08:00:00Z", + "availableAt": "2026-01-20T09:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-EU", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-20", + "locator": "listing table row 1" + }, + "terms": { + "listingCurrency": "EUR" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-LIST-OLD", + "revisionNumber": 1, + "status": "CANCELLED", + "relationshipType": "LISTED_AS", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-LISTING-OLD", + "effectiveFrom": "2026-01-20T08:00:00Z", + "effectiveTo": null, + "observedAt": "2026-01-10T08:00:00Z", + "availableAt": "2026-01-10T09:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-CANCEL", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-10", + "locator": "cancellation row 1" + }, + "terms": { + "listingCurrency": "GBP" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-LINE-US", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "TRADING_LINE_OF", + "sourceEntityId": "SYN-LINE-US", + "targetEntityId": "SYN-LISTING-US", + "effectiveFrom": "2026-01-10T14:30:00Z", + "effectiveTo": null, + "observedAt": "2026-01-05T14:00:00Z", + "availableAt": "2026-01-05T15:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-US", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-05", + "locator": "trading line row 1" + }, + "terms": { + "ticker": "SYN.A" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-LINE-EU", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "TRADING_LINE_OF", + "sourceEntityId": "SYN-LINE-EU", + "targetEntityId": "SYN-LISTING-EU", + "effectiveFrom": "2026-02-01T08:00:00Z", + "effectiveTo": null, + "observedAt": "2026-01-20T08:00:00Z", + "availableAt": "2026-01-20T09:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-EU", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-20", + "locator": "trading line row 1" + }, + "terms": { + "ticker": "SYNA" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VENUE-US", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "TRADES_ON", + "sourceEntityId": "SYN-LINE-US", + "targetEntityId": "SYN-VENUE-PRIMARY", + "effectiveFrom": "2026-01-10T14:30:00Z", + "effectiveTo": null, + "observedAt": "2026-01-05T14:00:00Z", + "availableAt": "2026-01-05T15:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-US", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-05", + "locator": "venue row 1" + }, + "terms": { + "marketIdentifierCode": "X-SYN-1" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VENUE-EU", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "TRADES_ON", + "sourceEntityId": "SYN-LINE-EU", + "targetEntityId": "SYN-VENUE-ALT", + "effectiveFrom": "2026-02-01T08:00:00Z", + "effectiveTo": null, + "observedAt": "2026-01-20T08:00:00Z", + "availableAt": "2026-01-20T09:00:00Z", + "source": { + "sourceId": "SYN-EXCHANGE-NOTICE-EU", + "sourceType": "synthetic_exchange_notice", + "documentDate": "2026-01-20", + "locator": "venue row 1" + }, + "terms": { + "marketIdentifierCode": "X-SYN-2" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VOTE-FOUNDER", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "VOTING_RIGHTS", + "sourceEntityId": "SYN-CLASS-FOUNDER", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article V.1" + }, + "terms": { + "numerator": 10, + "denominator": 1, + "unit": "votes_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VOTE-FOUNDER", + "revisionNumber": 2, + "status": "ACTIVE", + "relationshipType": "VOTING_RIGHTS", + "sourceEntityId": "SYN-CLASS-FOUNDER", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-04-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2026-03-20T09:00:00Z", + "availableAt": "2026-03-20T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-2", + "sourceType": "synthetic_charter_amendment", + "documentDate": "2026-03-20", + "locator": "Article V.1 amended" + }, + "terms": { + "numerator": 20, + "denominator": 1, + "unit": "votes_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VOTE-PUBLIC", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "VOTING_RIGHTS", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article V.2" + }, + "terms": { + "numerator": 1, + "denominator": 1, + "unit": "votes_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-VOTE-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "VOTING_RIGHTS", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article V.3" + }, + "terms": { + "numerator": 0, + "denominator": 1, + "unit": "votes_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-ECON-FOUNDER", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "ECONOMIC_RIGHTS", + "sourceEntityId": "SYN-CLASS-FOUNDER", + "targetEntityId": "SYN-INSTRUMENT-COMMON", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VI.1" + }, + "terms": { + "numerator": 1, + "denominator": 1, + "unit": "distribution_units_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-ECON-PUBLIC", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "ECONOMIC_RIGHTS", + "sourceEntityId": "SYN-CLASS-PUBLIC", + "targetEntityId": "SYN-INSTRUMENT-COMMON", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VI.2" + }, + "terms": { + "numerator": 1, + "denominator": 1, + "unit": "distribution_units_per_share" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-DIV-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "DIVIDEND_PREFERENCE", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-INSTRUMENT-PREFERRED", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VI.3" + }, + "terms": { + "currency": "USD", + "minorUnits": 250, + "perShares": 1, + "cumulative": true, + "frequency": "annual" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-CONVERT-FOUNDER", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "CONVERTS_TO", + "sourceEntityId": "SYN-CLASS-FOUNDER", + "targetEntityId": "SYN-CLASS-PUBLIC", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VII.1" + }, + "terms": { + "numerator": 1, + "denominator": 1, + "unit": "target_shares_per_source_share", + "conditions": [ + "qualifying_transfer" + ] + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-REDEEM-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "REDEEMABLE_FOR", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-ISSUER-ALPHA", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VIII.1" + }, + "terms": { + "currency": "USD", + "minorUnits": 10000, + "perShares": 1, + "holderOption": false, + "conditions": [ + "issuer_call_after_2030-01-01" + ] + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-PARTICIPATE-PREF", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "PARTICIPATION_RIGHTS", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-INSTRUMENT-PREFERRED", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VIII.2" + }, + "terms": { + "mode": "nonparticipating" + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-SENIOR-PREF-PUBLIC", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "SENIOR_TO", + "sourceEntityId": "SYN-CLASS-PREFERRED", + "targetEntityId": "SYN-CLASS-PUBLIC", + "effectiveFrom": "2026-01-01T00:00:00Z", + "effectiveTo": null, + "observedAt": "2025-12-15T09:00:00Z", + "availableAt": "2025-12-15T10:00:00Z", + "source": { + "sourceId": "SYN-CHARTER-1", + "sourceType": "synthetic_charter", + "documentDate": "2025-12-15", + "locator": "Article VIII.3" + }, + "terms": { + "scope": [ + "dividend", + "liquidation" + ] + }, + "unsupportedTerms": [ + + ] + }, + { + "assertionId": "R-FUNGIBLE-LINES", + "revisionNumber": 1, + "status": "ACTIVE", + "relationshipType": "FUNGIBLE_WITH", + "sourceEntityId": "SYN-LINE-US", + "targetEntityId": "SYN-LINE-EU", + "effectiveFrom": "2026-02-01T08:00:00Z", + "effectiveTo": null, + "observedAt": "2026-01-25T08:00:00Z", + "availableAt": "2026-01-25T09:00:00Z", + "source": { + "sourceId": "SYN-DEPOSITARY-NOTICE", + "sourceType": "synthetic_depositary_notice", + "documentDate": "2026-01-25", + "locator": "operational link row 1" + }, + "terms": { + "numerator": 1, + "denominator": 1, + "unit": "target_units_per_source_unit", + "conditions": [ + "settlement_bridge_open", + "same_beneficial_owner" + ], + "symmetric": true + }, + "unsupportedTerms": [ + + ] + } + ] + }, + "expected": { + "state": "RESOLVED", + "sameIssuerShareClassIds": [ + "SYN-CLASS-FOUNDER", + "SYN-CLASS-PREFERRED", + "SYN-CLASS-PUBLIC" + ], + "comparison": { + "votingRightsRatioLeftToRight": { + "status": "ESTABLISHED", + "numerator": 10, + "denominator": 1, + "unit": "votes_per_share" + }, + "economicRightsRatioLeftToRight": { + "status": "ESTABLISHED", + "numerator": 1, + "denominator": 1, + "unit": "distribution_units_per_share" + }, + "equalEconomics": true, + "conversion": { + "status": "ESTABLISHED", + "direction": "SYN-CLASS-FOUNDER-\u003eSYN-CLASS-PUBLIC", + "relationshipType": "CONVERTS_TO", + "ratio": { + "numerator": 1, + "denominator": 1 + }, + "unit": "target_shares_per_source_share", + "conditions": [ + "qualifying_transfer" + ] + }, + "fungibility": { + "status": "NOT_ESTABLISHED" + }, + "priceConvertibility": "NOT_ESTABLISHED" + }, + "diagnostics": { + "excludedFutureRevisionCount": 1, + "cancelledAssertionIds": [ + "R-LIST-OLD" + ] + } + }, + "notice": "Synthetic educational output derived from tests/shared_fixture.json; not a real issuer or provider record.", + "query": { + "validAt": "2026-03-01T12:00:00Z", + "knownAt": "2026-03-05T12:00:00Z", + "leftShareClassId": "SYN-CLASS-FOUNDER", + "rightShareClassId": "SYN-CLASS-PUBLIC" + }, + "result": { + "state": "RESOLVED", + "sameIssuerShareClassIds": [ + "SYN-CLASS-FOUNDER", + "SYN-CLASS-PREFERRED", + "SYN-CLASS-PUBLIC" + ], + "votingRightsRatioLeftToRight": { + "status": "ESTABLISHED", + "numerator": 10, + "denominator": 1, + "unit": "votes_per_share" + }, + "economicRightsRatioLeftToRight": { + "status": "ESTABLISHED", + "numerator": 1, + "denominator": 1, + "unit": "distribution_units_per_share" + }, + "equalEconomics": true, + "conversion": { + "status": "ESTABLISHED", + "direction": "SYN-CLASS-FOUNDER-\u003eSYN-CLASS-PUBLIC", + "ratio": { + "numerator": 1, + "denominator": 1 + }, + "conditions": [ + "qualifying_transfer" + ] + }, + "classFungibility": { + "status": "NOT_ESTABLISHED" + }, + "priceConvertibility": "NOT_ESTABLISHED", + "excludedFutureRevisionCount": 1, + "cancelledAssertionIds": [ + "R-LIST-OLD" + ] + }, + "license": "CC0-1.0 synthetic educational fixture" } diff --git a/test/fixtures/D02-F03-A04.json b/test/fixtures/D02-F03-A04.json index b159432..7ac3a1f 100644 --- a/test/fixtures/D02-F03-A04.json +++ b/test/fixtures/D02-F03-A04.json @@ -1,36 +1,290 @@ { - "label": "Synthetic elected mixed-consideration merger", - "license": "Synthetic educational fixture", - "inputs": { - "predecessorQuantity": "101", - "electedFulfilledFraction": "0.75", - "fallbackFraction": "0.25", - "stockRatio": "0.6", - "stockOptionCashPerShare": "5", - "fallbackCashPerShare": "35", - "cashInLieuPrice": "40", - "withholdingPerElectedShare": "0.2", - "feePerShare": "0.05", - "currency": "USD" - }, - "trace": [ - {"expression": "101 * 0.75", "meaning": "elected allocation", "result": "75.75"}, - {"expression": "101 * 0.25", "meaning": "fallback allocation", "result": "25.25"}, - {"expression": "75.75 * 0.6", "meaning": "gross successor shares", "result": "45.45"}, - {"expression": "floor(45.45)", "meaning": "whole successor shares", "result": "45"}, - {"expression": "0.45 * 40", "meaning": "cash in lieu", "result": "18"}, - {"expression": "75.75 * 5 + 25.25 * 35", "meaning": "cash consideration", "result": "1262.50"}, - {"expression": "75.75 * 0.2", "meaning": "withholding", "result": "15.15"}, - {"expression": "101 * 0.05", "meaning": "fees", "result": "5.05"}, - {"expression": "1262.50 + 18 - 15.15 - 5.05", "meaning": "net cash", "result": "1260.30"} - ], - "output": { - "state": "mapped", - "successorShares": "45.000000", - "netCash": "1260.300000", - "currency": "USD", - "historicalPriceAdjustment": "not_computed", - "successorListingState": "not_established" - }, - "canonicalFixture": "../tests/shared_fixture.json" + "topicId": "D02-F03-A04", + "input": { + "asOf": "2026-07-02T12:00:00Z", + "position": { + "predecessorQuantity": "101", + "electedOptionId": "stock-election", + "appraisalQuantity": "0" + }, + "eventVersions": [ + { + "eventId": "SYNTH-MERGER-001", + "revision": 1, + "status": "confirmed", + "availableAt": "2026-05-01T12:00:00Z", + "announcedAt": "2026-04-15T12:00:00Z", + "closingAt": "2026-06-30T20:00:00Z", + "effectiveAt": "2026-06-30T20:00:00Z", + "delistingAt": "2026-07-01T13:30:00Z", + "sourceIds": [ + "SYNTH-DEFINITIVE-AGREEMENT-R1", + "SYNTH-CLOSING-NOTICE" + ], + "predecessor": { + "issuerId": "ISSUER-TARGET", + "instrumentId": "INSTR-TARGET-COMMON", + "shareClassId": "CLASS-TARGET-A", + "listingId": "LIST-TARGET-XNAS", + "identifiers": [ + { + "scheme": "PACKAGE_SECURITY_KEY", + "value": "SYNTH-TARGET-A", + "sourceId": "SYNTH-SECURITY-MASTER" + } + ] + }, + "options": [ + { + "optionId": "stock-election", + "stockLegs": [ + { + "legId": "STOCK-LEG-1", + "ratioPerAllocatedPredecessorShare": "0.6", + "sourceId": "SYNTH-DEFINITIVE-AGREEMENT-R1", + "successor": { + "issuerId": "ISSUER-SUCCESSOR", + "instrumentId": "INSTR-SUCCESSOR-COMMON", + "shareClassId": "CLASS-SUCCESSOR-A", + "listingId": "LIST-SUCCESSOR-XNYS", + "identifiers": [ + { + "scheme": "PACKAGE_SECURITY_KEY", + "value": "SYNTH-SUCCESSOR-A", + "sourceId": "SYNTH-SECURITY-MASTER" + } + ] + }, + "fractionalPolicy": { + "mode": "cash_in_lieu", + "lotSize": "1", + "pricePerShare": "40", + "currency": "USD", + "observedAt": "2026-06-30T20:00:00Z", + "availableAt": "2026-06-30T20:01:00Z", + "sourceId": "SYNTH-CIL-PRICE" + } + } + ], + "cashLegs": [ + { + "legId": "CASH-1", + "kind": "consideration", + "amountPerAllocatedPredecessorShare": "5", + "currency": "USD", + "sourceId": "SYNTH-DEFINITIVE-AGREEMENT-R1" + }, + { + "legId": "TAX-1", + "kind": "withholding", + "amountPerAllocatedPredecessorShare": "0.2", + "currency": "USD", + "sourceId": "SYNTH-TAX-INSTRUCTION" + }, + { + "legId": "FEE-1", + "kind": "fee", + "amountPerAllocatedPredecessorShare": "0.05", + "currency": "USD", + "sourceId": "SYNTH-AGENT-INSTRUCTION" + } + ] + }, + { + "optionId": "cash-election", + "stockLegs": [ + + ], + "cashLegs": [ + { + "legId": "CASH-2", + "kind": "consideration", + "amountPerAllocatedPredecessorShare": "35", + "currency": "USD", + "sourceId": "SYNTH-DEFINITIVE-AGREEMENT-R1" + }, + { + "legId": "FEE-2", + "kind": "fee", + "amountPerAllocatedPredecessorShare": "0.05", + "currency": "USD", + "sourceId": "SYNTH-AGENT-INSTRUCTION" + } + ] + } + ], + "electionRules": { + "fallbackOptionId": "cash-election", + "fulfilledFractions": { + "stock-election": "0.75", + "cash-election": "1" + } + }, + "termsSupported": true + } + ] + }, + "expected": { + "state": "mapped", + "eventId": "SYNTH-MERGER-001", + "selectedRevision": 1, + "effectiveAt": "2026-06-30T20:00:00Z", + "predecessor": { + "issuerId": "ISSUER-TARGET", + "instrumentId": "INSTR-TARGET-COMMON", + "shareClassId": "CLASS-TARGET-A", + "listingId": "LIST-TARGET-XNAS", + "identifiers": [ + { + "scheme": "PACKAGE_SECURITY_KEY", + "value": "SYNTH-TARGET-A", + "sourceId": "SYNTH-SECURITY-MASTER" + } + ] + }, + "allocations": [ + { + "optionId": "stock-election", + "role": "elected", + "fulfilledFraction": "0.750000", + "allocatedPredecessorQuantity": "75.750000" + }, + { + "optionId": "cash-election", + "role": "fallback", + "fulfilledFraction": "0.250000", + "allocatedPredecessorQuantity": "25.250000" + } + ], + "successorPositions": [ + { + "issuerId": "ISSUER-SUCCESSOR", + "instrumentId": "INSTR-SUCCESSOR-COMMON", + "shareClassId": "CLASS-SUCCESSOR-A", + "listingId": "LIST-SUCCESSOR-XNYS", + "quantity": "45.000000" + } + ], + "cashByCurrency": [ + { + "currency": "USD", + "consideration": "1262.500000", + "appraisal": "0.000000", + "withholding": "15.150000", + "fees": "5.050000", + "cashInLieu": "18.000000", + "net": "1260.300000" + } + ], + "fractionalSettlements": [ + { + "stockLegId": "STOCK-LEG-1", + "grossQuantity": "45.450000", + "deliverableQuantity": "45.000000", + "fractionalQuantity": "0.450000", + "cashInLieu": "18.000000", + "currency": "USD", + "sourceId": "SYNTH-CIL-PRICE" + } + ], + "identityEdges": [ + { + "relation": "predecessor_instrument_to_successor_instrument", + "fromInstrumentId": "INSTR-TARGET-COMMON", + "toInstrumentId": "INSTR-SUCCESSOR-COMMON", + "effectiveAt": "2026-06-30T20:00:00Z", + "sourceId": "SYNTH-DEFINITIVE-AGREEMENT-R1" + } + ], + "listingState": { + "predecessor": "inactive", + "successors": "not_established" + }, + "priceAdjustment": { + "state": "not_computed", + "reason": "Identity and entitlement mapping does not create a historical price-adjustment series." + }, + "diagnostics": { + "asOf": "2026-07-02T12:00:00Z", + "selectedVersionAvailableAt": "2026-05-01T12:00:00Z", + "sourceIds": [ + "SYNTH-AGENT-INSTRUCTION", + "SYNTH-CIL-PRICE", + "SYNTH-CLOSING-NOTICE", + "SYNTH-DEFINITIVE-AGREEMENT-R1", + "SYNTH-SECURITY-MASTER", + "SYNTH-TAX-INSTRUCTION" + ] + } + }, + "label": "Synthetic elected mixed-consideration merger", + "license": "Synthetic educational fixture", + "inputs": { + "predecessorQuantity": "101", + "electedFulfilledFraction": "0.75", + "fallbackFraction": "0.25", + "stockRatio": "0.6", + "stockOptionCashPerShare": "5", + "fallbackCashPerShare": "35", + "cashInLieuPrice": "40", + "withholdingPerElectedShare": "0.2", + "feePerShare": "0.05", + "currency": "USD" + }, + "trace": [ + { + "expression": "101 * 0.75", + "meaning": "elected allocation", + "result": "75.75" + }, + { + "expression": "101 * 0.25", + "meaning": "fallback allocation", + "result": "25.25" + }, + { + "expression": "75.75 * 0.6", + "meaning": "gross successor shares", + "result": "45.45" + }, + { + "expression": "floor(45.45)", + "meaning": "whole successor shares", + "result": "45" + }, + { + "expression": "0.45 * 40", + "meaning": "cash in lieu", + "result": "18" + }, + { + "expression": "75.75 * 5 + 25.25 * 35", + "meaning": "cash consideration", + "result": "1262.50" + }, + { + "expression": "75.75 * 0.2", + "meaning": "withholding", + "result": "15.15" + }, + { + "expression": "101 * 0.05", + "meaning": "fees", + "result": "5.05" + }, + { + "expression": "1262.50 + 18 - 15.15 - 5.05", + "meaning": "net cash", + "result": "1260.30" + } + ], + "output": { + "state": "mapped", + "successorShares": "45.000000", + "netCash": "1260.300000", + "currency": "USD", + "historicalPriceAdjustment": "not_computed", + "successorListingState": "not_established" + }, + "canonicalFixture": "../tests/shared_fixture.json" } diff --git a/test/fixtures/D02-F03-A05.json b/test/fixtures/D02-F03-A05.json index 11f78f1..0d6e062 100644 --- a/test/fixtures/D02-F03-A05.json +++ b/test/fixtures/D02-F03-A05.json @@ -1,22 +1,184 @@ { - "topicId": "D02-F03-A05", - "case": "Synthetic mixed cash-and-stock terminal proceeds", - "license": "CC0-1.0 synthetic educational example", - "arithmetic": { - "previousRegularPriceUsd": "48.000000000000", - "lastRegularPriceUsd": "50.000000000000", - "cashEurPerOldShare": "10.000000000000", - "usdPerEur": "1.100000000000", - "cashValueUsd": "11.000000000000", - "successorSharesPerOldShare": "0.800000000000", - "successorPriceUsd": "52.500000000000", - "stockValueUsd": "42.000000000000", - "grossTerminalValueUsd": "53.000000000000", - "feesAndWithholdingUsd": "0.500000000000", - "netTerminalValueUsd": "52.500000000000", - "lastRegularReturn": "0.041666666667", - "terminalReturn": "0.050000000000", - "linkedReturn": "0.093750000000" - }, - "guard": "If the same known legs are flagged partial, their USD 52.50 subtotal remains visible but terminalReturn and linkedReturn are null." + "topicId": "D02-F03-A05", + "input": { + "asOf": "2026-04-17T12:00:00Z", + "baseCurrency": "USD", + "previousRegularObservation": { + "securityId": "SYNTH-OLD-A", + "price": "48", + "currency": "USD", + "tradingAt": "2026-04-10T20:00:00Z", + "observedAt": "2026-04-10T20:00:00Z", + "sourceAt": "2026-04-10T20:01:00Z", + "availableAt": "2026-04-10T20:05:00Z", + "sourceId": "SYNTH-PRICES" + }, + "lastRegularObservation": { + "securityId": "SYNTH-OLD-A", + "price": "50", + "currency": "USD", + "tradingAt": "2026-04-14T20:00:00Z", + "observedAt": "2026-04-14T20:00:00Z", + "sourceAt": "2026-04-14T20:01:00Z", + "availableAt": "2026-04-14T20:05:00Z", + "sourceId": "SYNTH-PRICES" + }, + "event": { + "eventId": "SYNTH-EVENT-001", + "reason": "merger", + "effectiveAt": "2026-04-15T13:30:00Z", + "observedAt": "2026-04-01T14:00:00Z", + "sourceAt": "2026-04-01T14:01:00Z", + "availableAt": "2026-04-01T14:05:00Z", + "sourceId": "SYNTH-EVENTS" + }, + "proceedsStatus": "complete", + "proceeds": [ + { + "kind": "cash", + "amountPerOldShare": "10", + "currency": "EUR", + "effectiveAt": "2026-04-15T13:30:00Z", + "observedAt": "2026-04-15T15:00:00Z", + "sourceAt": "2026-04-15T15:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-PAYMENTS", + "fxToBase": { + "fromCurrency": "EUR", + "toCurrency": "USD", + "rate": "1.1", + "rateAt": "2026-04-15T20:00:00Z", + "observedAt": "2026-04-15T20:00:00Z", + "sourceAt": "2026-04-15T20:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-FX" + } + }, + { + "kind": "stock", + "quantityPerOldShare": "0.8", + "successorSecurityId": "SYNTH-NEW-B", + "valuationPrice": "52.5", + "priceCurrency": "USD", + "valuationAt": "2026-04-15T20:00:00Z", + "observedAt": "2026-04-15T20:00:00Z", + "sourceAt": "2026-04-15T20:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-SUCCESSOR-PRICE", + "fxToBase": { + "fromCurrency": "USD", + "toCurrency": "USD", + "rate": "1", + "rateAt": "2026-04-15T20:00:00Z", + "observedAt": "2026-04-15T20:00:00Z", + "sourceAt": "2026-04-15T20:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-FX-IDENTITY" + } + } + ], + "deductions": [ + { + "kind": "fee", + "amountPerOldShare": "0.2", + "currency": "USD", + "effectiveAt": "2026-04-15T13:30:00Z", + "observedAt": "2026-04-15T21:00:00Z", + "sourceAt": "2026-04-15T21:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-FEES", + "fxToBase": { + "fromCurrency": "USD", + "toCurrency": "USD", + "rate": "1", + "rateAt": "2026-04-15T20:00:00Z", + "observedAt": "2026-04-15T20:00:00Z", + "sourceAt": "2026-04-15T20:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-FX-IDENTITY" + } + }, + { + "kind": "withholding", + "amountPerOldShare": "0.3", + "currency": "USD", + "effectiveAt": "2026-04-15T13:30:00Z", + "observedAt": "2026-04-15T21:00:00Z", + "sourceAt": "2026-04-15T21:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-WITHHOLDING", + "fxToBase": { + "fromCurrency": "USD", + "toCurrency": "USD", + "rate": "1", + "rateAt": "2026-04-15T20:00:00Z", + "observedAt": "2026-04-15T20:00:00Z", + "sourceAt": "2026-04-15T20:01:00Z", + "availableAt": "2026-04-16T00:00:00Z", + "sourceId": "SYNTH-FX-IDENTITY" + } + } + ], + "researchImputation": null + }, + "expected": { + "observed": { + "status": "complete", + "lastRegularReturn": "0.041666666667", + "terminalGrossValuePerOldShare": "53.000000000000", + "deductionsPerOldShare": "0.500000000000", + "terminalNetValuePerOldShare": "52.500000000000", + "terminalReturn": "0.050000000000", + "linkedReturn": "0.093750000000", + "proceedsBasis": "complete_observed", + "knownObservedGrossValuePerOldShare": null, + "knownObservedDeductionsPerOldShare": null, + "knownObservedNetValuePerOldShare": null + }, + "researchEstimate": null, + "diagnostics": { + "eventId": "SYNTH-EVENT-001", + "eventReason": "merger", + "asOf": "2026-04-17T12:00:00Z", + "effectiveAt": "2026-04-15T13:30:00Z", + "lastRegularTradingAt": "2026-04-14T20:00:00Z", + "observedEvidenceAvailable": true, + "missingEvidence": [ + + ], + "withheldEvidence": [ + + ], + "knownProceedsEvidence": [ + "deductions[0]", + "deductions[0].fxToBase", + "deductions[1]", + "deductions[1].fxToBase", + "proceeds[0]", + "proceeds[0].fxToBase", + "proceeds[1]", + "proceeds[1].fxToBase" + ], + "baseCurrency": "USD" + } + }, + "case": "Synthetic mixed cash-and-stock terminal proceeds", + "license": "CC0-1.0 synthetic educational example", + "arithmetic": { + "previousRegularPriceUsd": "48.000000000000", + "lastRegularPriceUsd": "50.000000000000", + "cashEurPerOldShare": "10.000000000000", + "usdPerEur": "1.100000000000", + "cashValueUsd": "11.000000000000", + "successorSharesPerOldShare": "0.800000000000", + "successorPriceUsd": "52.500000000000", + "stockValueUsd": "42.000000000000", + "grossTerminalValueUsd": "53.000000000000", + "feesAndWithholdingUsd": "0.500000000000", + "netTerminalValueUsd": "52.500000000000", + "lastRegularReturn": "0.041666666667", + "terminalReturn": "0.050000000000", + "linkedReturn": "0.093750000000" + }, + "guard": "If the same known legs are flagged partial, their USD 52.50 subtotal remains visible but terminalReturn and linkedReturn are null." } diff --git a/test/fixtures/D02-F04-A01.json b/test/fixtures/D02-F04-A01.json index d2f7e6d..c55b3c8 100644 --- a/test/fixtures/D02-F04-A01.json +++ b/test/fixtures/D02-F04-A01.json @@ -1,10 +1,258 @@ { - "description": "Synthetic bitemporal roster query before a later correction is available", - "fixture": "../tests/shared_fixture.json", - "queryName": "revision one remains valid before correction is known", - "result": { - "status": "resolved", - "securityIds": ["SEC:E", "SEC:F", "SEC:G", "SEC:H", "SEC:I", "SEC:J"], - "appliedEventVersions": ["EV-001@1", "EV-002@1", "EV-003@1", "EV-004@1", "EV-005@1", "EV-006@1"] - } + "topicId": "D02-F04-A01", + "input": { + "indexId": "IDX:SYNTH:ALPHA", + "effectiveAt": "2024-08-15T00:00:00Z", + "knownAt": "2024-08-15T12:00:00Z", + "snapshots": [ + { + "snapshotId": "BASE-2024", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "effectiveAt": "2024-01-01T00:00:00Z", + "availableAt": "2024-01-02T09:00:00Z", + "lastSequence": 0, + "status": "active", + "securityIds": [ + "SEC:A", + "SEC:B", + "SEC:C", + "SEC:D" + ], + "sourceId": "SYNTH-BASE" + } + ], + "events": [ + { + "eventId": "EV-001", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 1, + "eventType": "add", + "effectiveOrder": 0, + "effectiveAt": "2024-02-01T00:00:00Z", + "announcedAt": "2024-01-15T12:00:00Z", + "availableAt": "2024-01-15T12:05:00Z", + "status": "active", + "changes": [ + { + "action": "add", + "securityId": "SEC:E" + } + ], + "sourceId": "SYNTH-NOTICE-001" + }, + { + "eventId": "EV-002", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 2, + "eventType": "replace", + "effectiveOrder": 0, + "effectiveAt": "2024-03-01T00:00:00Z", + "announcedAt": "2024-02-20T16:00:00Z", + "availableAt": "2024-02-20T16:03:00Z", + "status": "active", + "changes": [ + { + "action": "delete", + "securityId": "SEC:B" + }, + { + "action": "add", + "securityId": "SEC:F" + } + ], + "sourceId": "SYNTH-NOTICE-002" + }, + { + "eventId": "EV-003", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 3, + "eventType": "rebalance", + "effectiveOrder": 0, + "effectiveAt": "2024-04-01T00:00:00Z", + "announcedAt": "2024-03-20T15:00:00Z", + "availableAt": "2024-03-20T15:04:00Z", + "status": "active", + "changes": [ + + ], + "sourceId": "SYNTH-NOTICE-003" + }, + { + "eventId": "EV-004", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 4, + "eventType": "corporate_action", + "effectiveOrder": 0, + "effectiveAt": "2024-04-15T00:00:00Z", + "announcedAt": "2024-04-10T14:00:00Z", + "availableAt": "2024-04-10T14:02:00Z", + "status": "active", + "changes": [ + { + "action": "delete", + "securityId": "SEC:C" + }, + { + "action": "add", + "securityId": "SEC:G" + } + ], + "sourceId": "SYNTH-NOTICE-004" + }, + { + "eventId": "EV-005", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 5, + "eventType": "reconstitution", + "effectiveOrder": 0, + "effectiveAt": "2024-07-01T00:00:00Z", + "announcedAt": "2024-06-20T13:00:00Z", + "availableAt": "2024-06-20T13:05:00Z", + "status": "active", + "changes": [ + { + "action": "delete", + "securityId": "SEC:A" + }, + { + "action": "delete", + "securityId": "SEC:D" + }, + { + "action": "add", + "securityId": "SEC:H" + }, + { + "action": "add", + "securityId": "SEC:I" + } + ], + "sourceId": "SYNTH-NOTICE-005" + }, + { + "eventId": "EV-006", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 6, + "eventType": "add", + "effectiveOrder": 0, + "effectiveAt": "2024-08-01T00:00:00Z", + "announcedAt": "2024-07-20T10:00:00Z", + "availableAt": "2024-07-20T10:03:00Z", + "status": "active", + "changes": [ + { + "action": "add", + "securityId": "SEC:J" + } + ], + "sourceId": "SYNTH-NOTICE-006-R1" + }, + { + "eventId": "EV-006", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 2, + "sequence": 6, + "eventType": "add", + "effectiveOrder": 0, + "effectiveAt": "2024-08-01T00:00:00Z", + "announcedAt": "2024-09-01T09:00:00Z", + "availableAt": "2024-09-01T09:04:00Z", + "status": "active", + "changes": [ + { + "action": "add", + "securityId": "SEC:K" + } + ], + "sourceId": "SYNTH-NOTICE-006-R2" + }, + { + "eventId": "EV-007", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 1, + "sequence": 7, + "eventType": "delete", + "effectiveOrder": 0, + "effectiveAt": "2024-10-01T00:00:00Z", + "announcedAt": "2024-09-20T11:00:00Z", + "availableAt": "2024-09-20T11:04:00Z", + "status": "active", + "changes": [ + { + "action": "delete", + "securityId": "SEC:F" + } + ], + "sourceId": "SYNTH-NOTICE-007-R1" + }, + { + "eventId": "EV-007", + "indexId": "IDX:SYNTH:ALPHA", + "revision": 2, + "sequence": 7, + "eventType": "delete", + "effectiveOrder": 0, + "effectiveAt": "2024-10-01T00:00:00Z", + "announcedAt": "2024-10-02T08:00:00Z", + "availableAt": "2024-10-02T08:05:00Z", + "status": "cancelled", + "changes": [ + + ], + "sourceId": "SYNTH-NOTICE-007-R2" + } + ] + }, + "expected": { + "status": "resolved", + "securityIds": [ + "SEC:E", + "SEC:F", + "SEC:G", + "SEC:H", + "SEC:I", + "SEC:J" + ], + "appliedEventVersions": [ + "EV-001@1", + "EV-002@1", + "EV-003@1", + "EV-004@1", + "EV-005@1", + "EV-006@1" + ], + "cancelledEventIds": [ + + ] + }, + "description": "Synthetic bitemporal roster query before a later correction is available", + "fixture": "../tests/shared_fixture.json", + "queryName": "revision one remains valid before correction is known", + "result": { + "status": "resolved", + "securityIds": [ + "SEC:E", + "SEC:F", + "SEC:G", + "SEC:H", + "SEC:I", + "SEC:J" + ], + "appliedEventVersions": [ + "EV-001@1", + "EV-002@1", + "EV-003@1", + "EV-004@1", + "EV-005@1", + "EV-006@1" + ] + }, + "evidenceNote": "Every index, identity, timestamp, and membership result in this fixture is synthetic." } diff --git a/test/fixtures/D02-F04-A02.json b/test/fixtures/D02-F04-A02.json index 182d1a5..cef627e 100644 --- a/test/fixtures/D02-F04-A02.json +++ b/test/fixtures/D02-F04-A02.json @@ -1,14 +1,185 @@ { - "note": "Synthetic arithmetic copied from tests/shared_fixture.json.", - "effectiveAt": "2023-12-31T23:59:59Z", - "knownAt": "2024-01-02T12:00:00Z", - "historicallyEligible": ["SEC:A", "SEC:B", "SEC:C"], - "historicallyIneligible": ["SEC:D"], - "laterRoster": ["SEC:A", "SEC:C", "SEC:D"], - "missingFromLaterRoster": ["SEC:B"], - "retentionRatio": 0.666667, - "historicalEqualWeightedReturn": -0.166667, - "laterRosterSubsetEqualWeightedReturn": 0.15, - "signedDifference": 0.316667, - "interpretation": "This sign and magnitude are synthetic and not universal." + "topicId": "D02-F04-A02", + "input": { + "universeId": "UNIVERSE:SYNTH:CORE", + "definitionId": "DEF:SYNTH:CORE", + "effectiveAt": "2023-12-31T23:59:59Z", + "knownAt": "2024-01-02T12:00:00Z", + "candidateUniverse": { + "construction": "historical_membership_ledger", + "asOf": "2023-12-31T23:59:59Z", + "availableAt": "2024-01-02T10:00:00Z", + "securityIds": [ + "SEC:A", + "SEC:B", + "SEC:C", + "SEC:D" + ], + "sourceId": "SYNTH-CANDIDATE-LEDGER" + }, + "universeDefinitions": [ + { + "definitionId": "DEF:SYNTH:CORE", + "universeId": "UNIVERSE:SYNTH:CORE", + "revision": 1, + "effectiveFrom": "2020-01-01T00:00:00Z", + "effectiveTo": null, + "announcedAt": "2019-12-15T12:00:00Z", + "availableAt": "2019-12-15T12:05:00Z", + "status": "active", + "baseType": "named_research_universe", + "baseId": "BASE:SYNTH:001", + "ruleSummary": "Synthetic members documented by effective-dated membership evidence.", + "sourceId": "SYNTH-DEFINITION-R1" + }, + { + "definitionId": "DEF:SYNTH:CORE", + "universeId": "UNIVERSE:SYNTH:CORE", + "revision": 2, + "effectiveFrom": "2020-01-01T00:00:00Z", + "effectiveTo": null, + "announcedAt": "2024-02-01T09:00:00Z", + "availableAt": "2024-02-01T09:05:00Z", + "status": "active", + "baseType": "named_research_universe", + "baseId": "BASE:SYNTH:001", + "ruleSummary": "Later documentation revision; unavailable to the canonical query.", + "sourceId": "SYNTH-DEFINITION-R2" + } + ], + "membershipRecords": [ + { + "membershipId": "MEM-A", + "revision": 1, + "universeId": "UNIVERSE:SYNTH:CORE", + "securityId": "SEC:A", + "validFrom": "2020-01-01T00:00:00Z", + "validTo": null, + "announcedAt": "2019-12-15T12:00:00Z", + "availableAt": "2019-12-15T12:05:00Z", + "status": "active", + "changeType": "entry", + "eventId": "EVENT-A-ENTRY", + "sourceId": "SYNTH-MEM-A" + }, + { + "membershipId": "MEM-B", + "revision": 1, + "universeId": "UNIVERSE:SYNTH:CORE", + "securityId": "SEC:B", + "validFrom": "2020-01-01T00:00:00Z", + "validTo": "2024-06-01T00:00:00Z", + "announcedAt": "2023-12-20T10:00:00Z", + "availableAt": "2023-12-20T10:05:00Z", + "status": "active", + "changeType": "exit", + "eventId": "EVENT-B-EXIT", + "sourceId": "SYNTH-MEM-B-R1" + }, + { + "membershipId": "MEM-B", + "revision": 2, + "universeId": "UNIVERSE:SYNTH:CORE", + "securityId": "SEC:B", + "validFrom": "2020-01-01T00:00:00Z", + "validTo": "2023-12-15T00:00:00Z", + "announcedAt": "2024-01-10T08:00:00Z", + "availableAt": "2024-01-10T08:05:00Z", + "status": "active", + "changeType": "revision", + "eventId": "EVENT-B-CORRECTION", + "sourceId": "SYNTH-MEM-B-R2" + }, + { + "membershipId": "MEM-C", + "revision": 1, + "universeId": "UNIVERSE:SYNTH:CORE", + "securityId": "SEC:C", + "validFrom": "2021-01-01T00:00:00Z", + "validTo": null, + "announcedAt": "2020-12-20T10:00:00Z", + "availableAt": "2020-12-20T10:05:00Z", + "status": "active", + "changeType": "entry", + "eventId": "EVENT-C-ENTRY", + "sourceId": "SYNTH-MEM-C" + }, + { + "membershipId": "MEM-D", + "revision": 1, + "universeId": "UNIVERSE:SYNTH:CORE", + "securityId": "SEC:D", + "validFrom": "2024-02-01T00:00:00Z", + "validTo": null, + "announcedAt": "2023-12-20T11:00:00Z", + "availableAt": "2023-12-20T11:05:00Z", + "status": "active", + "changeType": "entry", + "eventId": "EVENT-D-ENTRY", + "sourceId": "SYNTH-MEM-D" + } + ], + "comparisonRoster": { + "observedAt": "2025-01-02T00:00:00Z", + "availableAt": "2025-01-02T12:00:00Z", + "securityIds": [ + "SEC:A", + "SEC:C", + "SEC:D" + ], + "sourceId": "SYNTH-CURRENT-ROSTER" + } + }, + "expected": { + "status": "resolved", + "definitionVersion": "DEF:SYNTH:CORE@1", + "eligibleSecurityIds": [ + "SEC:A", + "SEC:B", + "SEC:C" + ], + "ineligibleSecurityIds": [ + "SEC:D" + ], + "unknownSecurityIds": [ + + ], + "ambiguousSecurityIds": [ + + ], + "hindsightDiagnostics": { + "historicallyEligibleMissingFromCurrent": [ + "SEC:B" + ], + "currentRosterNotHistoricallyEligible": [ + "SEC:D" + ], + "retentionRatio": 0.666667 + } + }, + "note": "Synthetic arithmetic copied from tests/shared_fixture.json.", + "effectiveAt": "2023-12-31T23:59:59Z", + "knownAt": "2024-01-02T12:00:00Z", + "historicallyEligible": [ + "SEC:A", + "SEC:B", + "SEC:C" + ], + "historicallyIneligible": [ + "SEC:D" + ], + "laterRoster": [ + "SEC:A", + "SEC:C", + "SEC:D" + ], + "missingFromLaterRoster": [ + "SEC:B" + ], + "retentionRatio": 0.666667, + "historicalEqualWeightedReturn": -0.166667, + "laterRosterSubsetEqualWeightedReturn": 0.15, + "signedDifference": 0.316667, + "interpretation": "This sign and magnitude are synthetic and not universal.", + "evidenceNote": "Every identifier, membership, timestamp, roster, and return is synthetic." } diff --git a/test/fixtures/D02-F04-A03.json b/test/fixtures/D02-F04-A03.json index f170604..cfdd0d7 100644 --- a/test/fixtures/D02-F04-A03.json +++ b/test/fixtures/D02-F04-A03.json @@ -1,21 +1,255 @@ { - "topicId": "D02-F04-A03", - "description": "Synthetic traditional-IPO evidence under a declared research-availability policy.", - "beforeLocalIngestion": { - "effectiveAt": "2025-05-13T13:36:10Z", - "knownAt": "2025-05-13T13:35:30Z", - "status": "incomplete", - "missingEventTypes": ["local_ingestion"], - "effectiveGateAt": null, - "knowledgeGateAt": null - }, - "afterLocalIngestion": { - "effectiveAt": "2025-05-13T13:36:10Z", - "knownAt": "2025-05-13T13:36:10Z", - "status": "resolved", - "missingEventTypes": [], - "effectiveGateAt": "2025-05-13T13:36:00Z", - "knowledgeGateAt": "2025-05-13T13:36:05Z" - }, - "boundary": "The result describes this research policy only. It does not establish investability, tradability, liquidity, offering eligibility, or returns." + "topicId": "D02-F04-A03", + "input": { + "query": { + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "effectiveAt": "2025-05-13T13:36:10Z", + "knownAt": "2025-05-13T13:36:10Z", + "policyId": "POLICY-SYN-IPO-RESEARCH" + }, + "policies": [ + { + "policyId": "POLICY-SYN-IPO-RESEARCH", + "revision": 1, + "state": "active", + "effectiveAt": "2025-05-01T00:00:00Z", + "availableAt": "2025-05-01T00:05:00Z", + "sourceId": "SYN-RESEARCH-GOVERNANCE", + "context": "traditional_ipo", + "marketPhase": "regular", + "requiredEventTypes": [ + "registration_effective", + "listing_notice", + "first_eligible_session", + "first_observed_trade", + "vendor_release", + "local_ingestion" + ] + }, + { + "policyId": "POLICY-SYN-IPO-RESEARCH", + "revision": 2, + "state": "active", + "effectiveAt": "2025-05-01T00:00:00Z", + "availableAt": "2025-05-14T09:00:00Z", + "sourceId": "SYN-RESEARCH-GOVERNANCE", + "context": "traditional_ipo", + "marketPhase": "regular", + "requiredEventTypes": [ + "registration_effective", + "listing_notice", + "first_eligible_session", + "first_observed_quote", + "first_observed_trade", + "vendor_release", + "local_ingestion" + ] + } + ], + "records": [ + { + "eventId": "EV-FILING", + "revision": 1, + "state": "active", + "eventType": "issuer_filing", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-05T14:00:00Z", + "availableAt": "2025-05-05T14:03:00Z", + "clockOwner": "regulator", + "sourceId": "SYN-REGULATOR-FILING" + }, + { + "eventId": "EV-EFFECT", + "revision": 1, + "state": "active", + "eventType": "registration_effective", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-08T12:00:00Z", + "availableAt": "2025-05-08T12:02:00Z", + "clockOwner": "regulator", + "sourceId": "SYN-REGULATOR-EFFECT" + }, + { + "eventId": "EV-LIST", + "revision": 1, + "state": "active", + "eventType": "listing_notice", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T13:30:00Z", + "availableAt": "2025-05-08T15:10:00Z", + "clockOwner": "exchange", + "sourceId": "SYN-EXCHANGE-NOTICE" + }, + { + "eventId": "EV-LIST", + "revision": 2, + "state": "active", + "eventType": "listing_notice", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T13:35:00Z", + "availableAt": "2025-05-09T16:00:00Z", + "clockOwner": "exchange", + "sourceId": "SYN-EXCHANGE-NOTICE" + }, + { + "eventId": "EV-LIST", + "revision": 3, + "state": "active", + "eventType": "listing_notice", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T13:36:00Z", + "availableAt": "2025-05-14T09:05:00Z", + "clockOwner": "exchange", + "sourceId": "SYN-EXCHANGE-NOTICE" + }, + { + "eventId": "EV-PRICE", + "revision": 1, + "state": "active", + "eventType": "offer_pricing", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-12T22:00:00Z", + "availableAt": "2025-05-12T22:05:00Z", + "clockOwner": "underwriter", + "sourceId": "SYN-PRICING-NOTICE" + }, + { + "eventId": "EV-ALLOC", + "revision": 1, + "state": "active", + "eventType": "allocation", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T00:30:00Z", + "availableAt": "2025-05-13T00:50:00Z", + "clockOwner": "underwriter", + "sourceId": "SYN-ALLOCATION-FEED" + }, + { + "eventId": "EV-SESSION", + "revision": 1, + "state": "active", + "eventType": "first_eligible_session", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "regular", + "effectiveAt": "2025-05-13T13:30:00Z", + "availableAt": "2025-05-12T15:15:00Z", + "clockOwner": "exchange", + "sourceId": "SYN-XNAS-CALENDAR", + "calendarId": "XNAS", + "sessionId": "XNAS-2025-05-13" + }, + { + "eventId": "EV-QUOTE", + "revision": 1, + "state": "active", + "eventType": "first_observed_quote", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "regular", + "effectiveAt": "2025-05-13T13:35:02Z", + "availableAt": "2025-05-13T13:35:05Z", + "clockOwner": "vendor", + "sourceId": "SYN-VENDOR-QUOTE" + }, + { + "eventId": "EV-TRADE", + "revision": 1, + "state": "active", + "eventType": "first_observed_trade", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "regular", + "effectiveAt": "2025-05-13T13:35:07Z", + "availableAt": "2025-05-13T13:35:12Z", + "clockOwner": "vendor", + "sourceId": "SYN-VENDOR-TRADE" + }, + { + "eventId": "EV-VENDOR", + "revision": 1, + "state": "active", + "eventType": "vendor_release", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T13:35:20Z", + "availableAt": "2025-05-13T13:35:24Z", + "clockOwner": "vendor", + "sourceId": "SYN-VENDOR-REFERENCE" + }, + { + "eventId": "EV-LOCAL", + "revision": 1, + "state": "active", + "eventType": "local_ingestion", + "issuerId": "ISSUER-SYN-001", + "instrumentId": "INSTRUMENT-SYN-001", + "listingId": "LISTING-SYN-XNAS", + "marketPhase": "all", + "effectiveAt": "2025-05-13T13:36:00Z", + "availableAt": "2025-05-13T13:36:05Z", + "clockOwner": "research_system", + "sourceId": "SYN-LOCAL-PIPELINE" + } + ] + }, + "expected": { + "status": "resolved", + "effectiveGateAt": "2025-05-13T13:36:00Z", + "knowledgeGateAt": "2025-05-13T13:36:05Z", + "missingEventTypes": [ + + ] + }, + "description": "Synthetic traditional-IPO evidence under a declared research-availability policy.", + "beforeLocalIngestion": { + "effectiveAt": "2025-05-13T13:36:10Z", + "knownAt": "2025-05-13T13:35:30Z", + "status": "incomplete", + "missingEventTypes": [ + "local_ingestion" + ], + "effectiveGateAt": null, + "knowledgeGateAt": null + }, + "afterLocalIngestion": { + "effectiveAt": "2025-05-13T13:36:10Z", + "knownAt": "2025-05-13T13:36:10Z", + "status": "resolved", + "missingEventTypes": [ + + ], + "effectiveGateAt": "2025-05-13T13:36:00Z", + "knowledgeGateAt": "2025-05-13T13:36:05Z" + }, + "boundary": "The result describes this research policy only. It does not establish investability, tradability, liquidity, offering eligibility, or returns.", + "evidenceNote": "Every event, identifier, source, and timestamp in this fixture is synthetic. The policy evaluates research data readiness only." } diff --git a/test/fixtures/D02-F04-A04.json b/test/fixtures/D02-F04-A04.json index d51481a..0b223dc 100644 --- a/test/fixtures/D02-F04-A04.json +++ b/test/fixtures/D02-F04-A04.json @@ -1,21 +1,90 @@ { - "topicId": "D02-F04-A04", - "source": "tests/shared_fixture.json", - "case": "Esterline Technologies fiscal 2017 Form 10-K and Form 10-K/A", - "historicalFacts": { - "originalAccession": "0001564590-17-024189", - "originalAcceptedAt": "2017-11-21T16:32:41Z", - "amendmentAccession": "0001564590-18-007244", - "amendmentAcceptedAt": "2018-03-30T14:43:54Z", - "basicEpsAsReported": 3.94, - "basicEpsRestated": 3.75 - }, - "syntheticAvailabilityAssumptions": { - "originalIngestedAt": "2017-11-21T16:40:00Z", - "amendmentIngestedAt": "2018-03-30T15:00:00Z" - }, - "derivedDifference": { - "basicEpsChangeUsdPerShare": -0.19, - "interpretation": "A revision of the historical filing value, not evidence of a market return or a new fiscal-period result." - } + "topicId": "D02-F04-A04", + "input": { + "entityId": "CIK0000033619", + "reportPeriod": "2017-09-29", + "formFamily": "10-K", + "asOf": "2018-02-01T00:00:00Z", + "records": [ + { + "entityId": "CIK0000033619", + "reportPeriod": "2017-09-29", + "form": "10-K", + "accessionNo": "0001564590-17-024189", + "amendmentNumber": 0, + "acceptedAt": "2017-11-21T16:32:41Z", + "ingestedAt": "2017-11-21T16:40:00Z", + "amendmentScope": [ + "Original annual filing" + ], + "facts": { + "basicEpsUsdPerShare": 3.94, + "netEarningsUsdMillions": 117.387 + } + }, + { + "entityId": "CIK0000033619", + "reportPeriod": "2017-09-29", + "form": "10-K/A", + "accessionNo": "0001564590-18-007244", + "amendmentNumber": 1, + "acceptedAt": "2018-03-30T14:43:54Z", + "ingestedAt": "2018-03-30T15:00:00Z", + "amendmentScope": [ + "Item 6", + "Item 7", + "Item 8", + "Item 9A", + "Item 15" + ], + "facts": { + "basicEpsUsdPerShare": 3.75, + "netEarningsUsdMillions": 111.554 + } + } + ] + }, + "expected": { + "entityId": "CIK0000033619", + "reportPeriod": "2017-09-29", + "asOf": "2018-02-01T00:00:00Z", + "selectionBasis": "latest accepted filing among locally ingested versions", + "accessionNo": "0001564590-17-024189", + "form": "10-K", + "amendmentNumber": 0, + "acceptedAt": "2017-11-21T16:32:41Z", + "ingestedAt": "2017-11-21T16:40:00Z", + "amendmentScope": [ + "Original annual filing" + ], + "facts": { + "basicEpsUsdPerShare": 3.94, + "netEarningsUsdMillions": 117.387 + }, + "eligibleAccessions": [ + "0001564590-17-024189" + ], + "excludedNotYetIngested": [ + "0001564590-18-007244" + ] + }, + "source": "tests/shared_fixture.json", + "case": "Esterline Technologies fiscal 2017 Form 10-K and Form 10-K/A", + "historicalFacts": { + "originalAccession": "0001564590-17-024189", + "originalAcceptedAt": "2017-11-21T16:32:41Z", + "amendmentAccession": "0001564590-18-007244", + "amendmentAcceptedAt": "2018-03-30T14:43:54Z", + "basicEpsAsReported": 3.94, + "basicEpsRestated": 3.75 + }, + "syntheticAvailabilityAssumptions": { + "originalIngestedAt": "2017-11-21T16:40:00Z", + "amendmentIngestedAt": "2018-03-30T15:00:00Z" + }, + "derivedDifference": { + "basicEpsChangeUsdPerShare": -0.19, + "interpretation": "A revision of the historical filing value, not evidence of a market return or a new fiscal-period result." + }, + "evidenceNote": "Accession, form, report-period, acceptance, and EPS facts are from SEC filing records. ingestedAt and query asOf values are synthetic local-system assumptions." } diff --git a/test/fixtures/D04-F01-A01.json b/test/fixtures/D04-F01-A01.json index 6679754..3666259 100644 --- a/test/fixtures/D04-F01-A01.json +++ b/test/fixtures/D04-F01-A01.json @@ -1,5 +1,47 @@ { - "topic_id": "D04-F01-A01", + "topicId": "D04-F01-A01", + "input": { + "session_date": "2026-01-05", + "session_id": "regular", + "session_timezone": "UTC", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-3", + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted", + "price_tolerance": 0, + "calculation_as_of": "2026-01-05T22:00:00Z", + "revisions": [ + { + "revision_id": "R1", + "revision_sequence": 1, + "supersedes_revision_id": null, + "effective_at": "2026-01-05T21:00:00Z", + "available_at": "2026-01-05T21:05:00Z", + "is_final": true, + "members": [ + {"listing_id": "L-A", "security_id": "S-A", "ticker": "A", "state": "eligible", "current_price": 11, "prior_comparable_price": 10}, + {"listing_id": "L-D", "security_id": "S-D", "ticker": "D", "state": "eligible", "current_price": 9, "prior_comparable_price": 10}, + {"listing_id": "L-U", "security_id": "S-U", "ticker": "U", "state": "eligible", "current_price": 10, "prior_comparable_price": 10} + ] + } + ] + }, + "expected": { + "status": "ready", + "direction": "balanced", + "selected_revision_id": "R1", + "advances": 1, + "declines": 1, + "unchanged": 1, + "excluded": 0, + "unclassified": 0, + "universe_size": 3, + "mover_count": 2, + "classified_count": 3, + "coverage_ratio": 1, + "net_advances": 0, + "is_provisional": false + }, "fixture": "../datasets/net-advances-fixtures.json", "query_before_correction": { "calculation_as_of": "2026-01-05T21:30:00Z", diff --git a/test/fixtures/D04-F01-A02.json b/test/fixtures/D04-F01-A02.json index f8629e7..4d4a5b4 100644 --- a/test/fixtures/D04-F01-A02.json +++ b/test/fixtures/D04-F01-A02.json @@ -1,14 +1,50 @@ { - "topic_id": "D04-F01-A02", + "topicId": "D04-F01-A02", "synthetic": true, "input": { + "series_id": "SYNTH-ADR", + "record_id": "ADR-R1", + "session_date": "2026-01-05", + "effective_at": "2026-01-05T21:00:00Z", + "available_at": "2026-01-05T21:05:00Z", + "venue_id": "SYNTH-X", + "calendar_id": "SYNTH-CAL", + "session_id": "regular", + "universe_id": "SYNTH-100", + "universe_revision": "U1", + "listing_id_scheme": "synthetic-listing-id", + "security_type_policy": "common-equity", + "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted", + "revision": 1, + "supersedes_record_id": null, "advances": 60, "declines": 30, "unchanged": 10, - "excluded_buckets_total": 0, + "new_or_no_prior_close": 0, + "halted": 0, + "suspended": 0, + "delisted": 0, + "missing": 0, + "unclassified": 0, "universe_size": 100, "is_final": true }, + "expected": { + "evidence_state": "resolved", + "ratio_state": "finite", + "advance_decline_ratio": 2, + "direction": "advances_dominant", + "observed_partition_ratio": 2, + "selected_record_id": "ADR-R1", + "selected_revision": 1, + "excluded_count": 0, + "mover_count": 90, + "classified_count": 100, + "coverage_ratio": 1, + "is_provisional": false, + "reasons": [] + }, "derivation": { "partition_sum": 100, "mover_count": 90, diff --git a/test/fixtures/D04-F01-A03.json b/test/fixtures/D04-F01-A03.json index b9247f6..10d8309 100644 --- a/test/fixtures/D04-F01-A03.json +++ b/test/fixtures/D04-F01-A03.json @@ -1,4 +1,61 @@ { + "topicId": "D04-F01-A03", + "input": { + "contract": { + "metric": "cumulative_issue_count_advance_decline_line", + "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-5", + "calendar_id": "SYNTH-CAL", + "session_type": "regular", + "comparison_basis": "comparable-prior-close", + "seed": 0, + "seed_lineage_id": "SEED-0", + "seed_effective_at": "2026-01-04T21:00:00Z", + "seed_available_at": "2026-01-04T21:05:00Z", + "expected_sessions": [ + {"session_sequence": 1, "session_date": "2026-01-05"}, + {"session_sequence": 2, "session_date": "2026-01-06"} + ] + }, + "events": [ + { + "event_id": "AD-1", "ingest_sequence": 1, "revision_number": 1, + "supersedes_event_id": null, "action": "upsert", "session_sequence": 1, + "session_date": "2026-01-05", "effective_at": "2026-01-05T21:00:00Z", + "available_at": "2026-01-05T21:05:00Z", "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", "venue_id": "SYNTH-X", + "universe_id": "SYNTH-5", "calendar_id": "SYNTH-CAL", "session_type": "regular", + "comparison_basis": "comparable-prior-close", "universe_snapshot_id": "U-1", + "is_final": true, "source_evidence_state": "ready", "advances": 3, + "declines": 1, "unchanged": 1, "excluded": 0, "unclassified": 0, "universe_size": 5 + }, + { + "event_id": "AD-2", "ingest_sequence": 2, "revision_number": 1, + "supersedes_event_id": null, "action": "upsert", "session_sequence": 2, + "session_date": "2026-01-06", "effective_at": "2026-01-06T21:00:00Z", + "available_at": "2026-01-06T21:05:00Z", "series_id": "SYNTH-AD", + "continuity_id": "SYNTH-CONTINUITY", "venue_id": "SYNTH-X", + "universe_id": "SYNTH-5", "calendar_id": "SYNTH-CAL", "session_type": "regular", + "comparison_basis": "comparable-prior-close", "universe_snapshot_id": "U-2", + "is_final": true, "source_evidence_state": "ready", "advances": 1, + "declines": 2, "unchanged": 2, "excluded": 0, "unclassified": 0, "universe_size": 5 + } + ], + "knowledgeCutoff": "2026-01-06T22:00:00Z" + }, + "expected": { + "status": "resolved", + "reasons": [], + "final_value": 1, + "contains_provisional": false, + "ignored_future_event_count": 0, + "points": { + "0": {"session_sequence": 1, "net_advances": 2, "cumulative_line": 2}, + "1": {"session_sequence": 2, "net_advances": -1, "cumulative_line": 1} + } + }, "data_class": "synthetic", "seed": 0, "original": { diff --git a/test/fixtures/D04-F01-A04.json b/test/fixtures/D04-F01-A04.json index b1bcbfa..ca36106 100644 --- a/test/fixtures/D04-F01-A04.json +++ b/test/fixtures/D04-F01-A04.json @@ -1,4 +1,50 @@ { + "topicId": "D04-F01-A04", + "input": { + "records": [ + { + "event_id": "NAD-1", "revision": 1, "supersedes_revision": null, + "event_type": "upsert", "session_sequence": 1, "session_date": "2026-01-05", + "effective_at": "2026-01-05T21:00:00Z", "available_at": "2026-01-05T21:05:00Z", + "venue_id": "SYNTH-X", "universe_id": "SYNTH-100", "calendar_id": "SYNTH-CAL", + "session": "regular", "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted", "stable_id_scheme": "synthetic-id", + "methodology_id": "mover-normalized-v1", "denominator_policy": "movers", + "seed": 0, "scale": 100, "roster_complete": true, "classification_complete": true, + "advances": 60, "declines": 30, "unchanged": 10, "excluded": 0, + "unclassified": 0, "universe_size": 100 + }, + { + "event_id": "NAD-2", "revision": 1, "supersedes_revision": null, + "event_type": "upsert", "session_sequence": 2, "session_date": "2026-01-06", + "effective_at": "2026-01-06T21:00:00Z", "available_at": "2026-01-06T21:05:00Z", + "venue_id": "SYNTH-X", "universe_id": "SYNTH-100", "calendar_id": "SYNTH-CAL", + "session": "regular", "comparison_basis": "comparable-prior-close", + "corporate_action_policy": "provider-adjusted", "stable_id_scheme": "synthetic-id", + "methodology_id": "mover-normalized-v1", "denominator_policy": "movers", + "seed": 0, "scale": 100, "roster_complete": true, "classification_complete": true, + "advances": 35, "declines": 55, "unchanged": 10, "excluded": 0, + "unclassified": 0, "universe_size": 100 + } + ], + "options": { + "cutoff": "2026-01-06T22:00:00Z", + "expectedStartSequence": 1, + "expectedEndSequence": 2, + "initialValue": 0, + "scale": 100, + "minimumCoverage": 0.95 + } + }, + "expected": { + "state": "resolved", + "reason_codes": [], + "ignored_future_revisions": 0, + "points": { + "0": {"net_advances": 30, "mover_count": 90, "scaled_contribution": 33.33333333333333, "normalized_line": 33.33333333333333}, + "1": {"net_advances": -20, "mover_count": 90, "scaled_contribution": -22.22222222222222, "normalized_line": 11.111111111111107} + } + }, "classification": "synthetic", "initial_value": "0", "scale": "100", diff --git a/test/fixtures/D04-F01-A05.json b/test/fixtures/D04-F01-A05.json index 0bf9b1a..5d0546a 100644 --- a/test/fixtures/D04-F01-A05.json +++ b/test/fixtures/D04-F01-A05.json @@ -1,5 +1,35 @@ { - "topic_id": "D04-F01-A05", + "topicId": "D04-F01-A05", + "input": { + "decision_time": "2026-01-05T22:00:00Z", + "metric_variant": "raw_issue_count", + "records": [ + { + "record_id": "ABI-R1", "revision": 1, "supersedes_record_id": null, + "kind": "observation", "effective_at": "2026-01-05T21:00:00Z", + "available_at": "2026-01-05T21:05:00Z", "is_final": true, + "session_date": "2026-01-05", "venue_id": "SYNTH-X", "universe_id": "SYNTH-100", + "universe_revision": "U1", "session_id": "regular", "calendar_id": "SYNTH-CAL", + "comparison_basis": "comparable-prior-close", "corporate_action_policy": "provider-adjusted", + "listing_identifier_scheme": "synthetic-listing-id", "advances": 60, "declines": 30, + "unchanged": 8, "excluded": 2, "missing": 0, "unclassified": 0, "universe_size": 100 + } + ] + }, + "expected": { + "evaluation_state": "resolved", + "publishable": true, + "reason_codes": [], + "record_id": "ABI-R1", + "revision": 1, + "is_provisional": false, + "net_advances": 30, + "absolute_breadth_index": 30, + "mover_count": 90, + "classified_count": 98, + "coverage_ratio": 0.98, + "breadth_state": "advances_imbalanced" + }, "label": "Synthetic resolved examples", "note": "These examples satisfy the package's complete point-in-time contract; they are not historical observations.", "rows": [ diff --git a/test/fixtures/D04-F02-A01.json b/test/fixtures/D04-F02-A01.json index c68c8bc..606c1c0 100644 --- a/test/fixtures/D04-F02-A01.json +++ b/test/fixtures/D04-F02-A01.json @@ -1,5 +1,20 @@ { - "topic_id": "D04-F02-A01", + "topicId": "D04-F02-A01", + "input": [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 100, -100, 0, -100 + ], + "expected": { + "38": {"observation": 39, "fast_ema": 0, "slow_ema": 0, "oscillator": 0, "status": "ready"}, + "39": {"observation": 40, "fast_ema": 10, "slow_ema": 5, "oscillator": 5, "status": "ready"}, + "40": {"observation": 41, "fast_ema": 19, "slow_ema": 9.75, "oscillator": 9.25, "status": "ready"}, + "41": {"observation": 42, "fast_ema": 7.1, "slow_ema": 4.2625, "oscillator": 2.8375, "status": "ready"}, + "42": {"observation": 43, "fast_ema": 6.39, "slow_ema": 4.049375, "oscillator": 2.340625, "status": "ready"}, + "43": {"observation": 44, "fast_ema": -4.249, "slow_ema": -1.15309375, "oscillator": -3.09590625, "status": "ready"} + }, "metric": "traditional_mcclellan_oscillator", "convention": { "input": "advances_minus_declines", diff --git a/test/fixtures/D04-F02-A02.json b/test/fixtures/D04-F02-A02.json index 3884066..628cd4b 100644 --- a/test/fixtures/D04-F02-A02.json +++ b/test/fixtures/D04-F02-A02.json @@ -1,5 +1,41 @@ { - "topic_id": "D04-F02-A02", + "topicId": "D04-F02-A02", + "input": { + "records": [ + { + "session_date": "2026-01-02", + "session_sequence": 1, + "effective_at": "2026-01-02T21:00:00Z", + "available_at": "2026-01-02T21:20:00Z", + "revision": 0, + "event_type": "upsert", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-STABLE-200", + "methodology_id": "close-vs-comparable-prior-close-v1", + "calendar_id": "SYNTH-WEEKDAY", + "volume_unit": "shares", + "volume_adjustment_basis": "reported-unadjusted", + "advances": 100, + "declines": 100, + "unchanged": 20, + "excluded": 0, + "unclassified": 0, + "universe_size": 220, + "up_volume": 1000000, + "down_volume": 1000000, + "unchanged_volume": 100000, + "total_volume": 2100000 + } + ], + "cutoff": "2026-04-01T00:00:00Z" + }, + "expected": { + "status": "resolved", + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 + }, "classification": "synthetic teaching input and author-derived arithmetic", "first_ready": { "observation": 39, diff --git a/test/fixtures/D04-F02-A03.json b/test/fixtures/D04-F02-A03.json index 2918d31..380c22a 100644 --- a/test/fixtures/D04-F02-A03.json +++ b/test/fixtures/D04-F02-A03.json @@ -1,5 +1,41 @@ { - "topic_id": "D04-F02-A03", + "topicId": "D04-F02-A03", + "input": { + "records": [ + { + "session_date": "2026-01-02", + "session_sequence": 1, + "effective_at": "2026-01-02T21:00:00Z", + "available_at": "2026-01-02T21:20:00Z", + "revision": 0, + "event_type": "upsert", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-STABLE-200", + "methodology_id": "close-vs-comparable-prior-close-v1", + "calendar_id": "SYNTH-WEEKDAY", + "volume_unit": "shares", + "volume_adjustment_basis": "reported-unadjusted", + "advances": 100, + "declines": 100, + "unchanged": 20, + "excluded": 0, + "unclassified": 0, + "universe_size": 220, + "up_volume": 1000000, + "down_volume": 1000000, + "unchanged_volume": 100000, + "total_volume": 2100000 + } + ], + "cutoff": "2026-04-01T00:00:00Z" + }, + "expected": { + "status": "resolved", + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 + }, "classification": "synthetic teaching input and author-derived arithmetic", "first_ready": { "observation": 39, diff --git a/test/fixtures/D04-F02-A04.json b/test/fixtures/D04-F02-A04.json index b9683e8..c4ca7c0 100644 --- a/test/fixtures/D04-F02-A04.json +++ b/test/fixtures/D04-F02-A04.json @@ -1,5 +1,41 @@ { - "topic_id": "D04-F02-A04", + "topicId": "D04-F02-A04", + "input": { + "records": [ + { + "session_date": "2026-01-02", + "session_sequence": 1, + "effective_at": "2026-01-02T21:00:00Z", + "available_at": "2026-01-02T21:20:00Z", + "revision": 0, + "event_type": "upsert", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-STABLE-200", + "methodology_id": "close-vs-comparable-prior-close-v1", + "calendar_id": "SYNTH-WEEKDAY", + "volume_unit": "shares", + "volume_adjustment_basis": "reported-unadjusted", + "advances": 100, + "declines": 100, + "unchanged": 20, + "excluded": 0, + "unclassified": 0, + "universe_size": 220, + "up_volume": 1000000, + "down_volume": 1000000, + "unchanged_volume": 100000, + "total_volume": 2100000 + } + ], + "cutoff": "2026-04-01T00:00:00Z" + }, + "expected": { + "status": "resolved", + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 + }, "classification": "synthetic teaching input and author-derived arithmetic", "first_ready": { "observation": 39, diff --git a/test/fixtures/D04-F02-A05.json b/test/fixtures/D04-F02-A05.json index 10b531e..09005b3 100644 --- a/test/fixtures/D04-F02-A05.json +++ b/test/fixtures/D04-F02-A05.json @@ -1,5 +1,41 @@ { - "topic_id": "D04-F02-A05", + "topicId": "D04-F02-A05", + "input": { + "records": [ + { + "session_date": "2026-01-02", + "session_sequence": 1, + "effective_at": "2026-01-02T21:00:00Z", + "available_at": "2026-01-02T21:20:00Z", + "revision": 0, + "event_type": "upsert", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-STABLE-200", + "methodology_id": "close-vs-comparable-prior-close-v1", + "calendar_id": "SYNTH-WEEKDAY", + "volume_unit": "shares", + "volume_adjustment_basis": "reported-unadjusted", + "advances": 100, + "declines": 100, + "unchanged": 20, + "excluded": 0, + "unclassified": 0, + "universe_size": 220, + "up_volume": 1000000, + "down_volume": 1000000, + "unchanged_volume": 100000, + "total_volume": 2100000 + } + ], + "cutoff": "2026-04-01T00:00:00Z" + }, + "expected": { + "status": "resolved", + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 + }, "classification": "synthetic teaching input and author-derived arithmetic", "first_ready": { "observation": 39, diff --git a/test/fixtures/D04-F02-A06.json b/test/fixtures/D04-F02-A06.json index 5ea13c7..be12bda 100644 --- a/test/fixtures/D04-F02-A06.json +++ b/test/fixtures/D04-F02-A06.json @@ -1,5 +1,41 @@ { - "topic_id": "D04-F02-A06", + "topicId": "D04-F02-A06", + "input": { + "records": [ + { + "session_date": "2026-01-02", + "session_sequence": 1, + "effective_at": "2026-01-02T21:00:00Z", + "available_at": "2026-01-02T21:20:00Z", + "revision": 0, + "event_type": "upsert", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-STABLE-200", + "methodology_id": "close-vs-comparable-prior-close-v1", + "calendar_id": "SYNTH-WEEKDAY", + "volume_unit": "shares", + "volume_adjustment_basis": "reported-unadjusted", + "advances": 100, + "declines": 100, + "unchanged": 20, + "excluded": 0, + "unclassified": 0, + "universe_size": 220, + "up_volume": 1000000, + "down_volume": 1000000, + "unchanged_volume": 100000, + "total_volume": 2100000 + } + ], + "cutoff": "2026-04-01T00:00:00Z" + }, + "expected": { + "status": "resolved", + "latest_oscillator": null, + "latest_index_value": null, + "ignored_future_records": 0 + }, "classification": "synthetic teaching input and author-derived arithmetic", "first_ready": { "observation": 39, diff --git a/test/fixtures/D04-F03-A01.json b/test/fixtures/D04-F03-A01.json index 89ea983..02b7236 100644 --- a/test/fixtures/D04-F03-A01.json +++ b/test/fixtures/D04-F03-A01.json @@ -1,5 +1,33 @@ { - "topic_id": "D04-F03-A01", + "topicId": "D04-F03-A01", + "input": { + "records": [ + { + "session_date": "2026-01-15", + "available_at": "2026-01-15T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 2, + "new_lows": 10, + "eligible_issues": 12, + "overlap_issues": 0 + } + ], + "decisionTime": "2026-03-01T00:00:00Z" + }, + "expected": { + "0": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": -8, + "status": "resolved", + "reason": null + } + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "session_date": "2026-01-15", diff --git a/test/fixtures/D04-F03-A02.json b/test/fixtures/D04-F03-A02.json index b6b553f..7f41008 100644 --- a/test/fixtures/D04-F03-A02.json +++ b/test/fixtures/D04-F03-A02.json @@ -1,5 +1,33 @@ { - "topic_id": "D04-F03-A02", + "topicId": "D04-F03-A02", + "input": { + "records": [ + { + "session_date": "2026-01-15", + "available_at": "2026-01-15T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 2, + "new_lows": 10, + "eligible_issues": 12, + "overlap_issues": 0 + } + ], + "decisionTime": "2026-03-01T00:00:00Z" + }, + "expected": { + "0": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": 0.2, + "status": "resolved", + "reason": null + } + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "session_date": "2026-01-15", diff --git a/test/fixtures/D04-F03-A03.json b/test/fixtures/D04-F03-A03.json index f3f0aa5..00eef81 100644 --- a/test/fixtures/D04-F03-A03.json +++ b/test/fixtures/D04-F03-A03.json @@ -1,5 +1,150 @@ { - "topic_id": "D04-F03-A03", + "topicId": "D04-F03-A03", + "input": { + "records": [ + { + "session_date": "2026-01-06", + "available_at": "2026-01-06T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-07", + "available_at": "2026-01-07T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-08", + "available_at": "2026-01-08T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-09", + "available_at": "2026-01-09T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-10", + "available_at": "2026-01-10T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-11", + "available_at": "2026-01-11T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-12", + "available_at": "2026-01-12T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-13", + "available_at": "2026-01-13T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-14", + "available_at": "2026-01-14T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 7, + "new_lows": 5, + "eligible_issues": 12, + "overlap_issues": 0 + }, + { + "session_date": "2026-01-15", + "available_at": "2026-01-15T21:30:00Z", + "source_evidence_state": "ready", + "venue_id": "SYNTH-X", + "universe_id": "SYNTH-HIGH-LOW-12", + "methodology_id": "synthetic-high-low-v1", + "lookback_sessions": 252, + "new_highs": 2, + "new_lows": 10, + "eligible_issues": 12, + "overlap_issues": 0 + } + ], + "decisionTime": "2026-03-01T00:00:00Z" + }, + "expected": { + "9": { + "session_date": "2026-01-15", + "new_highs": 2, + "new_lows": 10, + "value": 54.166666666666664, + "status": "resolved", + "reason": null + } + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "session_date": "2026-01-15", diff --git a/test/fixtures/D04-F03-A04.json b/test/fixtures/D04-F03-A04.json index ca399b5..6272daf 100644 --- a/test/fixtures/D04-F03-A04.json +++ b/test/fixtures/D04-F03-A04.json @@ -1,5 +1,31 @@ { - "topic_id": "D04-F03-A04", + "topicId": "D04-F03-A04", + "input": { + "snapshot": { + "window_sessions": 20, + "price_field": "adjusted_close", + "securities": [ + { + "security_id": "SYNTH-ABOVE", + "member_at_session": true, + "source_evidence_state": "ready", + "available_at": "2026-06-30T21:30:00Z", + "adjustment_basis": "split-adjusted-price-return", + "prices": [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 120] + } + ] + }, + "decisionTime": "2026-06-30T22:00:00Z" + }, + "expected": { + "status": "resolved", + "reason": null, + "window_sessions": 20, + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "status": "resolved", diff --git a/test/fixtures/D04-F03-A05.json b/test/fixtures/D04-F03-A05.json index 6a8769e..df48b1d 100644 --- a/test/fixtures/D04-F03-A05.json +++ b/test/fixtures/D04-F03-A05.json @@ -1,5 +1,31 @@ { - "topic_id": "D04-F03-A05", + "topicId": "D04-F03-A05", + "input": { + "snapshot": { + "window_sessions": 50, + "price_field": "adjusted_close", + "securities": [ + { + "security_id": "SYNTH-ABOVE", + "member_at_session": true, + "source_evidence_state": "ready", + "available_at": "2026-06-30T21:30:00Z", + "adjustment_basis": "split-adjusted-price-return", + "prices": [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 120] + } + ] + }, + "decisionTime": "2026-06-30T22:00:00Z" + }, + "expected": { + "status": "resolved", + "reason": null, + "window_sessions": 50, + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "status": "resolved", diff --git a/test/fixtures/D04-F03-A06.json b/test/fixtures/D04-F03-A06.json index 8048581..3ab4e57 100644 --- a/test/fixtures/D04-F03-A06.json +++ b/test/fixtures/D04-F03-A06.json @@ -1,5 +1,31 @@ { - "topic_id": "D04-F03-A06", + "topicId": "D04-F03-A06", + "input": { + "snapshot": { + "window_sessions": 200, + "price_field": "adjusted_close", + "securities": [ + { + "security_id": "SYNTH-ABOVE", + "member_at_session": true, + "source_evidence_state": "ready", + "available_at": "2026-06-30T21:30:00Z", + "adjustment_basis": "split-adjusted-price-return", + "prices": [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 120] + } + ] + }, + "decisionTime": "2026-06-30T22:00:00Z" + }, + "expected": { + "status": "resolved", + "reason": null, + "window_sessions": 200, + "eligible_count": 1, + "above_count": 1, + "equal_count": 0, + "percent_above": 100 + }, "source_class": "synthetic teaching input and author-derived arithmetic", "canonical_display_state": { "status": "resolved", diff --git a/test/fixtures/D06-F01-A01.json b/test/fixtures/D06-F01-A01.json index 08a0748..41ec83d 100644 --- a/test/fixtures/D06-F01-A01.json +++ b/test/fixtures/D06-F01-A01.json @@ -1,16 +1,44 @@ { "topic_id": "D06-F01-A01", "input": { - "timestamp": "2026-01-05T10:00:00Z", - "instrument_id": "SYNTH:ABC", - "interval": "5m", + "candle": { + "timestamp": "2026-01-05T10:00:00Z", + "instrument_id": "SYNTH:ABC", + "interval": "5m", + "open": 100, + "high": 108, + "low": 97, + "close": 105, + "is_closed": true, + "price_basis": "raw-trades", + "session": "synthetic-utc" + }, + "directionEpsilon": 0 + }, + "expected": { "open": 100, "high": 108, "low": 97, "close": 105, + "timestamp": "2026-01-05T10:00:00Z", + "instrument_id": "SYNTH:ABC", + "interval": "5m", "is_closed": true, + "volume": null, "price_basis": "raw-trades", - "session": "synthetic-utc" + "session": "synthetic-utc", + "body_high": 105, + "body_low": 100, + "body": 5, + "upper_shadow": 3, + "lower_shadow": 3, + "range": 11, + "direction": "bullish", + "body_to_range": 0.45454545454545453, + "upper_shadow_to_range": 0.2727272727272727, + "lower_shadow_to_range": 0.2727272727272727, + "open_position": 0.2727272727272727, + "close_position": 0.7272727272727273 }, "direction_epsilon": 0, "output": { diff --git a/test/fixtures/D06-F01-A02.json b/test/fixtures/D06-F01-A02.json index 0cac37d..da8cf54 100644 --- a/test/fixtures/D06-F01-A02.json +++ b/test/fixtures/D06-F01-A02.json @@ -1,12 +1,38 @@ { "topic_id": "D06-F01-A02", "input": { - "prior_closed_bodies": [1, 2, 2, 3, 12], - "current_body": 4, - "current_range": 6, - "window": 5, - "min_periods": 5, - "tick_size": 0.01 + "observation": { + "timestamp": "2026-01-05T10:25:00Z", + "instrument_id": "SYNTH:ABC", + "interval": "5m", + "body": 4, + "range": 6, + "is_closed": true, + "price_basis": "raw", + "session": "continuous" + }, + "priorClosedBodies": [1, 2, 2, 3, 12], + "configInput": { + "window": 5, + "min_periods": 5, + "tick_size": 0.01, + "thresholds": { + "tiny_max": 0.25, + "small_max": 0.75, + "long_min": 1.5 + } + } + }, + "expected": { + "status": "ready", + "body_class": "long", + "body_score": 2, + "raw_scale": 2, + "effective_scale": 2, + "scale_floor_applied": false, + "history_count": 5, + "body_to_current_range": 0.6666666666666666, + "is_provisional": false }, "derivation": { "sorted_reference": [1, 2, 2, 3, 12], diff --git a/test/fixtures/D07-F01-A01.json b/test/fixtures/D07-F01-A01.json index fe8d65b..b0590ef 100644 --- a/test/fixtures/D07-F01-A01.json +++ b/test/fixtures/D07-F01-A01.json @@ -1,8 +1,9 @@ { - "topic_id": "D07-F01-A01", + "topicId": "D07-F01-A01", "title": "Three-observation trailing SMA", "window": 3, "values": [10, 13, 12, 15, 14, 18], + "input": {"values": [10, 13, 12, 15, 14, 18], "window": 3}, "expected": [null, null, 11.666666666666666, 13.333333333333334, 13.666666666666666, 15.666666666666666], "steps": [ {"observation": 1, "incoming": 10, "outgoing": null, "window_values": [10], "window_sum": null, "sma": null, "status": "warming"}, diff --git a/test/fixtures/D07-F01-A02.json b/test/fixtures/D07-F01-A02.json index 7bbc18d..0e24c76 100644 --- a/test/fixtures/D07-F01-A02.json +++ b/test/fixtures/D07-F01-A02.json @@ -1,5 +1,7 @@ { - "topic_id": "D07-F01-A02", + "topicId": "D07-F01-A02", + "input": {"values": [10, 13, 12, 15, 14, 18], "span": 3}, + "expected": [null, null, 11.666666666666666, 13.333333333333334, 13.666666666666666, 15.833333333333334], "metric": "exponential_moving_average", "convention": { "span": 3, diff --git a/test/fixtures/D07-F01-A03.json b/test/fixtures/D07-F01-A03.json index 90621d7..ce08d63 100644 --- a/test/fixtures/D07-F01-A03.json +++ b/test/fixtures/D07-F01-A03.json @@ -1,10 +1,11 @@ { - "topic_id": "D07-F01-A03", + "topicId": "D07-F01-A03", "title": "Three-observation linear WMA", "window": 3, "weights_oldest_to_newest": [1, 2, 3], "denominator": 6, "values": [10, 13, 12, 15, 14, 18], + "input": {"values": [10, 13, 12, 15, 14, 18], "window": 3}, "expected": [null, null, 12, 13.666666666666666, 14, 16.166666666666668], "steps": [ {"observation": 1, "window_values": [10], "weighted_sum": null, "wma": null, "status": "warming"}, diff --git a/test/fixtures/D07-F01-A04.json b/test/fixtures/D07-F01-A04.json index f9b46fe..36ac05d 100644 --- a/test/fixtures/D07-F01-A04.json +++ b/test/fixtures/D07-F01-A04.json @@ -1,5 +1,7 @@ { - "topic_id": "D07-F01-A04", + "topicId": "D07-F01-A04", + "input": {"values": [10, 13, 12, 15, 14, 18], "period": 3}, + "expected": [null, null, 11.666666666666666, 12.777777777777779, 13.185185185185185, 14.790123456790123], "series_id": "synthetic-demo", "unit": "index points", "frequency": "one observation step", diff --git a/test/fixtures/D07-F01-A05.json b/test/fixtures/D07-F01-A05.json index 66ed0e1..4d9ab9b 100644 --- a/test/fixtures/D07-F01-A05.json +++ b/test/fixtures/D07-F01-A05.json @@ -1,5 +1,12 @@ { - "topic_id": "D07-F01-A05", + "topicId": "D07-F01-A05", + "input": {"values": [10, 13, 12, 15, 14, 18, 17, 20], "span": 3}, + "expected": { + "4": {"dema": 14.444444444444445, "status": "ready"}, + "5": {"dema": 17.305555555555557, "status": "ready"}, + "6": {"dema": 17.444444444444443, "status": "ready"}, + "7": {"dema": 19.618055555555557, "status": "ready"} + }, "convention": { "span": 3, "alpha": "1/2", diff --git a/test/fixtures/D07-F01-A06.json b/test/fixtures/D07-F01-A06.json index 50583dd..ec79569 100644 --- a/test/fixtures/D07-F01-A06.json +++ b/test/fixtures/D07-F01-A06.json @@ -1,5 +1,12 @@ { - "topic_id": "D07-F01-A06", + "topicId": "D07-F01-A06", + "input": {"values": [10, 13, 12, 15, 14, 18, 17, 20, 19, 22], "span": 3}, + "expected": { + "6": {"ema1": 16.416666666666664, "ema2": 15.388888888888888, "ema3": 14.212962962962962, "tema": 17.29629629629629, "status": "ready"}, + "7": {"tema": 19.73495370370371, "status": "ready"}, + "8": {"tema": 19.311921296296298, "status": "ready"}, + "9": {"tema": 21.703703703703713, "status": "ready"} + }, "series_id": "synthetic-tema-demo", "unit": "index points", "frequency": "one observation step", diff --git a/test/fixtures/D07-F01-A07.json b/test/fixtures/D07-F01-A07.json index 65797ec..0a20a26 100644 --- a/test/fixtures/D07-F01-A07.json +++ b/test/fixtures/D07-F01-A07.json @@ -1,16 +1,65 @@ { - "topic_id": "D07-F01-A07", - "window": 5, - "rounding_policy": "floor", - "half_length": 2, - "root_length": 2, - "values": [10, 13, 12, 15, 14, 18, 17, 20, 19, 22], - "first_ready_observation": 6, - "first_ready_components": { - "short_wma": 16.666666666666668, - "long_wma": 15.2, - "raw_hull": 18.133333333333336, - "previous_raw_hull": 15.200000000000001, - "hull_ma": 17.15555555555556 - } + "topicId": "D07-F01-A07", + "bars": [ + {"close": 10}, {"close": 13}, {"close": 12}, {"close": 15}, {"close": 14}, + {"close": 18}, {"close": 17}, {"close": 20}, {"close": 19}, {"close": 22} + ], + "canonical_parameters": {"window": 5}, + "checkpoints": [ + {"index": 4, "shortWma": 14.333333333333334, "longWma": 13.466666666666667, "rawHull": 15.200000000000001, "hullMa": null}, + {"index": 5, "shortWma": 16.666666666666668, "longWma": 15.2, "rawHull": 18.133333333333336, "hullMa": 17.15555555555556}, + {"index": 9, "shortWma": 21, "longWma": 19.866666666666667, "rawHull": 22.133333333333333, "hullMa": 21.51111111111111} + ], + "contract": { + "rounding": "floor", + "weight_order": "oldest=1,newest=window", + "warm_up": "null", + "missing_values": "reject" + }, + "cases": [ + { + "name": "worked-window-five", + "values": [10, 13, 12, 15, 14, 18, 17, 20, 19, 22], + "window": 5, + "half_length": 2, + "root_length": 2, + "short_wma": [null, 12, 12.333333333333334, 14, 14.333333333333334, 16.666666666666668, 17.333333333333332, 19, 19.333333333333332, 21], + "long_wma": [null, null, null, null, 13.466666666666667, 15.2, 16.066666666666666, 17.666666666666668, 18.4, 19.866666666666667], + "raw_hull": [null, null, null, null, 15.200000000000001, 18.133333333333336, 18.599999999999998, 20.333333333333332, 20.266666666666666, 22.133333333333333], + "hull_ma": [null, null, null, null, null, 17.15555555555556, 18.444444444444443, 19.755555555555556, 20.288888888888888, 21.51111111111111] + }, + { + "name": "period-one-identity", + "values": [-2, 0, 7.5], + "window": 1, + "half_length": 1, + "root_length": 1, + "short_wma": [-2, 0, 7.5], + "long_wma": [-2, 0, 7.5], + "raw_hull": [-2, 0, 7.5], + "hull_ma": [-2, 0, 7.5] + }, + { + "name": "constant-window-six", + "values": [4, 4, 4, 4, 4, 4, 4, 4], + "window": 6, + "half_length": 3, + "root_length": 2, + "short_wma": [null, null, 4, 4, 4, 4, 4, 4], + "long_wma": [null, null, null, null, null, 4, 4, 4], + "raw_hull": [null, null, null, null, null, 4, 4, 4], + "hull_ma": [null, null, null, null, null, null, 4, 4] + }, + { + "name": "signed-weight-step-overshoot", + "values": [0, 0, 0, 0, 10, 10], + "window": 5, + "half_length": 2, + "root_length": 2, + "short_wma": [null, 0, 0, 0, 6.666666666666667, 10], + "long_wma": [null, null, null, null, 3.3333333333333335, 6], + "raw_hull": [null, null, null, null, 10, 14], + "hull_ma": [null, null, null, null, null, 12.666666666666666] + } + ] } diff --git a/test/fixtures/D07-F01-A08.json b/test/fixtures/D07-F01-A08.json index 48f0514..0f57c62 100644 --- a/test/fixtures/D07-F01-A08.json +++ b/test/fixtures/D07-F01-A08.json @@ -1,24 +1,66 @@ { - "classification": "synthetic teaching input with author-derived calculations", - "values": [100, 101, 102, 103, 104, 103, 104, 103, 104, 108, 109], - "parameters": { - "efficiency_period": 4, - "fast_period": 2, - "slow_period": 30 - }, - "internal_seed": { - "index": 3, - "value": 103, - "published": false - }, - "rows": [ - {"index": 4, "value": 104, "change": 4, "path_length": 4, "efficiency_ratio": 1, "smoothing_constant": 0.4444444444444444, "kama": 103.44444444444444}, - {"index": 5, "value": 103, "change": 2, "path_length": 4, "efficiency_ratio": 0.5, "smoothing_constant": 0.13365707018152384, "kama": 103.38504130214154}, - {"index": 6, "value": 104, "change": 2, "path_length": 4, "efficiency_ratio": 0.5, "smoothing_constant": 0.13365707018152384, "kama": 103.46723487997996}, - {"index": 7, "value": 103, "change": 0, "path_length": 4, "efficiency_ratio": 0, "smoothing_constant": 0.004162330905306971, "kama": 103.46529009379898}, - {"index": 8, "value": 104, "change": 0, "path_length": 4, "efficiency_ratio": 0, "smoothing_constant": 0.004162330905306971, "kama": 103.46751573336694}, - {"index": 9, "value": 108, "change": 5, "path_length": 7, "efficiency_ratio": 0.7142857142857143, "smoothing_constant": 0.24465256098970975, "kama": 104.57639961684428}, - {"index": 10, "value": 109, "change": 5, "path_length": 7, "efficiency_ratio": 0.7142857142857143, "smoothing_constant": 0.24465256098970975, "kama": 105.65864477937839} + "topicId": "D07-F01-A08", + "bars": [ + {"close": 100}, {"close": 101}, {"close": 102}, {"close": 103}, + {"close": 104}, {"close": 103}, {"close": 104}, {"close": 103}, + {"close": 104}, {"close": 105}, {"close": 106}, {"close": 105}, + {"close": 107}, {"close": 108}, {"close": 107}, {"close": 110} ], - "rounding": "No intermediate rounding; displayed values may be rounded." + "canonical_parameters": {"efficiencyPeriod": 10, "fastPeriod": 2, "slowPeriod": 30}, + "checkpoints": [ + {"index": 9, "efficiencyRatio": null, "smoothingConstant": null, "kama": null}, + {"index": 10, "efficiencyRatio": 0.6, "smoothingConstant": 0.18131113423517162, "kama": 105.18131113423517}, + {"index": 12, "efficiencyRatio": 0.45454545454545453, "smoothingConstant": 0.11439338995861552, "kama": 105.37438317823111}, + {"index": 15, "efficiencyRatio": 0.5384615384615384, "smoothingConstant": 0.15112736636790103, "kama": 106.38726276301216} + ], + "contract": { + "seed": "values[efficiency_period - 1], internal and unpublished", + "first_ready_index": "efficiency_period", + "zero_path_efficiency_ratio": 1, + "warm_up": "null", + "missing_values": "reject", + "rounding": "none" + }, + "cases": [ + { + "name": "canonical-default-10-2-30", + "values": [100, 101, 102, 103, 104, 103, 104, 103, 104, 105, 106, 105, 107, 108, 107, 110], + "efficiency_period": 10, + "fast_period": 2, + "slow_period": 30, + "efficiency_ratio": [null, null, null, null, null, null, null, null, null, null, 0.6, 0.4, 0.45454545454545453, 0.45454545454545453, 0.2727272727272727, 0.5384615384615384], + "smoothing_constant": [null, null, null, null, null, null, null, null, null, null, 0.18131113423517162, 0.09325471152734419, 0.11439338995861552, 0.11439338995861552, 0.0523215314625777, 0.15112736636790103], + "kama": [null, null, null, null, null, null, null, null, null, null, 105.18131113423517, 105.16440301671538, 105.37438317823111, 105.67473638720563, 105.74407620901866, 106.38726276301216] + }, + { + "name": "worked-path-4-2-30", + "values": [100, 101, 102, 103, 104, 103, 104, 103, 104, 108, 109], + "efficiency_period": 4, + "fast_period": 2, + "slow_period": 30, + "efficiency_ratio": [null, null, null, null, 1, 0.5, 0.5, 0, 0, 0.7142857142857143, 0.7142857142857143], + "smoothing_constant": [null, null, null, null, 0.4444444444444444, 0.13365707018152384, 0.13365707018152384, 0.004162330905306971, 0.004162330905306971, 0.24465256098970975, 0.24465256098970975], + "kama": [null, null, null, null, 103.44444444444444, 103.38504130214154, 103.46723487997996, 103.46529009379898, 103.46751573336694, 104.57639961684428, 105.65864477937839] + }, + { + "name": "zero-path-after-step", + "values": [100, 100, 100, 100, 110, 110, 110, 110, 110], + "efficiency_period": 4, + "fast_period": 2, + "slow_period": 30, + "efficiency_ratio": [null, null, null, null, 1, 1, 1, 1, 1], + "smoothing_constant": [null, null, null, null, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444], + "kama": [null, null, null, null, 104.44444444444444, 106.91358024691358, 108.28532235939643, 109.0474013107758, 109.47077850598656] + }, + { + "name": "constant-series", + "values": [7, 7, 7, 7, 7, 7, 7, 7], + "efficiency_period": 3, + "fast_period": 2, + "slow_period": 30, + "efficiency_ratio": [null, null, null, 1, 1, 1, 1, 1], + "smoothing_constant": [null, null, null, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444, 0.4444444444444444], + "kama": [null, null, null, 7, 7, 7, 7, 7] + } + ] } diff --git a/test/fixtures/D07-F01-A09.json b/test/fixtures/D07-F01-A09.json index d1d4587..dd4260e 100644 --- a/test/fixtures/D07-F01-A09.json +++ b/test/fixtures/D07-F01-A09.json @@ -1,132 +1,11162 @@ { - "classification": "author-derived calculation from synthetic teaching input", - "fixture": "../datasets/mama-fixtures.json#canonical-regime-shift", + "topicId": "D07-F01-A09", + "bars": [ + {"close": 100.0}, {"close": 100.517638}, {"close": 101.0}, {"close": 101.414214}, + {"close": 101.732051}, {"close": 101.931852}, {"close": 102.0}, {"close": 101.931852}, + {"close": 101.732051}, {"close": 101.414214}, {"close": 101.0}, {"close": 100.517638}, + {"close": 100.0}, {"close": 99.482362}, {"close": 99.0}, {"close": 98.585786}, + {"close": 98.267949}, {"close": 98.068148}, {"close": 98.0}, {"close": 98.068148}, + {"close": 98.267949}, {"close": 98.585786}, {"close": 99.0}, {"close": 99.482362}, + {"close": 100.0}, {"close": 100.517638}, {"close": 101.0}, {"close": 101.414214}, + {"close": 101.732051}, {"close": 101.931852}, {"close": 102.0}, {"close": 101.931852}, + {"close": 101.732051}, {"close": 101.414214}, {"close": 101.0}, {"close": 100.517638}, + {"close": 101.011419}, {"close": 101.488464}, {"close": 101.932873}, {"close": 102.330385}, + {"close": 102.669091}, {"close": 102.94003}, {"close": 103.137638}, {"close": 103.26003}, + {"close": 103.309091}, {"close": 103.290385}, {"close": 103.212873}, {"close": 103.088464}, + {"close": 102.931419}, {"close": 102.757638}, {"close": 102.583857}, {"close": 102.426812}, + {"close": 102.302403}, {"close": 102.224891}, {"close": 102.206185}, {"close": 102.255246}, + {"close": 102.377638}, {"close": 102.575246}, {"close": 102.846185}, {"close": 103.184891}, + {"close": 103.582403}, {"close": 104.026812}, {"close": 104.503857}, {"close": 104.997638}, + {"close": 105.491419}, {"close": 105.968464}, {"close": 106.412873}, {"close": 106.810385}, + {"close": 107.149091}, {"close": 107.42003}, {"close": 107.617638}, {"close": 107.74003}, + {"close": 109.012822}, {"close": 109.54003}, {"close": 109.012822}, {"close": 107.74003}, + {"close": 106.467238}, {"close": 105.94003}, {"close": 106.467238}, {"close": 107.74003}, + {"close": 109.012822}, {"close": 109.54003}, {"close": 109.012822}, {"close": 107.74003}, + {"close": 106.467238}, {"close": 105.94003}, {"close": 106.467238}, {"close": 107.74003}, + {"close": 109.012822}, {"close": 109.54003}, {"close": 109.012822}, {"close": 107.74003}, + {"close": 106.467238}, {"close": 105.94003}, {"close": 106.467238}, {"close": 107.74003}, + {"close": 107.78003}, {"close": 107.809312}, {"close": 107.82003}, {"close": 107.809312}, + {"close": 107.78003}, {"close": 107.74003}, {"close": 107.70003}, {"close": 107.670748}, + {"close": 107.66003}, {"close": 107.670748}, {"close": 107.70003}, {"close": 107.74003}, + {"close": 107.78003}, {"close": 107.809312}, {"close": 107.82003}, {"close": 107.809312}, + {"close": 107.78003}, {"close": 107.74003}, {"close": 107.70003}, {"close": 107.670748}, + {"close": 107.66003}, {"close": 107.670748}, {"close": 107.70003}, {"close": 107.74003}, + {"close": 107.86205}, {"close": 107.942818}, {"close": 107.946055}, {"close": 107.844838}, + {"close": 107.624838}, {"close": 107.286055}, {"close": 106.842818}, {"close": 106.32205}, + {"close": 105.76003}, {"close": 105.19801}, {"close": 104.677242}, {"close": 104.234005}, + {"close": 103.895222}, {"close": 103.675222}, {"close": 103.574005}, {"close": 103.577242}, + {"close": 103.65801}, {"close": 103.78003}, {"close": 103.90205}, {"close": 103.982818}, + {"close": 103.986055}, {"close": 103.884838}, {"close": 103.664838}, {"close": 103.326055} + ], + "canonical_parameters": {"fastLimit": 0.5, "slowLimit": 0.05}, + "checkpoints": [ + {"index": 32, "phase": -2.640381561915, "deltaPhase": 11.179106123472, "alpha": 0.05, "mama": 100.283132803372, "fama": 91.078423889195}, + {"index": 33, "phase": -17.016354301187, "deltaPhase": 14.375972739272, "alpha": 0.05, "mama": 100.339686863203, "fama": 91.309955463545}, + {"index": 47, "phase": -41.479381585387, "deltaPhase": 15.02764426943, "alpha": 0.05, "mama": 102.422090962023, "fama": 97.377856135634}, + {"index": 63, "phase": 56.490730105903, "deltaPhase": 12.926727974263, "alpha": 0.05, "mama": 103.406687914093, "fama": 100.677503934215}, + {"index": 71, "phase": -0.29948176035, "deltaPhase": 4.719062124572, "alpha": 0.105953256558, "mama": 105.22576360742, "fama": 101.724492008942}, + {"index": 72, "phase": -5.042077669848, "deltaPhase": 4.742595909498, "alpha": 0.105427493622, "mama": 105.625023681949, "fama": 101.930103647981}, + {"index": 79, "phase": -80.146549032588, "deltaPhase": 39.164916875397, "alpha": 0.05, "mama": 106.550063234142, "fama": 105.512403493614}, + {"index": 95, "phase": -70.253914512864, "deltaPhase": 62.506243546588, "alpha": 0.05, "mama": 107.235009349112, "fama": 107.0832571867}, + {"index": 96, "phase": 88.689744454216, "deltaPhase": 1.0, "alpha": 0.5, "mama": 107.507519674556, "fama": 107.189322808664}, + {"index": 119, "phase": 37.225902763516, "deltaPhase": 29.262512225095, "alpha": 0.05, "mama": 107.708336006236, "fama": 107.603888156388}, + {"index": 120, "phase": -2.106311140505, "deltaPhase": 39.33221390402, "alpha": 0.05, "mama": 107.716021705925, "fama": 107.606691495126}, + {"index": 127, "phase": -60.243344534554, "deltaPhase": 54.976868765635, "alpha": 0.05, "mama": 107.643066958931, "fama": 107.663868636861}, + {"index": 143, "phase": 66.23371246664, "deltaPhase": 20.80705766932, "alpha": 0.05, "mama": 104.378584497396, "fama": 106.227821220431} + ], + "topic_id": "D07-F01-A09", + "variant": "TA-Lib-compatible MAMA, zero unstable-period extension", + "generated_at": "2026-07-26", "parameters": { "fast_limit": 0.5, "slow_limit": 0.05 }, - "checkpoints": [ - { - "index": 32, - "value": 101.732051, - "phase": -2.640381561915, - "delta_phase": 11.179106123472, - "alpha": 0.05, - "mama": 100.283132803372, - "fama": 91.078423889195 - }, - { - "index": 33, - "value": 101.414214, - "phase": -17.016354301187, - "delta_phase": 14.375972739272, - "alpha": 0.05, - "mama": 100.339686863203, - "fama": 91.309955463545 - }, - { - "index": 47, - "value": 103.088464, - "phase": -41.479381585387, - "delta_phase": 15.02764426943, - "alpha": 0.05, - "mama": 102.422090962023, - "fama": 97.377856135634 - }, - { - "index": 63, - "value": 104.997638, - "phase": 56.490730105903, - "delta_phase": 12.926727974263, - "alpha": 0.05, - "mama": 103.406687914093, - "fama": 100.677503934215 - }, + "lookback": 32, + "processing_start": 12, + "rounding": "inputs 6 decimals; expected values 12 decimals; compute in float64 before rounding", + "source_and_license": "Author-generated deterministic synthetic data; CC BY 4.0 with the tutorial.", + "scenarios": [ { - "index": 71, - "value": 107.74003, - "phase": -0.29948176035, - "delta_phase": 4.719062124572, - "alpha": 0.105953256558, - "mama": 105.22576360742, - "fama": 101.724492008942 + "id": "canonical-regime-shift", + "classification": "synthetic teaching input", + "lesson": "A long cycle, rising trend, short cycle, quiet shelf, and reversal expose each adaptive state.", + "observations": [ + { + "index": 0, + "timestamp": "2026-01-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 1, + "timestamp": "2026-01-02T00:00:00Z", + "value": 100.517638 + }, + { + "index": 2, + "timestamp": "2026-01-03T00:00:00Z", + "value": 101.0 + }, + { + "index": 3, + "timestamp": "2026-01-04T00:00:00Z", + "value": 101.414214 + }, + { + "index": 4, + "timestamp": "2026-01-05T00:00:00Z", + "value": 101.732051 + }, + { + "index": 5, + "timestamp": "2026-01-06T00:00:00Z", + "value": 101.931852 + }, + { + "index": 6, + "timestamp": "2026-01-07T00:00:00Z", + "value": 102.0 + }, + { + "index": 7, + "timestamp": "2026-01-08T00:00:00Z", + "value": 101.931852 + }, + { + "index": 8, + "timestamp": "2026-01-09T00:00:00Z", + "value": 101.732051 + }, + { + "index": 9, + "timestamp": "2026-01-10T00:00:00Z", + "value": 101.414214 + }, + { + "index": 10, + "timestamp": "2026-01-11T00:00:00Z", + "value": 101.0 + }, + { + "index": 11, + "timestamp": "2026-01-12T00:00:00Z", + "value": 100.517638 + }, + { + "index": 12, + "timestamp": "2026-01-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 13, + "timestamp": "2026-01-14T00:00:00Z", + "value": 99.482362 + }, + { + "index": 14, + "timestamp": "2026-01-15T00:00:00Z", + "value": 99.0 + }, + { + "index": 15, + "timestamp": "2026-01-16T00:00:00Z", + "value": 98.585786 + }, + { + "index": 16, + "timestamp": "2026-01-17T00:00:00Z", + "value": 98.267949 + }, + { + "index": 17, + "timestamp": "2026-01-18T00:00:00Z", + "value": 98.068148 + }, + { + "index": 18, + "timestamp": "2026-01-19T00:00:00Z", + "value": 98.0 + }, + { + "index": 19, + "timestamp": "2026-01-20T00:00:00Z", + "value": 98.068148 + }, + { + "index": 20, + "timestamp": "2026-01-21T00:00:00Z", + "value": 98.267949 + }, + { + "index": 21, + "timestamp": "2026-01-22T00:00:00Z", + "value": 98.585786 + }, + { + "index": 22, + "timestamp": "2026-01-23T00:00:00Z", + "value": 99.0 + }, + { + "index": 23, + "timestamp": "2026-01-24T00:00:00Z", + "value": 99.482362 + }, + { + "index": 24, + "timestamp": "2026-01-25T00:00:00Z", + "value": 100.0 + }, + { + "index": 25, + "timestamp": "2026-01-26T00:00:00Z", + "value": 100.517638 + }, + { + "index": 26, + "timestamp": "2026-01-27T00:00:00Z", + "value": 101.0 + }, + { + "index": 27, + "timestamp": "2026-01-28T00:00:00Z", + "value": 101.414214 + }, + { + "index": 28, + "timestamp": "2026-01-29T00:00:00Z", + "value": 101.732051 + }, + { + "index": 29, + "timestamp": "2026-01-30T00:00:00Z", + "value": 101.931852 + }, + { + "index": 30, + "timestamp": "2026-01-31T00:00:00Z", + "value": 102.0 + }, + { + "index": 31, + "timestamp": "2026-02-01T00:00:00Z", + "value": 101.931852 + }, + { + "index": 32, + "timestamp": "2026-02-02T00:00:00Z", + "value": 101.732051 + }, + { + "index": 33, + "timestamp": "2026-02-03T00:00:00Z", + "value": 101.414214 + }, + { + "index": 34, + "timestamp": "2026-02-04T00:00:00Z", + "value": 101.0 + }, + { + "index": 35, + "timestamp": "2026-02-05T00:00:00Z", + "value": 100.517638 + }, + { + "index": 36, + "timestamp": "2026-02-06T00:00:00Z", + "value": 101.011419 + }, + { + "index": 37, + "timestamp": "2026-02-07T00:00:00Z", + "value": 101.488464 + }, + { + "index": 38, + "timestamp": "2026-02-08T00:00:00Z", + "value": 101.932873 + }, + { + "index": 39, + "timestamp": "2026-02-09T00:00:00Z", + "value": 102.330385 + }, + { + "index": 40, + "timestamp": "2026-02-10T00:00:00Z", + "value": 102.669091 + }, + { + "index": 41, + "timestamp": "2026-02-11T00:00:00Z", + "value": 102.94003 + }, + { + "index": 42, + "timestamp": "2026-02-12T00:00:00Z", + "value": 103.137638 + }, + { + "index": 43, + "timestamp": "2026-02-13T00:00:00Z", + "value": 103.26003 + }, + { + "index": 44, + "timestamp": "2026-02-14T00:00:00Z", + "value": 103.309091 + }, + { + "index": 45, + "timestamp": "2026-02-15T00:00:00Z", + "value": 103.290385 + }, + { + "index": 46, + "timestamp": "2026-02-16T00:00:00Z", + "value": 103.212873 + }, + { + "index": 47, + "timestamp": "2026-02-17T00:00:00Z", + "value": 103.088464 + }, + { + "index": 48, + "timestamp": "2026-02-18T00:00:00Z", + "value": 102.931419 + }, + { + "index": 49, + "timestamp": "2026-02-19T00:00:00Z", + "value": 102.757638 + }, + { + "index": 50, + "timestamp": "2026-02-20T00:00:00Z", + "value": 102.583857 + }, + { + "index": 51, + "timestamp": "2026-02-21T00:00:00Z", + "value": 102.426812 + }, + { + "index": 52, + "timestamp": "2026-02-22T00:00:00Z", + "value": 102.302403 + }, + { + "index": 53, + "timestamp": "2026-02-23T00:00:00Z", + "value": 102.224891 + }, + { + "index": 54, + "timestamp": "2026-02-24T00:00:00Z", + "value": 102.206185 + }, + { + "index": 55, + "timestamp": "2026-02-25T00:00:00Z", + "value": 102.255246 + }, + { + "index": 56, + "timestamp": "2026-02-26T00:00:00Z", + "value": 102.377638 + }, + { + "index": 57, + "timestamp": "2026-02-27T00:00:00Z", + "value": 102.575246 + }, + { + "index": 58, + "timestamp": "2026-02-28T00:00:00Z", + "value": 102.846185 + }, + { + "index": 59, + "timestamp": "2026-03-01T00:00:00Z", + "value": 103.184891 + }, + { + "index": 60, + "timestamp": "2026-03-02T00:00:00Z", + "value": 103.582403 + }, + { + "index": 61, + "timestamp": "2026-03-03T00:00:00Z", + "value": 104.026812 + }, + { + "index": 62, + "timestamp": "2026-03-04T00:00:00Z", + "value": 104.503857 + }, + { + "index": 63, + "timestamp": "2026-03-05T00:00:00Z", + "value": 104.997638 + }, + { + "index": 64, + "timestamp": "2026-03-06T00:00:00Z", + "value": 105.491419 + }, + { + "index": 65, + "timestamp": "2026-03-07T00:00:00Z", + "value": 105.968464 + }, + { + "index": 66, + "timestamp": "2026-03-08T00:00:00Z", + "value": 106.412873 + }, + { + "index": 67, + "timestamp": "2026-03-09T00:00:00Z", + "value": 106.810385 + }, + { + "index": 68, + "timestamp": "2026-03-10T00:00:00Z", + "value": 107.149091 + }, + { + "index": 69, + "timestamp": "2026-03-11T00:00:00Z", + "value": 107.42003 + }, + { + "index": 70, + "timestamp": "2026-03-12T00:00:00Z", + "value": 107.617638 + }, + { + "index": 71, + "timestamp": "2026-03-13T00:00:00Z", + "value": 107.74003 + }, + { + "index": 72, + "timestamp": "2026-03-14T00:00:00Z", + "value": 109.012822 + }, + { + "index": 73, + "timestamp": "2026-03-15T00:00:00Z", + "value": 109.54003 + }, + { + "index": 74, + "timestamp": "2026-03-16T00:00:00Z", + "value": 109.012822 + }, + { + "index": 75, + "timestamp": "2026-03-17T00:00:00Z", + "value": 107.74003 + }, + { + "index": 76, + "timestamp": "2026-03-18T00:00:00Z", + "value": 106.467238 + }, + { + "index": 77, + "timestamp": "2026-03-19T00:00:00Z", + "value": 105.94003 + }, + { + "index": 78, + "timestamp": "2026-03-20T00:00:00Z", + "value": 106.467238 + }, + { + "index": 79, + "timestamp": "2026-03-21T00:00:00Z", + "value": 107.74003 + }, + { + "index": 80, + "timestamp": "2026-03-22T00:00:00Z", + "value": 109.012822 + }, + { + "index": 81, + "timestamp": "2026-03-23T00:00:00Z", + "value": 109.54003 + }, + { + "index": 82, + "timestamp": "2026-03-24T00:00:00Z", + "value": 109.012822 + }, + { + "index": 83, + "timestamp": "2026-03-25T00:00:00Z", + "value": 107.74003 + }, + { + "index": 84, + "timestamp": "2026-03-26T00:00:00Z", + "value": 106.467238 + }, + { + "index": 85, + "timestamp": "2026-03-27T00:00:00Z", + "value": 105.94003 + }, + { + "index": 86, + "timestamp": "2026-03-28T00:00:00Z", + "value": 106.467238 + }, + { + "index": 87, + "timestamp": "2026-03-29T00:00:00Z", + "value": 107.74003 + }, + { + "index": 88, + "timestamp": "2026-03-30T00:00:00Z", + "value": 109.012822 + }, + { + "index": 89, + "timestamp": "2026-03-31T00:00:00Z", + "value": 109.54003 + }, + { + "index": 90, + "timestamp": "2026-04-01T00:00:00Z", + "value": 109.012822 + }, + { + "index": 91, + "timestamp": "2026-04-02T00:00:00Z", + "value": 107.74003 + }, + { + "index": 92, + "timestamp": "2026-04-03T00:00:00Z", + "value": 106.467238 + }, + { + "index": 93, + "timestamp": "2026-04-04T00:00:00Z", + "value": 105.94003 + }, + { + "index": 94, + "timestamp": "2026-04-05T00:00:00Z", + "value": 106.467238 + }, + { + "index": 95, + "timestamp": "2026-04-06T00:00:00Z", + "value": 107.74003 + }, + { + "index": 96, + "timestamp": "2026-04-07T00:00:00Z", + "value": 107.78003 + }, + { + "index": 97, + "timestamp": "2026-04-08T00:00:00Z", + "value": 107.809312 + }, + { + "index": 98, + "timestamp": "2026-04-09T00:00:00Z", + "value": 107.82003 + }, + { + "index": 99, + "timestamp": "2026-04-10T00:00:00Z", + "value": 107.809312 + }, + { + "index": 100, + "timestamp": "2026-04-11T00:00:00Z", + "value": 107.78003 + }, + { + "index": 101, + "timestamp": "2026-04-12T00:00:00Z", + "value": 107.74003 + }, + { + "index": 102, + "timestamp": "2026-04-13T00:00:00Z", + "value": 107.70003 + }, + { + "index": 103, + "timestamp": "2026-04-14T00:00:00Z", + "value": 107.670748 + }, + { + "index": 104, + "timestamp": "2026-04-15T00:00:00Z", + "value": 107.66003 + }, + { + "index": 105, + "timestamp": "2026-04-16T00:00:00Z", + "value": 107.670748 + }, + { + "index": 106, + "timestamp": "2026-04-17T00:00:00Z", + "value": 107.70003 + }, + { + "index": 107, + "timestamp": "2026-04-18T00:00:00Z", + "value": 107.74003 + }, + { + "index": 108, + "timestamp": "2026-04-19T00:00:00Z", + "value": 107.78003 + }, + { + "index": 109, + "timestamp": "2026-04-20T00:00:00Z", + "value": 107.809312 + }, + { + "index": 110, + "timestamp": "2026-04-21T00:00:00Z", + "value": 107.82003 + }, + { + "index": 111, + "timestamp": "2026-04-22T00:00:00Z", + "value": 107.809312 + }, + { + "index": 112, + "timestamp": "2026-04-23T00:00:00Z", + "value": 107.78003 + }, + { + "index": 113, + "timestamp": "2026-04-24T00:00:00Z", + "value": 107.74003 + }, + { + "index": 114, + "timestamp": "2026-04-25T00:00:00Z", + "value": 107.70003 + }, + { + "index": 115, + "timestamp": "2026-04-26T00:00:00Z", + "value": 107.670748 + }, + { + "index": 116, + "timestamp": "2026-04-27T00:00:00Z", + "value": 107.66003 + }, + { + "index": 117, + "timestamp": "2026-04-28T00:00:00Z", + "value": 107.670748 + }, + { + "index": 118, + "timestamp": "2026-04-29T00:00:00Z", + "value": 107.70003 + }, + { + "index": 119, + "timestamp": "2026-04-30T00:00:00Z", + "value": 107.74003 + }, + { + "index": 120, + "timestamp": "2026-05-01T00:00:00Z", + "value": 107.86205 + }, + { + "index": 121, + "timestamp": "2026-05-02T00:00:00Z", + "value": 107.942818 + }, + { + "index": 122, + "timestamp": "2026-05-03T00:00:00Z", + "value": 107.946055 + }, + { + "index": 123, + "timestamp": "2026-05-04T00:00:00Z", + "value": 107.844838 + }, + { + "index": 124, + "timestamp": "2026-05-05T00:00:00Z", + "value": 107.624838 + }, + { + "index": 125, + "timestamp": "2026-05-06T00:00:00Z", + "value": 107.286055 + }, + { + "index": 126, + "timestamp": "2026-05-07T00:00:00Z", + "value": 106.842818 + }, + { + "index": 127, + "timestamp": "2026-05-08T00:00:00Z", + "value": 106.32205 + }, + { + "index": 128, + "timestamp": "2026-05-09T00:00:00Z", + "value": 105.76003 + }, + { + "index": 129, + "timestamp": "2026-05-10T00:00:00Z", + "value": 105.19801 + }, + { + "index": 130, + "timestamp": "2026-05-11T00:00:00Z", + "value": 104.677242 + }, + { + "index": 131, + "timestamp": "2026-05-12T00:00:00Z", + "value": 104.234005 + }, + { + "index": 132, + "timestamp": "2026-05-13T00:00:00Z", + "value": 103.895222 + }, + { + "index": 133, + "timestamp": "2026-05-14T00:00:00Z", + "value": 103.675222 + }, + { + "index": 134, + "timestamp": "2026-05-15T00:00:00Z", + "value": 103.574005 + }, + { + "index": 135, + "timestamp": "2026-05-16T00:00:00Z", + "value": 103.577242 + }, + { + "index": 136, + "timestamp": "2026-05-17T00:00:00Z", + "value": 103.65801 + }, + { + "index": 137, + "timestamp": "2026-05-18T00:00:00Z", + "value": 103.78003 + }, + { + "index": 138, + "timestamp": "2026-05-19T00:00:00Z", + "value": 103.90205 + }, + { + "index": 139, + "timestamp": "2026-05-20T00:00:00Z", + "value": 103.982818 + }, + { + "index": 140, + "timestamp": "2026-05-21T00:00:00Z", + "value": 103.986055 + }, + { + "index": 141, + "timestamp": "2026-05-22T00:00:00Z", + "value": 103.884838 + }, + { + "index": 142, + "timestamp": "2026-05-23T00:00:00Z", + "value": 103.664838 + }, + { + "index": 143, + "timestamp": "2026-05-24T00:00:00Z", + "value": 103.326055 + } + ], + "expected": { + "smooth": [ + null, + null, + null, + 100.9692132, + 101.3688484, + 101.6751989, + 101.8673872, + 101.9323163, + 101.8655612, + 101.6716713, + 101.3638596, + 100.9631031, + 100.4967128, + 99.9964724, + 99.4964724, + 99.0307868, + 98.6311516, + 98.3248011, + 98.1326128, + 98.0676837, + 98.1344388, + 98.3283287, + 98.6361404, + 99.0368969, + 99.5032872, + 100.0035276, + 100.5035276, + 100.9692132, + 101.3688484, + 101.6751989, + 101.8673872, + 101.9323163, + 101.8655612, + 101.6716713, + 101.3638596, + 100.9631031, + 100.9012804, + 101.1023389, + 101.473736, + 101.9108506, + 102.3021729, + 102.6361036, + 102.9039209, + 103.1002185, + 103.223176, + 103.2746511, + 103.2600859, + 103.1882336, + 103.0707199, + 102.921461, + 102.7559644, + 102.5905514, + 102.44154, + 102.3244254, + 102.2531031, + 102.2391724, + 102.2913551, + 102.4150575, + 102.6121, + 102.8806249, + 103.2151901, + 103.6070424, + 104.0445561, + 104.513815, + 104.9993116, + 105.4847246, + 105.953736, + 106.3908506, + 106.7821729, + 107.1161036, + 107.3839209, + 107.5802185, + 108.1926684, + 108.8296284, + 109.0437052, + 108.6091468, + 107.6654716, + 106.7654716, + 106.4363548, + 106.8709132, + 107.8145884, + 108.7145884, + 109.0437052, + 108.6091468, + 107.6654716, + 106.7654716, + 106.4363548, + 106.8709132, + 107.8145884, + 108.7145884, + 109.0437052, + 108.6091468, + 107.6654716, + 106.7654716, + 106.4363548, + 106.8709132, + 107.3214716, + 107.6524636, + 107.8008146, + 107.8095992, + 107.7997428, + 107.7738864, + 107.7389582, + 107.7043172, + 107.6792454, + 107.6704608, + 107.6803172, + 107.7061736, + 107.7411018, + 107.7757428, + 107.8008146, + 107.8095992, + 107.7997428, + 107.7738864, + 107.7389582, + 107.7043172, + 107.6792454, + 107.6704608, + 107.6803172, + 107.7061736, + 107.7739098, + 107.8537512, + 107.9076804, + 107.8965203, + 107.7868794, + 107.5654465, + 107.2323951, + 106.8013602, + 106.2977961, + 105.7559048, + 105.2145108, + 104.7123796, + 104.2835397, + 103.9531806, + 103.7346135, + 103.6276649, + 103.6186998, + 103.6822639, + 103.7841552, + 103.8855492, + 103.9476804, + 103.9365203, + 103.8268794, + 103.6054465 + ], + "detrender": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 5.220603236534, + 6.060386206274, + 47.418776209958, + 51.05630633882, + 7.17963853732, + 7.50010917952, + -0.634201492245, + -0.537152739907, + -0.394641065583, + -0.212227282826, + 0.001575125739, + 0.235498376258, + 0.475878267622, + 0.707176709898, + 0.912667487181, + 1.075279312829, + 1.178577442246, + 1.207858749583, + 1.151319017779, + 1.001241145265, + 0.755133784203, + 0.416740658512, + -0.003172790659, + -0.486354691978, + -0.899688781972, + -1.203978061363, + -0.779271873461, + 0.273035079887, + 1.14366369353, + 1.744939873601, + 1.879380516422, + 1.684669344992, + 1.381560146625, + 1.043210920191, + 0.702673163499, + 0.374129481512, + 0.086196977024, + -0.146958709626, + -0.325114707143, + -0.453047696399, + -0.531179969802, + -0.556745862914, + -0.527633763091, + -0.444582622569, + -0.311414099989, + -0.134349054975, + 0.078442897058, + 0.316770237756, + 0.568230799132, + 0.818572488137, + 1.053011194558, + 1.258437731092, + 1.425807392398, + 1.551519800128, + 1.636864407599, + 1.685660761161, + 1.701185061886, + 1.68357365477, + 1.628363322222, + 1.526494207936, + 1.491018636834, + 1.434686202816, + 2.091943254046, + 2.854504841309, + 1.813060348753, + -0.751956956429, + -3.648260426932, + -4.864709890519, + -3.031804111677, + 0.268964846515, + 3.316685496926, + 4.188161671117, + 2.6373142992, + -0.241891333559, + -2.986162003723, + -3.856115666479, + -2.56799197646, + 0.21578690479, + 2.708166730547, + 3.568537251445, + 2.386363316286, + -0.199977359588, + -2.506264349051, + -3.285685701529, + -2.313667826471, + -0.081036424242, + 1.31544440462, + 1.362031073335, + 1.001313183784, + 0.424562176664, + 0.090698866093, + -0.034683997422, + -0.101378633844, + -0.112712617149, + -0.093738058306, + -0.051693861736, + 0.001601472353, + 0.05246744007, + 0.088076194253, + 0.099651185129, + 0.084724694774, + 0.04766778282, + -0.001499604518, + -0.049714014152, + -0.084263908911, + -0.096111270353, + -0.082263051002, + -0.046538635117, + 0.007100684578, + 0.062311764812, + 0.135168099084, + 0.189904210606, + 0.155062759761, + 0.019713581357, + -0.215186309862, + -0.515479262522, + -0.835045023257, + -1.12919322616, + -1.360878894278, + -1.526234819629, + -1.635111323742, + -1.665293040026, + -1.587181752255, + -1.392594410053, + -1.087377076296, + -0.700595180172, + -0.29128746466, + 0.064529242909, + 0.301078529562, + 0.382902198781, + 0.300395157535, + 0.058636744862 + ], + "i1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 5.220603236534, + 6.060386206274, + 47.418776209958, + 51.05630633882, + 7.17963853732, + 7.50010917952, + -0.634201492245, + -0.537152739907, + -0.394641065583, + -0.212227282826, + 0.001575125739, + 0.235498376258, + 0.475878267622, + 0.707176709898, + 0.912667487181, + 1.075279312829, + 1.178577442246, + 1.207858749583, + 1.151319017779, + 1.001241145265, + 0.755133784203, + 0.416740658512, + -0.003172790659, + -0.486354691978, + -0.899688781972, + -1.203978061363, + -0.779271873461, + 0.273035079887, + 1.14366369353, + 1.744939873601, + 1.879380516422, + 1.684669344992, + 1.381560146625, + 1.043210920191, + 0.702673163499, + 0.374129481512, + 0.086196977024, + -0.146958709626, + -0.325114707143, + -0.453047696399, + -0.531179969802, + -0.556745862914, + -0.527633763091, + -0.444582622569, + -0.311414099989, + -0.134349054975, + 0.078442897058, + 0.316770237756, + 0.568230799132, + 0.818572488137, + 1.053011194558, + 1.258437731092, + 1.425807392398, + 1.551519800128, + 1.636864407599, + 1.685660761161, + 1.701185061886, + 1.68357365477, + 1.628363322222, + 1.526494207936, + 1.491018636834, + 1.434686202816, + 2.091943254046, + 2.854504841309, + 1.813060348753, + -0.751956956429, + -3.648260426932, + -4.864709890519, + -3.031804111677, + 0.268964846515, + 3.316685496926, + 4.188161671117, + 2.6373142992, + -0.241891333559, + -2.986162003723, + -3.856115666479, + -2.56799197646, + 0.21578690479, + 2.708166730547, + 3.568537251445, + 2.386363316286, + -0.199977359588, + -2.506264349051, + -3.285685701529, + -2.313667826471, + -0.081036424242, + 1.31544440462, + 1.362031073335, + 1.001313183784, + 0.424562176664, + 0.090698866093, + -0.034683997422, + -0.101378633844, + -0.112712617149, + -0.093738058306, + -0.051693861736, + 0.001601472353, + 0.05246744007, + 0.088076194253, + 0.099651185129, + 0.084724694774, + 0.04766778282, + -0.001499604518, + -0.049714014152, + -0.084263908911, + -0.096111270353, + -0.082263051002, + -0.046538635117, + 0.007100684578, + 0.062311764812, + 0.135168099084, + 0.189904210606, + 0.155062759761, + 0.019713581357, + -0.215186309862, + -0.515479262522, + -0.835045023257, + -1.12919322616, + -1.360878894278, + -1.526234819629, + -1.635111323742, + -1.665293040026, + -1.587181752255, + -1.392594410053, + -1.087377076296, + -0.700595180172, + -0.29128746466, + 0.064529242909, + 0.301078529562 + ], + "q1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.271199896931, + 0.367295766417, + 5.316563499545, + 6.386605497479, + 20.170043477512, + 22.478784782099, + -20.752694032843, + -23.342617208072, + -8.58547095882, + -9.405627190339, + -0.567378284619, + -0.550260216043, + 0.378821163319, + 0.449261255131, + 0.500586808712, + 0.524549020067, + 0.512462097252, + 0.455641122209, + 0.346016587649, + 0.176954019525, + -0.055701615938, + -0.352352924915, + -0.70817040968, + -1.111463490732, + -1.493572653097, + -1.806490862834, + -1.701061428705, + -1.130412490886, + 0.488981124273, + 2.966968619929, + 3.858336717531, + 3.109547439544, + 1.694789977386, + 0.102820907939, + -0.838174068155, + -1.221415129097, + -1.302334860912, + -1.232194759688, + -1.096065770022, + -0.916679385991, + -0.726359647541, + -0.540760450351, + -0.361019145991, + -0.179433952764, + 0.006828582063, + 0.193934894614, + 0.373876880212, + 0.537588235393, + 0.676190505468, + 0.780916847017, + 0.843533885587, + 0.858201377986, + 0.824112878921, + 0.747132185329, + 0.639005371768, + 0.514080330579, + 0.384795458085, + 0.257591354647, + 0.130284013428, + -0.008892077936, + -0.148539559252, + -0.327751576778, + -0.127338026213, + 0.197076030688, + 1.275467941673, + 2.194356777961, + -2.479777053497, + -10.438431668764, + -13.352174141224, + -9.934208753104, + 1.788615877082, + 11.599007149034, + 13.602652000579, + 9.221643723457, + -1.247457519161, + -9.174457953291, + -11.827116796178, + -7.501287907344, + 0.724146981515, + 7.809065015965, + 10.270544248965, + 6.44096135529, + -0.485508860879, + -6.648000445311, + -8.743226726876, + -5.534849647623, + 0.020314162153, + 4.93856561503, + 5.970837770988, + 2.844719419814, + 0.114859651472, + -1.191422259443, + -1.434410626093, + -0.856743536673, + -0.441077530705, + -0.180274529702, + -0.008086300638, + 0.083236565023, + 0.137924071902, + 0.149924903254, + 0.123674595214, + 0.067311162739, + -0.004059039124, + -0.072052727724, + -0.119511410369, + -0.134707501701, + -0.114271214498, + -0.064019851471, + 0.003534841247, + 0.070144888363, + 0.129286387537, + 0.160456855515, + 0.171539136177, + 0.141593648791, + -0.017504816308, + -0.271230424196, + -0.539862702383, + -0.760648201105, + -0.870937553469, + -0.87438255409, + -0.791708425719, + -0.645707130654, + -0.466966745404, + -0.228723565743, + 0.124792361822, + 0.578148498246, + 1.058602364451, + 1.46043565757, + 1.664239488362, + 1.594791442217, + 1.248285981854, + 0.683725696098 + ], + "i2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + -0.002817658449, + -0.006706192203, + -0.099139325302, + 0.839280064587, + 1.10182597343, + 9.415669121484, + 16.601046157817, + 13.44776860598, + 16.961430032745, + 18.937724050755, + 14.010499746889, + 9.875991647796, + 6.354098330864, + 3.325177936479, + 2.351296008469, + 1.57034254829, + 1.348842542329, + 1.219841232358, + 1.189757912556, + 1.209798181819, + 1.263357434683, + 1.335579816831, + 1.413215087085, + 1.484306196106, + 1.531203826909, + 1.534177476045, + 1.442942022577, + 1.225858296033, + 0.74235738429, + 0.002820948663, + -0.939910898212, + -2.088524586631, + -2.538948073682, + -1.760345053401, + -0.371631490063, + 1.019304121032, + 1.927956032263, + 2.200866796308, + 2.061660007096, + 1.709578778656, + 1.285320639022, + 0.862653686253, + 0.47621591712, + 0.145663729933, + -0.123465806454, + -0.332533653597, + -0.484631781934, + -0.580451040897, + -0.618771598444, + -0.598231392817, + -0.519148288019, + -0.384469300533, + -0.200180808505, + 0.024488914175, + 0.277221546124, + 0.543483413769, + 0.808174741738, + 1.057636313578, + 1.281496731347, + 1.474112598628, + 1.634001311969, + 1.76694034251, + 1.847353874264, + 1.901421023963, + 1.722400696628, + 1.41975325358, + 1.263934105807, + 1.234207894872, + 3.357226209438, + 8.218584149749, + 10.051578444331, + 6.627889430275, + -1.199163674799, + -10.052942513512, + -12.342121283352, + -8.539317146108, + -0.748287492738, + 6.374879086193, + 8.615508917253, + 5.901828686924, + -0.051760031445, + -5.323743647781, + -7.110551704921, + -4.836698274304, + -0.145130032585, + 3.971418435521, + 5.408884235305, + 3.618488392811, + 0.090077766015, + -2.991801987429, + -4.086674556247, + -2.718068905122, + -0.564033402443, + 0.782482919379, + 1.235548483898, + 1.007035385017, + 0.565074940532, + 0.237421745272, + 0.028521362837, + -0.069536348626, + -0.096247566847, + -0.082183005553, + -0.042966914827, + 0.005225907314, + 0.049197199419, + 0.077768664202, + 0.08432520592, + 0.068039302338, + 0.033870058312, + -0.008759719321, + -0.049016983724, + -0.07538696916, + -0.083335688263, + -0.065085531908, + -0.021986428651, + 0.028847928019, + 0.088030988193, + 0.141495608568, + 0.149066740141, + 0.08444634407, + -0.062734803327, + -0.283720657083, + -0.553578800621, + -0.849228174934, + -1.143396861631, + -1.417892564811, + -1.676149799533, + -1.903398884932, + -2.049085008025, + -2.054105544359, + -1.870702005253, + -1.483044777651 + ], + "q2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.054239979386, + 0.116851136793, + 1.156793609343, + 2.279053557974, + 5.951195304766, + 10.532906555549, + 5.743458649464, + 4.462942290097, + 6.883367777038, + -1.048811353469, + -6.24538040638, + -7.066235434246, + -7.738939136508, + -6.232590561581, + -5.01415261309, + -3.817558784923, + -2.84547391435, + -2.066272040992, + -1.458334478989, + -1.007914943394, + -0.707115905051, + -0.551860372133, + -0.539762683305, + -0.667826712162, + -0.918880603278, + -1.265063990333, + -1.608228299296, + -1.848111880665, + -1.779472077587, + -1.199996860805, + -0.428134518548, + 0.378614612124, + 1.213691862799, + 1.711503721104, + 1.774748783005, + 1.483252325105, + 0.944289114124, + 0.364504953491, + -0.139274728243, + -0.527414156523, + -0.796628244124, + -0.956703998371, + -1.017967821442, + -0.994685678113, + -0.90243371605, + -0.755527148899, + -0.565714318356, + -0.343678673908, + -0.100661877658, + 0.150677133495, + 0.396472118702, + 0.622705306546, + 0.81672687829, + 0.968789873868, + 1.073094048437, + 1.127954202786, + 1.135044273471, + 1.098000523381, + 1.020712248385, + 0.905454099962, + 0.757358682506, + 0.572661140218, + 0.430452625088, + 0.346765017701, + 0.45217639995, + 0.770147700843, + 0.165331398467, + -1.672220282071, + -3.568525839305, + -5.338329024504, + -5.833951603853, + -4.806668432348, + -2.796081504692, + -0.051521099538, + 1.921888617825, + 2.35447865921, + 1.197854923196, + -0.777629548219, + -2.201115762875, + -2.39044195046, + -1.281543701457, + 0.402746309758, + 1.69242344997, + 1.909817446949, + 0.988428659868, + -0.409569059027, + -1.585116333311, + -1.913694830991, + -1.383675950288, + -0.534128822962, + 0.512672833269, + 1.251869973364, + 1.230348805409, + 0.834023164856, + 0.360103616327, + -0.010604724663, + -0.168127932588, + -0.200413645792, + -0.166962252524, + -0.10513520668, + -0.043295663738, + 0.005629063029, + 0.032980223925, + 0.036241011123, + 0.018345564058, + -0.013066630351, + -0.047568970426, + -0.074560011483, + -0.085702189888, + -0.077267880123, + -0.048706880811, + -0.006169966886, + 0.043339825371, + 0.088718178845, + 0.099388462162, + 0.059383258286, + -0.032329951288, + -0.181453064129, + -0.372553375754, + -0.579677492917, + -0.778877608178, + -0.94364858968, + -1.051970682824, + -1.077971541173, + -0.99452220854, + -0.792596388014, + -0.475874133784, + -0.060746554132, + 0.407200756905, + 0.862295696435, + 1.2366320979, + 1.467458782821 + ], + "re": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.001271379802, + 0.028184602973, + 0.533185468753, + 3.324115056536, + 17.270854612067, + 57.177737880245, + 95.518140673322, + 128.177204430119, + 165.340068982424, + 186.647495965278, + 185.817778134149, + 172.141860106269, + 151.585917403985, + 129.082661495221, + 107.832961700731, + 88.862551115417, + 72.59502028067, + 58.968942528258, + 47.757002837257, + 38.653826312782, + 31.338569837767, + 25.507922906698, + 20.897960695025, + 17.295654224007, + 14.538839616226, + 12.48071986497, + 10.93278154714, + 9.585962926923, + 8.096261353351, + 6.579230810255, + 5.6235704553, + 5.651291754228, + 5.830365967743, + 5.402630534466, + 4.772823377481, + 4.491417212575, + 4.510608265215, + 4.505821157483, + 4.324262058037, + 3.982911626765, + 3.56051410414, + 3.12535194358, + 2.716666634766, + 2.349263988396, + 2.023985132371, + 1.736901886524, + 1.484667303023, + 1.266486234222, + 1.084189217777, + 0.941413391377, + 0.842427087378, + 0.791050377209, + 0.79010720552, + 0.841364064913, + 0.945304502766, + 1.100145107447, + 1.30032291814, + 1.535478346863, + 1.791038390883, + 2.051721801579, + 2.305555986165, + 2.546578304616, + 2.76963532517, + 2.902069830854, + 2.880381186244, + 2.688665780083, + 2.407630010907, + 3.948279284353, + 12.486945662415, + 32.74021582132, + 45.124696964825, + 37.198140063362, + 32.198348186802, + 50.55380213775, + 62.426708436262, + 51.7834043631, + 40.286377556345, + 43.55599809903, + 46.066577906762, + 37.404857722789, + 29.875770206642, + 31.607890519378, + 32.811075014086, + 26.766793706836, + 21.21719458885, + 21.399787105635, + 21.640912435925, + 17.907505721662, + 14.41991785079, + 13.926471825103, + 13.491110012646, + 11.407551685894, + 9.242999928954, + 7.647826011659, + 6.366345258025, + 5.207242888567, + 4.199365552958, + 3.367539063462, + 2.697145318669, + 2.159965175519, + 1.729505380475, + 1.384347663972, + 1.107672270287, + 0.886322208589, + 0.709775024026, + 0.569255904176, + 0.457261557573, + 0.367548136339, + 0.295303575937, + 0.237081431239, + 0.190464297328, + 0.153574441797, + 0.124713349033, + 0.101820391579, + 0.082509862825, + 0.066131821013, + 0.056569930204, + 0.062994592303, + 0.096105463455, + 0.166124389646, + 0.283456694939, + 0.456715834409, + 0.686194502081, + 0.957569895245, + 1.24794964, + 1.549115003571, + 1.883149877504, + 2.28161791732, + 2.737327201078, + 3.171654140247, + 3.45513160672 + ], + "im": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + -6.899427e-06, + -0.000770892057, + 0.2387468158, + -0.305722382309, + 8.641233263832, + 31.068738940739, + 25.484429544277, + 17.013932895061, + 43.240078294212, + 55.30784654051, + 51.710710238856, + 47.67459689043, + 40.913506235509, + 33.134461854271, + 26.728024191643, + 21.246235965476, + 16.860198617699, + 13.352273497714, + 10.568795673756, + 8.371458678805, + 6.647724377663, + 5.306379250498, + 4.273625338384, + 3.487164541818, + 2.895200613166, + 2.444539218576, + 2.094683033347, + 1.83763064813, + 1.647265864777, + 1.54363226638, + 1.48491250681, + 1.502638496634, + 1.643891319061, + 1.812737367862, + 1.922236298296, + 1.917214535053, + 1.808872634746, + 1.658700189788, + 1.496809662605, + 1.334248218072, + 1.175889995093, + 1.025223200405, + 0.88525939285, + 0.759059820382, + 0.648609418704, + 0.554494218822, + 0.475957746416, + 0.411612059281, + 0.359980412628, + 0.31977598848, + 0.289989797919, + 0.269862390315, + 0.258676691182, + 0.255399456675, + 0.258422687077, + 0.265679421663, + 0.275161087676, + 0.285637218566, + 0.297371437939, + 0.310513392692, + 0.328906425242, + 0.322589873636, + 0.29364669336, + 0.182415473618, + 0.009027574611, + 0.154959290631, + 0.587493345343, + 0.228050877275, + -2.098809655223, + -2.821409878103, + -0.327564176138, + 4.597168905491, + 9.287148004136, + 11.421021493612, + 11.666346143676, + 11.026484145258, + 10.232045282858, + 9.652070733495, + 9.242509744353, + 8.931443941749, + 8.513846413728, + 8.040333157308, + 7.511089350572, + 6.909583345488, + 6.300871282614, + 5.856666746475, + 5.608379147018, + 5.453590119678, + 5.200431613576, + 4.903670545267, + 4.667437452467, + 4.261565231963, + 3.695880955271, + 3.106444989795, + 2.560303938915, + 2.080906813765, + 1.679391751371, + 1.350298280913, + 1.083160333685, + 0.867949944041, + 0.695179945512, + 0.5566376665, + 0.445656036406, + 0.356862245932, + 0.285903707072, + 0.229242471456, + 0.184004122917, + 0.147864451388, + 0.118965120057, + 0.095844252009, + 0.077349287798, + 0.062635717542, + 0.051023093015, + 0.041722105415, + 0.034212239727, + 0.028601835585, + 0.025161257751, + 0.025262216174, + 0.031199745669, + 0.045387660535, + 0.068666940048, + 0.099717160262, + 0.139097918248, + 0.188872934002, + 0.251873031688, + 0.332252801511, + 0.426593835425, + 0.521183132339, + 0.603043276196, + 0.667849532994, + 0.716519088992 + ], + "period": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.2, + 2.16, + 2.928, + 3.5424, + 4.03392, + 4.437312, + 4.8810432, + 5.36914752, + 5.906062272, + 6.4966684992, + 7.14633534912, + 7.860968884032, + 8.647065772435, + 9.511772349679, + 10.462949584647, + 11.509244543111, + 12.660168997422, + 13.926185897165, + 15.318804486881, + 16.850684935569, + 18.535753429126, + 20.389328772039, + 22.428261649243, + 24.172270480081, + 25.654048706422, + 26.916247458329, + 28.030043656851, + 29.062287064865, + 29.884578404859, + 30.168299680166, + 29.587522518448, + 28.537698620719, + 27.665612341065, + 26.705086457496, + 25.245872842895, + 23.579645235264, + 22.023388649737, + 20.913591096696, + 20.293489598014, + 20.005827562595, + 19.892246503927, + 19.853337386352, + 19.847149465969, + 19.866895741066, + 19.914532306154, + 19.983704735438, + 20.053535285484, + 20.093479404984, + 20.073822280705, + 19.979009153811, + 19.820870729618, + 19.647154184205, + 19.540031344732, + 19.603746856939, + 19.946915378366, + 20.666597234121, + 21.836484252892, + 23.495255122699, + 25.628628317532, + 28.14054555695, + 30.878695989733, + 33.571120003602, + 36.829835375859, + 39.463868300687, + 41.57109464055, + 43.25687571244, + 44.605500569952, + 41.661537532335, + 43.329230025868, + 40.469500844161, + 37.798513788446, + 35.303811878409, + 38.243049502727, + 35.719008235547, + 34.230939780703, + 34.186590860955, + 33.338926517662, + 31.723484414657, + 31.141135162273, + 31.259404516079, + 30.368857542268, + 28.82161574063, + 28.102117003842, + 28.065710507181, + 27.426883203732, + 26.294631461819, + 25.739789727302, + 25.547462293447, + 24.688841631536, + 23.381670894327, + 22.417107169748, + 21.706524298316, + 20.880092168079, + 20.007680638437, + 19.263129617982, + 18.696954706691, + 18.262965268297, + 17.913542693672, + 17.626097857136, + 17.391531756191, + 17.202098682585, + 17.049678857021, + 16.926700559798, + 16.826529437623, + 16.744198956238, + 16.677034157133, + 16.624065217467, + 16.583912056713, + 16.552565427984, + 16.523372632489, + 16.489660624764, + 16.449275672536, + 16.404386642068, + 16.359377668188, + 16.31881808898, + 16.252062171421, + 16.080105037422, + 15.86675981469, + 15.988320325617, + 16.793872095427, + 18.146793929327, + 19.804756852641, + 21.689666492309, + 23.634944606704, + 25.360780329233, + 26.598498495368, + 27.226581850798, + 27.42217140009, + 27.533387519977, + 27.821938422364, + 28.31257248131, + 28.795588190907 + ], + "phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 50.736403963721, + 73.276331591115, + 25.363206032113, + -22.120110159289, + -72.903337062107, + -48.860136334266, + 86.142506096269, + 46.567510570861, + 54.352291554629, + -60.741107828701, + 89.799119807811, + 64.805612923095, + 47.785241660501, + 35.929310229813, + 26.530255304251, + 17.837774770989, + 8.538724561557, + -2.640381561915, + -17.016354301187, + -35.271485169812, + -55.807618413102, + -74.40969157025, + 89.899369916082, + 74.044105978139, + 51.48392024714, + -22.103935245004, + -75.283700039516, + 85.952213589066, + 69.806929977226, + 44.164709452902, + 3.131530168199, + -26.451737315957, + -41.479381585387, + -51.304181687025, + -60.305554832965, + -71.153249535242, + -84.628172306999, + 78.562187878568, + 58.984973902413, + 38.550214908483, + 18.665099964265, + -0.702707179397, + -20.181200993748, + -40.062544236671, + -59.917146255948, + -78.7625201478, + 84.263894722665, + 69.417458080166, + 56.490730105903, + 45.193244434669, + 35.35645154075, + 26.920399393815, + 19.826963374639, + 13.928987194228, + 8.9432221369, + 4.419580364222, + -0.29948176035, + -5.042077669848, + -11.380250606098, + -4.76849399832, + 7.529449408896, + 41.637807169532, + 46.368720434124, + -40.98163215719, + -80.146549032588, + 86.776667434968, + 69.834635607794, + -20.187043839098, + -75.351489924092, + 88.867239810538, + 70.218210877659, + -16.58633331286, + -73.962031579627, + 88.828334850834, + 68.293162510618, + -10.63580665958, + -71.796675913139, + 88.796377303689, + 67.195193055121, + -7.747670966277, + -70.253914512864, + 88.689744454216, + 65.638257075636, + -0.354233798239, + -64.897387053964, + -89.222427367439, + 65.183413106751, + 4.820330045668, + -49.955124895322, + -73.512104535149, + -83.95691014128, + 85.503815837686, + 60.648473205039, + 4.103519799771, + -41.604109037002, + -69.454031114218, + 89.387999490315, + 67.01150699705, + 37.388432198712, + -2.332509331876, + -40.378956601643, + -68.255143217745, + 89.362192456757, + 66.488414988611, + 37.225902763516, + -2.106311140505, + -40.453898747472, + -70.20287515561, + 87.466147555225, + 70.036396342174, + 46.329991427611, + -5.266475768919, + -60.243344534554, + -87.908721281844, + 74.20386616209, + 59.380107171959, + 46.318263960234, + 35.03535367628, + 25.383311796003, + 17.012013017716, + 7.96301109242, + -4.285574039558, + -20.01471220614, + -37.240847793898, + -53.330228373306, + -67.170359161406, + -79.649067183941, + 87.04077013596, + 66.23371246664 + ], + "delta_phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 47.913125559001, + 47.483316191402, + 50.783226902818, + 1.0, + 1.0, + 39.574995525407, + 1.0, + 115.09339938333, + 1.0, + 24.993506884716, + 17.020371262594, + 11.855931430688, + 9.399054925561, + 8.692480533262, + 9.299050209432, + 11.179106123472, + 14.375972739272, + 18.255130868626, + 20.53613324329, + 18.602073157148, + 1.0, + 15.855263937943, + 22.560185730999, + 73.587855492144, + 53.179764794512, + 1.0, + 16.145283611841, + 25.642220524324, + 41.033179284703, + 29.583267484155, + 15.02764426943, + 9.824800101638, + 9.00137314594, + 10.847694702277, + 13.474922771757, + 1.0, + 19.577213976155, + 20.434758993929, + 19.885114944218, + 19.367807143662, + 19.478493814351, + 19.881343242923, + 19.854602019278, + 18.845373891851, + 1.0, + 14.846436642499, + 12.926727974263, + 11.297485671234, + 9.836792893919, + 8.436052146935, + 7.093436019176, + 5.897976180411, + 4.985765057328, + 4.523641772678, + 4.719062124572, + 4.742595909498, + 6.33817293625, + 1.0, + 1.0, + 1.0, + 1.0, + 87.350352591314, + 39.164916875397, + 1.0, + 16.942031827175, + 90.021679446891, + 55.164446084994, + 1.0, + 18.649028932879, + 86.804544190519, + 57.375698266767, + 1.0, + 20.535172340217, + 78.928969170197, + 61.16086925356, + 1.0, + 21.601184248568, + 74.942864021398, + 62.506243546588, + 1.0, + 23.05148737858, + 65.992490873874, + 64.543153255725, + 24.325040313475, + 1.0, + 60.363083061083, + 54.775454940991, + 23.556979639827, + 10.444805606131, + 1.0, + 24.855342632647, + 56.544953405268, + 45.707628836773, + 27.849922077216, + 1.0, + 22.376492493265, + 29.623074798339, + 39.720941530588, + 38.046447269767, + 27.876186616102, + 1.0, + 22.873777468147, + 29.262512225095, + 39.33221390402, + 38.347587606967, + 29.748976408138, + 1.0, + 17.429751213051, + 23.706404914564, + 51.59646719653, + 54.976868765635, + 27.665376747291, + 1.0, + 14.823758990131, + 13.061843211726, + 11.282910283954, + 9.652041880277, + 8.371298778287, + 9.049001925296, + 12.248585131978, + 15.729138166582, + 17.226135587759, + 16.089380579408, + 13.840130788099, + 12.478708022536, + 1.0, + 20.80705766932 + ], + "alpha": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.5, + 0.05, + 0.5, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.053196837763, + 0.057520980126, + 0.053768932175, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.050891620677, + 0.055547080639, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05082957478, + 0.059269429739, + 0.070487701397, + 0.084774842201, + 0.100285511702, + 0.110530414459, + 0.105953256558, + 0.105427493622, + 0.078887087025, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.051802510412, + 0.059727888496, + 0.055254712523, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05 + ], + "mama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 100.283132803372, + 100.339686863203, + 100.372702520043, + 100.379949294041, + 100.411522779339, + 100.949993389669, + 100.999137370186, + 101.065699751677, + 101.145869314093, + 101.235577348388, + 102.186607674194, + 102.240278790484, + 102.29371940096, + 102.343552680912, + 102.387018696867, + 102.422090962023, + 102.448011491332, + 102.465210339977, + 102.471142672978, + 102.468926139329, + 102.385664569665, + 102.377625891181, + 102.369053846622, + 102.363363454291, + 102.364077181577, + 102.374635622498, + 102.398213091373, + 102.437546986804, + 102.494789787464, + 103.260800893732, + 103.322953699045, + 103.406687914093, + 103.510924468388, + 103.635840157786, + 103.800433310711, + 104.012597886606, + 104.278493595359, + 104.593544181229, + 104.927798524382, + 105.22576360742, + 105.625023681949, + 105.933867126064, + 107.473344563032, + 107.606687281516, + 107.036962640758, + 106.488496320379, + 106.48743340436, + 106.550063234142, + 107.781442617071, + 107.869371986217, + 107.926544486907, + 107.917218762561, + 107.192228381281, + 107.129618462217, + 107.096499439106, + 107.12867596715, + 108.070748983575, + 108.144213034396, + 108.187643482677, + 108.165262808543, + 107.316250404271, + 107.247439384058, + 107.208429314855, + 107.235009349112, + 107.507519674556, + 107.522609290828, + 107.537480326287, + 107.551071909973, + 107.562519814474, + 107.651274907237, + 107.653712661875, + 107.654564428781, + 107.654837707342, + 107.655633221975, + 107.677831610988, + 107.680941530438, + 107.685895953916, + 107.69206675622, + 107.698464918409, + 107.753888459205, + 107.755195536244, + 107.754437259432, + 107.751716896461, + 107.747668451638, + 107.743286529056, + 107.707017264528, + 107.706667901301, + 107.708336006236, + 107.716021705925, + 107.727361520628, + 107.738296194597, + 107.791567097298, + 107.783230642434, + 107.758371860312, + 107.712594167296, + 107.643066958931, + 107.548915110985, + 106.373462555492, + 106.288651527718, + 106.185919201332, + 106.071384341265, + 105.947257116633, + 105.805507778837, + 105.682385593803, + 105.581166814113, + 105.491109973407, + 105.411656974737, + 105.340215026, + 105.2725070247, + 105.203123573465, + 104.433980786732, + 104.378584497396 + ], + "fama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 91.078423889195, + 91.309955463545, + 91.536524139958, + 91.75760976881, + 91.973957594073, + 94.217966542972, + 94.387495813653, + 94.554450912103, + 94.719236372153, + 94.882144896559, + 96.708260590968, + 96.846561045955, + 96.982740004831, + 97.116760321733, + 97.248516781111, + 97.377856135634, + 97.506870347202, + 97.644581002909, + 97.765245044661, + 97.882837072027, + 99.008543946437, + 99.092770995055, + 99.174678066345, + 99.254395201043, + 99.332137250557, + 99.408199709855, + 99.482950044393, + 99.556814967953, + 99.630264338441, + 100.537898477264, + 100.607524857808, + 100.677503934215, + 100.74833944757, + 100.821724664209, + 100.909997845628, + 101.01934541825, + 101.157492304462, + 101.32978541481, + 101.528630354925, + 101.724492008942, + 101.930103647981, + 102.088026266942, + 103.434355840964, + 104.477438701102, + 105.117319686016, + 105.460113844607, + 105.485796833601, + 105.512403493614, + 106.079663274478, + 106.124405992272, + 106.169459454638, + 106.213153437336, + 106.457922173322, + 106.474714580544, + 106.490259202008, + 106.506219621137, + 106.897351961747, + 106.928523488563, + 106.960001488416, + 106.990133021419, + 107.071662367132, + 107.076056792555, + 107.079366105613, + 107.0832571867, + 107.189322808664, + 107.197654970718, + 107.206150604607, + 107.214773637242, + 107.223467291672, + 107.330419195563, + 107.338501532221, + 107.346403104635, + 107.354113969703, + 107.36165195101, + 107.440696866004, + 107.446702982615, + 107.452682806898, + 107.458667405631, + 107.46466234345, + 107.536968872389, + 107.542424538985, + 107.547724856996, + 107.552824657983, + 107.557695752824, + 107.56233552223, + 107.598505957805, + 107.601210006392, + 107.603888156388, + 107.606691495126, + 107.609708245764, + 107.612922944485, + 107.657583982688, + 107.660725149182, + 107.66316631696, + 107.664402013218, + 107.663868636861, + 107.660994798714, + 107.339111737909, + 107.312850232654, + 107.284676956871, + 107.254344641481, + 107.220489433923, + 107.178232500663, + 107.136906205255, + 107.098012720477, + 107.0578401518, + 107.016685572373, + 106.974773808714, + 106.932217139114, + 106.888989799972, + 106.275237546662, + 106.227821220431 + ] + } }, { - "index": 72, - "value": 109.012822, - "phase": -5.042077669848, - "delta_phase": 4.742595909498, - "alpha": 0.105427493622, - "mama": 105.625023681949, - "fama": 101.930103647981 + "id": "clean-20-bar-cycle", + "classification": "synthetic teaching input", + "lesson": "A noise-free control makes phase progression and half-cycle fast attacks easy to inspect.", + "observations": [ + { + "index": 0, + "timestamp": "2026-01-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 1, + "timestamp": "2026-01-02T00:00:00Z", + "value": 100.927051 + }, + { + "index": 2, + "timestamp": "2026-01-03T00:00:00Z", + "value": 101.763356 + }, + { + "index": 3, + "timestamp": "2026-01-04T00:00:00Z", + "value": 102.427051 + }, + { + "index": 4, + "timestamp": "2026-01-05T00:00:00Z", + "value": 102.85317 + }, + { + "index": 5, + "timestamp": "2026-01-06T00:00:00Z", + "value": 103.0 + }, + { + "index": 6, + "timestamp": "2026-01-07T00:00:00Z", + "value": 102.85317 + }, + { + "index": 7, + "timestamp": "2026-01-08T00:00:00Z", + "value": 102.427051 + }, + { + "index": 8, + "timestamp": "2026-01-09T00:00:00Z", + "value": 101.763356 + }, + { + "index": 9, + "timestamp": "2026-01-10T00:00:00Z", + "value": 100.927051 + }, + { + "index": 10, + "timestamp": "2026-01-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 11, + "timestamp": "2026-01-12T00:00:00Z", + "value": 99.072949 + }, + { + "index": 12, + "timestamp": "2026-01-13T00:00:00Z", + "value": 98.236644 + }, + { + "index": 13, + "timestamp": "2026-01-14T00:00:00Z", + "value": 97.572949 + }, + { + "index": 14, + "timestamp": "2026-01-15T00:00:00Z", + "value": 97.14683 + }, + { + "index": 15, + "timestamp": "2026-01-16T00:00:00Z", + "value": 97.0 + }, + { + "index": 16, + "timestamp": "2026-01-17T00:00:00Z", + "value": 97.14683 + }, + { + "index": 17, + "timestamp": "2026-01-18T00:00:00Z", + "value": 97.572949 + }, + { + "index": 18, + "timestamp": "2026-01-19T00:00:00Z", + "value": 98.236644 + }, + { + "index": 19, + "timestamp": "2026-01-20T00:00:00Z", + "value": 99.072949 + }, + { + "index": 20, + "timestamp": "2026-01-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 21, + "timestamp": "2026-01-22T00:00:00Z", + "value": 100.927051 + }, + { + "index": 22, + "timestamp": "2026-01-23T00:00:00Z", + "value": 101.763356 + }, + { + "index": 23, + "timestamp": "2026-01-24T00:00:00Z", + "value": 102.427051 + }, + { + "index": 24, + "timestamp": "2026-01-25T00:00:00Z", + "value": 102.85317 + }, + { + "index": 25, + "timestamp": "2026-01-26T00:00:00Z", + "value": 103.0 + }, + { + "index": 26, + "timestamp": "2026-01-27T00:00:00Z", + "value": 102.85317 + }, + { + "index": 27, + "timestamp": "2026-01-28T00:00:00Z", + "value": 102.427051 + }, + { + "index": 28, + "timestamp": "2026-01-29T00:00:00Z", + "value": 101.763356 + }, + { + "index": 29, + "timestamp": "2026-01-30T00:00:00Z", + "value": 100.927051 + }, + { + "index": 30, + "timestamp": "2026-01-31T00:00:00Z", + "value": 100.0 + }, + { + "index": 31, + "timestamp": "2026-02-01T00:00:00Z", + "value": 99.072949 + }, + { + "index": 32, + "timestamp": "2026-02-02T00:00:00Z", + "value": 98.236644 + }, + { + "index": 33, + "timestamp": "2026-02-03T00:00:00Z", + "value": 97.572949 + }, + { + "index": 34, + "timestamp": "2026-02-04T00:00:00Z", + "value": 97.14683 + }, + { + "index": 35, + "timestamp": "2026-02-05T00:00:00Z", + "value": 97.0 + }, + { + "index": 36, + "timestamp": "2026-02-06T00:00:00Z", + "value": 97.14683 + }, + { + "index": 37, + "timestamp": "2026-02-07T00:00:00Z", + "value": 97.572949 + }, + { + "index": 38, + "timestamp": "2026-02-08T00:00:00Z", + "value": 98.236644 + }, + { + "index": 39, + "timestamp": "2026-02-09T00:00:00Z", + "value": 99.072949 + }, + { + "index": 40, + "timestamp": "2026-02-10T00:00:00Z", + "value": 100.0 + }, + { + "index": 41, + "timestamp": "2026-02-11T00:00:00Z", + "value": 100.927051 + }, + { + "index": 42, + "timestamp": "2026-02-12T00:00:00Z", + "value": 101.763356 + }, + { + "index": 43, + "timestamp": "2026-02-13T00:00:00Z", + "value": 102.427051 + }, + { + "index": 44, + "timestamp": "2026-02-14T00:00:00Z", + "value": 102.85317 + }, + { + "index": 45, + "timestamp": "2026-02-15T00:00:00Z", + "value": 103.0 + }, + { + "index": 46, + "timestamp": "2026-02-16T00:00:00Z", + "value": 102.85317 + }, + { + "index": 47, + "timestamp": "2026-02-17T00:00:00Z", + "value": 102.427051 + }, + { + "index": 48, + "timestamp": "2026-02-18T00:00:00Z", + "value": 101.763356 + }, + { + "index": 49, + "timestamp": "2026-02-19T00:00:00Z", + "value": 100.927051 + }, + { + "index": 50, + "timestamp": "2026-02-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 51, + "timestamp": "2026-02-21T00:00:00Z", + "value": 99.072949 + }, + { + "index": 52, + "timestamp": "2026-02-22T00:00:00Z", + "value": 98.236644 + }, + { + "index": 53, + "timestamp": "2026-02-23T00:00:00Z", + "value": 97.572949 + }, + { + "index": 54, + "timestamp": "2026-02-24T00:00:00Z", + "value": 97.14683 + }, + { + "index": 55, + "timestamp": "2026-02-25T00:00:00Z", + "value": 97.0 + }, + { + "index": 56, + "timestamp": "2026-02-26T00:00:00Z", + "value": 97.14683 + }, + { + "index": 57, + "timestamp": "2026-02-27T00:00:00Z", + "value": 97.572949 + }, + { + "index": 58, + "timestamp": "2026-02-28T00:00:00Z", + "value": 98.236644 + }, + { + "index": 59, + "timestamp": "2026-03-01T00:00:00Z", + "value": 99.072949 + }, + { + "index": 60, + "timestamp": "2026-03-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 61, + "timestamp": "2026-03-03T00:00:00Z", + "value": 100.927051 + }, + { + "index": 62, + "timestamp": "2026-03-04T00:00:00Z", + "value": 101.763356 + }, + { + "index": 63, + "timestamp": "2026-03-05T00:00:00Z", + "value": 102.427051 + }, + { + "index": 64, + "timestamp": "2026-03-06T00:00:00Z", + "value": 102.85317 + }, + { + "index": 65, + "timestamp": "2026-03-07T00:00:00Z", + "value": 103.0 + }, + { + "index": 66, + "timestamp": "2026-03-08T00:00:00Z", + "value": 102.85317 + }, + { + "index": 67, + "timestamp": "2026-03-09T00:00:00Z", + "value": 102.427051 + }, + { + "index": 68, + "timestamp": "2026-03-10T00:00:00Z", + "value": 101.763356 + }, + { + "index": 69, + "timestamp": "2026-03-11T00:00:00Z", + "value": 100.927051 + }, + { + "index": 70, + "timestamp": "2026-03-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 71, + "timestamp": "2026-03-13T00:00:00Z", + "value": 99.072949 + }, + { + "index": 72, + "timestamp": "2026-03-14T00:00:00Z", + "value": 98.236644 + }, + { + "index": 73, + "timestamp": "2026-03-15T00:00:00Z", + "value": 97.572949 + }, + { + "index": 74, + "timestamp": "2026-03-16T00:00:00Z", + "value": 97.14683 + }, + { + "index": 75, + "timestamp": "2026-03-17T00:00:00Z", + "value": 97.0 + }, + { + "index": 76, + "timestamp": "2026-03-18T00:00:00Z", + "value": 97.14683 + }, + { + "index": 77, + "timestamp": "2026-03-19T00:00:00Z", + "value": 97.572949 + }, + { + "index": 78, + "timestamp": "2026-03-20T00:00:00Z", + "value": 98.236644 + }, + { + "index": 79, + "timestamp": "2026-03-21T00:00:00Z", + "value": 99.072949 + }, + { + "index": 80, + "timestamp": "2026-03-22T00:00:00Z", + "value": 100.0 + }, + { + "index": 81, + "timestamp": "2026-03-23T00:00:00Z", + "value": 100.927051 + }, + { + "index": 82, + "timestamp": "2026-03-24T00:00:00Z", + "value": 101.763356 + }, + { + "index": 83, + "timestamp": "2026-03-25T00:00:00Z", + "value": 102.427051 + }, + { + "index": 84, + "timestamp": "2026-03-26T00:00:00Z", + "value": 102.85317 + }, + { + "index": 85, + "timestamp": "2026-03-27T00:00:00Z", + "value": 103.0 + }, + { + "index": 86, + "timestamp": "2026-03-28T00:00:00Z", + "value": 102.85317 + }, + { + "index": 87, + "timestamp": "2026-03-29T00:00:00Z", + "value": 102.427051 + }, + { + "index": 88, + "timestamp": "2026-03-30T00:00:00Z", + "value": 101.763356 + }, + { + "index": 89, + "timestamp": "2026-03-31T00:00:00Z", + "value": 100.927051 + }, + { + "index": 90, + "timestamp": "2026-04-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 91, + "timestamp": "2026-04-02T00:00:00Z", + "value": 99.072949 + }, + { + "index": 92, + "timestamp": "2026-04-03T00:00:00Z", + "value": 98.236644 + }, + { + "index": 93, + "timestamp": "2026-04-04T00:00:00Z", + "value": 97.572949 + }, + { + "index": 94, + "timestamp": "2026-04-05T00:00:00Z", + "value": 97.14683 + }, + { + "index": 95, + "timestamp": "2026-04-06T00:00:00Z", + "value": 97.0 + }, + { + "index": 96, + "timestamp": "2026-04-07T00:00:00Z", + "value": 97.14683 + }, + { + "index": 97, + "timestamp": "2026-04-08T00:00:00Z", + "value": 97.572949 + }, + { + "index": 98, + "timestamp": "2026-04-09T00:00:00Z", + "value": 98.236644 + }, + { + "index": 99, + "timestamp": "2026-04-10T00:00:00Z", + "value": 99.072949 + }, + { + "index": 100, + "timestamp": "2026-04-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 101, + "timestamp": "2026-04-12T00:00:00Z", + "value": 100.927051 + }, + { + "index": 102, + "timestamp": "2026-04-13T00:00:00Z", + "value": 101.763356 + }, + { + "index": 103, + "timestamp": "2026-04-14T00:00:00Z", + "value": 102.427051 + }, + { + "index": 104, + "timestamp": "2026-04-15T00:00:00Z", + "value": 102.85317 + }, + { + "index": 105, + "timestamp": "2026-04-16T00:00:00Z", + "value": 103.0 + }, + { + "index": 106, + "timestamp": "2026-04-17T00:00:00Z", + "value": 102.85317 + }, + { + "index": 107, + "timestamp": "2026-04-18T00:00:00Z", + "value": 102.427051 + }, + { + "index": 108, + "timestamp": "2026-04-19T00:00:00Z", + "value": 101.763356 + }, + { + "index": 109, + "timestamp": "2026-04-20T00:00:00Z", + "value": 100.927051 + }, + { + "index": 110, + "timestamp": "2026-04-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 111, + "timestamp": "2026-04-22T00:00:00Z", + "value": 99.072949 + }, + { + "index": 112, + "timestamp": "2026-04-23T00:00:00Z", + "value": 98.236644 + }, + { + "index": 113, + "timestamp": "2026-04-24T00:00:00Z", + "value": 97.572949 + }, + { + "index": 114, + "timestamp": "2026-04-25T00:00:00Z", + "value": 97.14683 + }, + { + "index": 115, + "timestamp": "2026-04-26T00:00:00Z", + "value": 97.0 + }, + { + "index": 116, + "timestamp": "2026-04-27T00:00:00Z", + "value": 97.14683 + }, + { + "index": 117, + "timestamp": "2026-04-28T00:00:00Z", + "value": 97.572949 + }, + { + "index": 118, + "timestamp": "2026-04-29T00:00:00Z", + "value": 98.236644 + }, + { + "index": 119, + "timestamp": "2026-04-30T00:00:00Z", + "value": 99.072949 + }, + { + "index": 120, + "timestamp": "2026-05-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 121, + "timestamp": "2026-05-02T00:00:00Z", + "value": 100.927051 + }, + { + "index": 122, + "timestamp": "2026-05-03T00:00:00Z", + "value": 101.763356 + }, + { + "index": 123, + "timestamp": "2026-05-04T00:00:00Z", + "value": 102.427051 + }, + { + "index": 124, + "timestamp": "2026-05-05T00:00:00Z", + "value": 102.85317 + }, + { + "index": 125, + "timestamp": "2026-05-06T00:00:00Z", + "value": 103.0 + }, + { + "index": 126, + "timestamp": "2026-05-07T00:00:00Z", + "value": 102.85317 + }, + { + "index": 127, + "timestamp": "2026-05-08T00:00:00Z", + "value": 102.427051 + }, + { + "index": 128, + "timestamp": "2026-05-09T00:00:00Z", + "value": 101.763356 + }, + { + "index": 129, + "timestamp": "2026-05-10T00:00:00Z", + "value": 100.927051 + }, + { + "index": 130, + "timestamp": "2026-05-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 131, + "timestamp": "2026-05-12T00:00:00Z", + "value": 99.072949 + }, + { + "index": 132, + "timestamp": "2026-05-13T00:00:00Z", + "value": 98.236644 + }, + { + "index": 133, + "timestamp": "2026-05-14T00:00:00Z", + "value": 97.572949 + }, + { + "index": 134, + "timestamp": "2026-05-15T00:00:00Z", + "value": 97.14683 + }, + { + "index": 135, + "timestamp": "2026-05-16T00:00:00Z", + "value": 97.0 + }, + { + "index": 136, + "timestamp": "2026-05-17T00:00:00Z", + "value": 97.14683 + }, + { + "index": 137, + "timestamp": "2026-05-18T00:00:00Z", + "value": 97.572949 + }, + { + "index": 138, + "timestamp": "2026-05-19T00:00:00Z", + "value": 98.236644 + }, + { + "index": 139, + "timestamp": "2026-05-20T00:00:00Z", + "value": 99.072949 + }, + { + "index": 140, + "timestamp": "2026-05-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 141, + "timestamp": "2026-05-22T00:00:00Z", + "value": 100.927051 + }, + { + "index": 142, + "timestamp": "2026-05-23T00:00:00Z", + "value": 101.763356 + }, + { + "index": 143, + "timestamp": "2026-05-24T00:00:00Z", + "value": 102.427051 + } + ], + "expected": { + "smooth": [ + null, + null, + null, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374, + 102.3147596, + 102.7176968, + 102.8546071, + 102.7120884, + 102.3040917, + 101.6705544, + 100.8734916, + 99.9909254, + 99.1092474, + 98.3147626, + 97.6852404, + 97.2823032, + 97.1453929, + 97.2879116, + 97.6959083, + 98.3294456, + 99.1265084, + 100.0090746, + 100.8907526, + 101.6852374 + ], + "detrender": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 5.148527183935, + 5.958464502136, + 46.734558355981, + 50.191590987308, + 6.867517349205, + 7.383610136076, + -0.39049109007, + 0.004211443106, + 0.430093272968, + 0.848463247495, + 1.217925021604, + 1.497758176607, + 1.651577534966, + 1.651020309415, + 1.479183286182, + 1.133505335235, + 0.627790446455, + -0.006923240852, + -0.722899498426, + -1.457827499069, + -2.138617209831, + -2.686814032406, + -3.025430565295, + -3.086808776969, + -2.820956354642, + -2.163090834299, + -1.176553398783, + 0.012485953666, + 1.225752844433, + 2.275374079913, + 3.035497312538, + 3.464778977875, + 3.56484024005, + 3.337605902155, + 2.794869683569, + 1.990054674013, + 1.018563239657, + -0.010353187974, + -0.996720337953, + -1.857329027546, + -2.524662802857, + -2.945127861458, + -3.081084457499, + -2.917810358983, + -2.470408997682, + -1.7843112499, + -0.929201552917, + 0.009614307608, + 0.940113229651, + 1.772664141129, + 2.428584238676, + 2.84665342141, + 2.987576718191, + 2.83744513944, + 2.410066837245, + 1.746759970238, + 0.912746234719, + -0.009473345295, + -0.928828753336, + -1.755374844595, + -2.409431704052, + -2.828677425959, + -2.972928707681, + -2.827406181857, + -2.404782056478, + -1.745137569173, + -0.912880663405, + 0.009482231998, + 0.930129002962, + 1.758125546676, + 2.41315251065, + 2.832810814488, + 2.977119122941, + 2.831383767661, + 2.408182017302, + 1.747550540377, + 0.914060913636, + -0.009493192079, + -0.931058777009, + -1.759625727513, + -2.414932203518, + -2.834675745068, + -2.978923604711, + -2.832977509006, + -2.409420247948, + -1.748346636979, + -0.914417941482, + 0.009496283122, + 0.931306628382, + 1.760006446733, + 2.415361345774, + 2.83509701289, + 2.97929564536, + 2.833267324442, + 2.40961046943, + 1.748443911108, + 0.914449509864, + -0.009496450179, + -0.93131205061, + -1.760004606535, + -2.41535076675, + -2.835079655172, + -2.979272147407, + -2.833238287483, + -2.409579659167, + -1.748418141715, + -0.914435230906, + 0.009496304117, + 0.931298710671, + 1.759981945529, + 2.415323053156, + 2.835050118369, + 2.979243100832, + 2.833212003256, + 2.409558568811, + 1.748404092891, + 0.914428711795, + -0.009496245929, + -0.931293919536, + -1.759974412358, + -2.415314370864, + -2.835041370824, + -2.979235086597, + -2.833205410829, + -2.409553879452, + -1.74840138648, + -0.914427647184, + 0.009496238033, + 0.931293385655, + 1.759973718101, + 2.415313691406, + 2.835040785505 + ], + "i1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 5.148527183935, + 5.958464502136, + 46.734558355981, + 50.191590987308, + 6.867517349205, + 7.383610136076, + -0.39049109007, + 0.004211443106, + 0.430093272968, + 0.848463247495, + 1.217925021604, + 1.497758176607, + 1.651577534966, + 1.651020309415, + 1.479183286182, + 1.133505335235, + 0.627790446455, + -0.006923240852, + -0.722899498426, + -1.457827499069, + -2.138617209831, + -2.686814032406, + -3.025430565295, + -3.086808776969, + -2.820956354642, + -2.163090834299, + -1.176553398783, + 0.012485953666, + 1.225752844433, + 2.275374079913, + 3.035497312538, + 3.464778977875, + 3.56484024005, + 3.337605902155, + 2.794869683569, + 1.990054674013, + 1.018563239657, + -0.010353187974, + -0.996720337953, + -1.857329027546, + -2.524662802857, + -2.945127861458, + -3.081084457499, + -2.917810358983, + -2.470408997682, + -1.7843112499, + -0.929201552917, + 0.009614307608, + 0.940113229651, + 1.772664141129, + 2.428584238676, + 2.84665342141, + 2.987576718191, + 2.83744513944, + 2.410066837245, + 1.746759970238, + 0.912746234719, + -0.009473345295, + -0.928828753336, + -1.755374844595, + -2.409431704052, + -2.828677425959, + -2.972928707681, + -2.827406181857, + -2.404782056478, + -1.745137569173, + -0.912880663405, + 0.009482231998, + 0.930129002962, + 1.758125546676, + 2.41315251065, + 2.832810814488, + 2.977119122941, + 2.831383767661, + 2.408182017302, + 1.747550540377, + 0.914060913636, + -0.009493192079, + -0.931058777009, + -1.759625727513, + -2.414932203518, + -2.834675745068, + -2.978923604711, + -2.832977509006, + -2.409420247948, + -1.748346636979, + -0.914417941482, + 0.009496283122, + 0.931306628382, + 1.760006446733, + 2.415361345774, + 2.83509701289, + 2.97929564536, + 2.833267324442, + 2.40961046943, + 1.748443911108, + 0.914449509864, + -0.009496450179, + -0.93131205061, + -1.760004606535, + -2.41535076675, + -2.835079655172, + -2.979272147407, + -2.833238287483, + -2.409579659167, + -1.748418141715, + -0.914435230906, + 0.009496304117, + 0.931298710671, + 1.759981945529, + 2.415323053156, + 2.835050118369, + 2.979243100832, + 2.833212003256, + 2.409558568811, + 1.748404092891, + 0.914428711795, + -0.009496245929, + -0.931293919536, + -1.759974412358, + -2.415314370864, + -2.835041370824, + -2.979235086597, + -2.833205410829, + -2.409553879452, + -1.74840138648, + -0.914427647184, + 0.009496238033, + 0.931293385655 + ], + "q1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.267455690151, + 0.361118699616, + 5.241166992073, + 6.278754262749, + 19.861330537334, + 22.09857596433, + -20.53882244505, + -22.895440332314, + -8.146348516653, + -8.850508119644, + -0.072005779326, + -0.0851850523, + 0.735292093746, + 0.633487948882, + 0.440058476664, + 0.153453021122, + -0.219214143812, + -0.660308030468, + -1.140169509968, + -1.616260853017, + -2.033326863629, + -2.3249835151, + -2.417171603159, + -2.233868680459, + -1.705347874793, + -0.754866731586, + 0.553593160485, + 2.129078464996, + 3.647418066176, + 4.668261829771, + 4.990683488446, + 4.596955971343, + 3.657580705912, + 2.417184692293, + 1.080685907647, + -0.234469435105, + -1.452996846298, + -2.476283598034, + -3.197365168754, + -3.558517841099, + -3.565388593315, + -3.258860428993, + -2.688564816065, + -1.90564079705, + -0.968711454092, + 0.047511338584, + 1.050451843367, + 1.940575465748, + 2.629191812893, + 3.05201338825, + 3.174343315803, + 2.991034174059, + 2.524495270756, + 1.821234344975, + 0.947344706441, + -0.015931795451, + -0.97718875938, + -1.842446438019, + -2.525566009378, + -2.958921227813, + -3.10124658089, + -2.941188298331, + -2.496804562616, + -1.812046374161, + -0.951738723735, + 0.003504337932, + 0.962525336623, + 1.830743068212, + 2.520110143572, + 2.960233902884, + 3.107414101419, + 2.949196646207, + 2.50401434273, + 1.816999585235, + 0.954049327532, + -0.003759110678, + -0.965200750518, + -1.835516979732, + -2.52624770396, + -2.966684693919, + -3.113200152253, + -2.953725785783, + -2.507116036845, + -1.818762008268, + -0.954629655867, + 0.004218890297, + 0.966525137254, + 1.837421939995, + 2.528360918713, + 2.968653946969, + 3.114791049298, + 2.954846969606, + 2.507785176877, + 1.819052038236, + 0.95462644328, + -0.004429803896, + -0.966851066413, + -1.837764041104, + -2.528636592507, + -2.968821948725, + -3.11485608694, + -2.954842178285, + -2.507748170116, + -1.81900940705, + -0.954591903337, + 0.004448210113, + 0.966845318757, + 1.837728483406, + 2.528573671951, + 2.968743099372, + 3.114776418714, + 2.954774103646, + 2.507698331906, + 1.818979313243, + 0.954580455685, + -0.004442647308, + -0.966824877516, + -1.837696984837, + -2.528536860084, + -2.968707165543, + -3.11474609502, + -2.954751737506, + -2.507684163313, + -1.818972369862, + -0.954579404806, + 0.004439151167, + 0.966818333737, + 1.837689155673, + 2.528529463553, + 2.968701372456, + 3.114742288013, + 2.954749676091 + ], + "i2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + -0.002778757638, + -0.006600198093, + -0.097732919975, + 0.828107566692, + 1.083949832899, + 9.280572054109, + 16.339866866225, + 13.196970803092, + 16.671319994505, + 18.64800342441, + 13.844406242873, + 9.877164251434, + 6.556744335419, + 3.74892563778, + 2.974882547699, + 2.370885325041, + 2.278685025653, + 2.217765470261, + 2.178612272564, + 2.100127420532, + 1.956228095926, + 1.725338356449, + 1.389445140422, + 0.932816124788, + 0.340745654621, + -0.400962911216, + -1.285002842726, + -2.280811936348, + -3.270983927667, + -4.079300826582, + -4.504714624725, + -4.344141277562, + -3.543719112197, + -2.221426826206, + -0.602968252079, + 1.034914246405, + 2.454589823289, + 3.507263107394, + 4.130596829072, + 4.312150347799, + 4.066574414304, + 3.441219615031, + 2.5210842006, + 1.41625112375, + 0.242441846817, + -0.892532007089, + -1.894163843781, + -2.682481634662, + -3.193720740854, + -3.385267380754, + -3.242692871286, + -2.784194612812, + -2.05929569802, + -1.142658280362, + -0.125593592041, + 0.893075070242, + 1.816145101957, + 2.556503629184, + 3.044421974576, + 3.233691697641, + 3.106417414831, + 2.675510549272, + 1.983837006978, + 1.099828332425, + 0.11031576211, + -0.888291570902, + -1.799390492962, + -2.535122287524, + -3.024186422581, + -3.218356352012, + -3.097528367856, + -2.672545295756, + -1.984776422704, + -1.102056011909, + -0.111533378721, + 0.889465213204, + 1.803303925567, + 2.541373061807, + 3.032014504816, + 3.226891078168, + 3.105871899676, + 2.679846165216, + 1.990371393716, + 1.105603946772, + 0.113043456267, + -0.889716583284, + -1.804903202696, + -2.543877822832, + -3.035003814586, + -3.229974130577, + -3.108701762325, + -2.682158186363, + -1.992021160316, + -1.10657460398, + -0.113419293791, + 0.889793378555, + 1.805274717242, + 2.544399563827, + 3.035557561184, + 3.230471625803, + 3.109088029147, + 2.682414415045, + 1.992161197848, + 1.106633030178, + 0.113435899639, + -0.889785974616, + -1.80525651083, + -2.544362030723, + -3.035499652405, + -3.230397010361, + -3.109004408744, + -2.682332651125, + -1.992092720375, + -1.106586578231, + -0.1134154877, + 0.889781130874, + 1.805230633497, + 2.544321003078, + 3.03544976148, + 3.230344452127, + 3.108954995736, + 2.68229120148, + 1.992062305341, + 1.106568148398, + 0.11340810253, + -0.889779654488, + -1.805222977417, + -2.544309778419, + -3.035437232068, + -3.230332452453, + -3.108944858598, + -2.682283654485 + ], + "q2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.05349113803, + 0.115016650347, + 1.140246718693, + 2.243192428333, + 5.859183895818, + 10.365157409853, + 5.627248925581, + 4.38997336606, + 6.827737283783, + -0.934119050921, + -5.95315629263, + -6.639198865673, + -7.198431515401, + -5.648709781245, + -4.450802218117, + -3.357486473186, + -2.580251244273, + -2.091670036075, + -1.864661712499, + -1.867751607655, + -2.06079339868, + -2.391420527095, + -2.792609102881, + -3.181835859615, + -3.46238892877, + -3.51150804312, + -3.227218657804, + -2.539261432675, + -1.462372660591, + -0.125261980992, + 1.303763225263, + 2.638242365761, + 3.705659498469, + 4.384657545113, + 4.598620582962, + 4.329808365835, + 3.631323682417, + 2.613091750554, + 1.406952177693, + 0.139199601541, + -1.075175047776, + -2.131223667502, + -2.939685275846, + -3.436260565954, + -3.587605197169, + -3.392694110955, + -2.880915342963, + -2.108063298359, + -1.151222822391, + -0.102835488626, + 0.936941155185, + 1.869630325609, + 2.607931992823, + 3.083674870964, + 3.253783920172, + 3.104274877591, + 2.651782831684, + 1.942034260382, + 1.045336596012, + 0.049668448253, + -0.947929667622, + -1.850769502466, + -2.571664533918, + -3.040955896327, + -3.212968954401, + -3.070567840511, + -2.62725323288, + -1.926224426814, + -1.036256940364, + -0.044793154293, + 0.950950658433, + 1.853729618632, + 2.575643993224, + 3.046280093887, + 3.219268509689, + 3.076989447126, + 2.632807084189, + 1.930126174113, + 1.038100180517, + 0.044528050643, + -0.953119478502, + -1.857423884091, + -2.580363008285, + -3.051457848302, + -3.224349723235, + -3.081509006628, + -2.636448386322, + -1.932738378029, + -1.039675578235, + -0.045163816565, + 0.953254811842, + 1.858118817011, + 2.581392142353, + 3.052610713974, + 3.225454915955, + 3.082450362534, + 2.637169708269, + 1.933234650174, + 1.039975364435, + 0.045311875494, + -0.953209543318, + -1.858130628624, + -2.581423708948, + -3.052636803438, + -3.225463970862, + -3.082443056942, + -2.637154512668, + -1.933222197044, + -1.039974308268, + -0.045327418769, + 0.95317551588, + 1.858079206485, + 2.581358699048, + 3.052564194719, + 3.225390932376, + 3.082376605277, + 2.637100191213, + 1.933183250104, + 1.039951621925, + 0.045319985317, + -0.953170044606, + -1.858064049292, + -2.581337501131, + -3.05254056662, + -3.225368010351, + -3.082356699601, + -2.637084607662, + -1.933172351726, + -1.039945080166, + -0.045317067648, + 0.953170257666, + 1.85806251654 + ], + "re": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.001234142374, + 0.027345796856, + 0.517248524536, + 3.221979621598, + 16.735791277416, + 55.382759562858, + 92.374251423784, + 123.896302747578, + 160.018824773163, + 180.761358164947, + 179.862619117885, + 166.400867115762, + 146.169213182628, + 124.194151241366, + 103.754643716735, + 85.816846880943, + 70.743602140892, + 58.341263333239, + 48.284628323305, + 40.219178348344, + 33.836018479389, + 28.883927929057, + 25.143486466631, + 22.381710432221, + 20.309684386202, + 18.617276059866, + 17.118941186793, + 15.929922086047, + 15.449239096094, + 16.001946102439, + 17.403308906094, + 18.95681599554, + 19.989484912423, + 20.292153187281, + 20.091147637266, + 19.72556323709, + 19.400025447496, + 19.152737357812, + 18.923710233374, + 18.61617145405, + 18.150019993042, + 17.508162241862, + 16.740932377864, + 15.92700686294, + 15.132657473697, + 14.399059254053, + 13.750089728075, + 13.198861345199, + 12.745086117901, + 12.372275214612, + 12.053824495746, + 11.764929342501, + 11.490960600502, + 11.228192934019, + 10.980249382108, + 10.754962853631, + 10.562537213805, + 10.412660833016, + 10.309457128399, + 10.24718850434, + 10.2108811801, + 10.182171970111, + 10.146177291085, + 10.095306890324, + 10.029774828725, + 9.956928401664, + 9.890013580384, + 9.844560030807, + 9.831513384605, + 9.850481511416, + 9.888603263008, + 9.92667310019, + 9.948032043039, + 9.94436755613, + 9.916784079163, + 9.87444640833, + 9.832460703318, + 9.807797425717, + 9.812278966949, + 9.845797127677, + 9.895358858894, + 9.941630492719, + 9.968190678482, + 9.967342254794, + 9.940931018834, + 9.898763166791, + 9.856414174959, + 9.831151297346, + 9.83490894276, + 9.867521883514, + 9.915875623625, + 9.960590334168, + 9.985333334797, + 9.982579696636, + 9.95434074499, + 9.91052583863, + 9.866742283215, + 9.840231375472, + 9.842866261203, + 9.874418798589, + 9.921745117864, + 9.965480968943, + 9.98933285559, + 9.985806672265, + 9.956920407789, + 9.912570434547, + 9.868342700196, + 9.841456455547, + 9.84376683505, + 9.875036180327, + 9.922120873112, + 9.965661552712, + 9.98936648325, + 9.985736572719, + 9.95678017656, + 9.912383359194, + 9.868123514296, + 9.841213939106, + 9.843506929073, + 9.874765117251, + 9.921846818522, + 9.965393775689, + 9.989113047562, + 9.98550253563, + 9.956567323124, + 9.912191075492, + 9.867949965666, + 9.841057114057, + 9.843365423182, + 9.87463845626, + 9.92173514592 + ], + "im": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + -6.689742e-06, + -0.000748363567, + 0.232097445493, + -0.298427335789, + 8.389511667575, + 30.139849934902, + 24.618091832908, + 16.31071369986, + 41.627904131854, + 52.918754367655, + 48.958096235491, + 44.680189163612, + 37.754303611032, + 30.179738568615, + 24.030948104817, + 18.91812361579, + 14.943271907765, + 11.870306396002, + 9.526860993222, + 7.756324905281, + 6.429579549988, + 5.442753233928, + 4.717401701416, + 4.203036457165, + 3.879393296033, + 3.747175202726, + 3.817284297483, + 4.047924700939, + 4.34948537606, + 4.656130676884, + 4.969064006623, + 5.324994904046, + 5.721224588111, + 6.091317636607, + 6.347037096746, + 6.451588665262, + 6.425658765034, + 6.312342418472, + 6.148276312706, + 5.959097449028, + 5.760651193907, + 5.557142618561, + 5.345668024166, + 5.126105726194, + 4.905801279599, + 4.695642896613, + 4.503511360963, + 4.331695368877, + 4.179110142241, + 4.044340161036, + 3.92627421123, + 3.823193072701, + 3.73259912009, + 3.652213963104, + 3.580921237607, + 3.518651485164, + 3.465376472768, + 3.420294173467, + 3.382052250066, + 3.349562445804, + 3.322263314165, + 3.299588763194, + 3.28054527612, + 3.264086004897, + 3.249825858158, + 3.23813742229, + 3.229385598777, + 3.223153217681, + 3.218438825604, + 3.214600292109, + 3.211784507958, + 3.210284885667, + 3.20976410054, + 3.209421741162, + 3.208860269061, + 3.208479582143, + 3.208851844529, + 3.209875619986, + 3.210865799056, + 3.211474871813, + 3.212121311037, + 3.213299558373, + 3.214774623564, + 3.215800986442, + 3.216061158693, + 3.216075651938, + 3.216539900055, + 3.217444060745, + 3.218165821863, + 3.21841050114, + 3.218639809668, + 3.219369860726, + 3.220368318341, + 3.220890963649, + 3.220632324981, + 3.220132572403, + 3.220104821723, + 3.220550296622, + 3.220853057312, + 3.220721444412, + 3.220614890428, + 3.221042398211, + 3.221765088514, + 3.222037343958, + 3.221556335997, + 3.220864528706, + 3.220674393582, + 3.220984347718, + 3.221175184648, + 3.220951844046, + 3.220770002488, + 3.221135334311, + 3.221807071611, + 3.222038908976, + 3.221527374638, + 3.220813636001, + 3.220608464895, + 3.220908748232, + 3.221094081334, + 3.220868337124, + 3.220686246556, + 3.221052900011, + 3.221727347863, + 3.221963213003, + 3.221456782096, + 3.220748807207, + 3.220549646796, + 3.220855896626, + 3.22104696267, + 3.22082658624, + 3.220649450126 + ], + "period": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.2, + 2.16, + 2.928, + 3.5424, + 4.03392, + 4.437312, + 4.8810432, + 5.36914752, + 5.906062272, + 6.4966684992, + 7.14633534912, + 7.860968884032, + 8.647065772435, + 9.511772349679, + 10.462949584647, + 11.509244543111, + 12.660168997422, + 13.926185897165, + 15.318804486881, + 16.850684935569, + 18.535753429126, + 20.389328772039, + 22.428261649243, + 24.671087814167, + 26.506558906772, + 27.863332645721, + 28.617495767314, + 28.621690998332, + 27.947302457117, + 26.936912931876, + 25.987521125592, + 25.308281806484, + 24.835499474058, + 24.376361317194, + 23.81020726162, + 23.154951785225, + 22.499394725002, + 21.928390866131, + 21.489834199054, + 21.19211681312, + 21.010022556661, + 20.896844478092, + 20.80615619725, + 20.710613353691, + 20.604191714523, + 20.491818474656, + 20.379825400706, + 20.274091346373, + 20.182030617807, + 20.111626454413, + 20.066781276252, + 20.044134192134, + 20.034782936328, + 20.028869273874, + 20.019045496957, + 20.00142144179, + 19.975457645019, + 19.94431114191, + 19.914965900889, + 19.896238878817, + 19.894597499863, + 19.910556914753, + 19.938425538307, + 19.969161965169, + 19.993764285368, + 20.005427649886, + 20.000950247775, + 19.982309944487, + 19.957455511215, + 19.938082714531, + 19.934189323757, + 19.948769903549, + 19.976603786928, + 20.00757462966, + 20.031364627775, + 20.040601154547, + 20.032390590548, + 20.009481881112, + 19.980628540239, + 19.958096970598, + 19.952052634353, + 19.965225227752, + 19.991901069325, + 20.021564125663, + 20.043769875203, + 20.051241203803, + 20.041257627907, + 20.016725148231, + 19.986509442948, + 19.962923063429, + 19.956087764677, + 19.968617918999, + 19.994682818436, + 20.023713242773, + 20.045285658123, + 20.052181996368, + 20.041736849866, + 20.016883608713, + 19.986481017741, + 19.962804092735, + 19.955921503095, + 19.968403637839, + 19.994404111627, + 20.023365149267, + 20.04488410423, + 20.051756458636, + 20.041317853802, + 20.016493759174, + 19.986130977172, + 19.9624924283, + 19.955638583675, + 19.968138758022, + 19.994151826497, + 20.023126870999, + 20.044665187153, + 20.051562177822, + 20.041150935491, + 20.016353741931, + 19.986014613605, + 19.96239478808, + 19.955554794969, + 19.968065675077, + 19.994088550098, + 20.023073890744, + 20.044623014256, + 20.051530450554, + 20.041128284341, + 20.016338139647, + 19.986003889532, + 19.96238714696, + 19.955549188475, + 19.968061825942 + ], + "phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 50.648527352825, + 73.300582835047, + 25.307266053938, + -22.254791836301, + -73.303315121568, + -47.811765502577, + 87.47370542898, + -86.652722356377, + -11.203113858387, + 40.912735719448, + 27.480613092736, + 16.373391117338, + 5.308282527241, + -7.563207056645, + -24.056004203347, + -45.16793429964, + -68.772760205611, + 89.804915306267, + 72.72813463289, + 58.905277263158, + 46.24795010121, + 32.403706773766, + 14.009666331644, + -10.167428715966, + -37.043183898823, + -59.330061153766, + -75.85420907258, + 89.856654713269, + 75.069770684388, + 58.114334457746, + 38.530519898548, + 17.32302198639, + -3.763082224375, + -23.52546948528, + -41.54127678385, + -58.101677300655, + -74.027160482731, + 89.833624780971, + 72.993782300566, + 55.362296019318, + 37.045871099746, + 18.207069437574, + -0.883449798512, + -19.799573681379, + -38.150627054836, + -55.83707052747, + -73.06685302868, + 89.826465662442, + 72.55152291694, + 54.924023300643, + 36.866819822954, + 18.407051912921, + -0.305537254058, + -19.003214110264, + -37.397167343885, + -55.331060918424, + -72.856437176449, + 89.824979729648, + 72.473856833791, + 54.890919804264, + 36.945500973303, + 18.596062510487, + -0.067537334479, + -18.799959309526, + -37.281754098986, + -55.297993451719, + -72.861217885766, + 89.825163248336, + 72.49556697757, + 54.926432229618, + 36.978167528525, + 18.612774134727, + -0.07234546325, + -18.823917490883, + -37.314659363289, + -55.326165897868, + -72.875487363905, + 89.825286480858, + 72.504364926, + 54.936805530823, + 36.984562558449, + 18.611907248866, + -0.081144896186, + -18.838068875273, + -37.329114213179, + -55.336370804466, + -72.879889188633, + 89.825318857807, + 72.506226850794, + 54.938166626444, + 36.98406048047, + 18.609273831619, + -0.085190900965, + -18.842181633958, + -37.332076481926, + -55.337801831441, + -72.880244901838, + 89.825319432228, + 72.506104575839, + 54.937797225498, + 36.983535790786, + 18.608752964939, + -0.085545550687, + -18.842257007211, + -37.331895187216, + -55.337529918543, + -72.880068487514, + 89.825317651117, + 72.505961421367, + 54.937608682017, + 36.983396190351, + 18.608725693632, + -0.085439403009, + -18.842049213412, + -37.331663464011, + -55.337355075945, + -72.879988295552, + 89.825317020855, + 72.505921587242, + 54.937571777805, + 36.983390063721, + 18.608760082081, + -0.085372396224, + -18.841971431016, + -37.33159952883, + -55.337318160414, + -72.879975607463, + 89.825316952598, + 72.50591954386 + ], + "delta_phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 47.99331678111, + 47.562057890239, + 51.048523285267, + 1.0, + 1.0, + 174.126427785357, + 1.0, + 1.0, + 13.432122626712, + 11.107221975399, + 11.065108590096, + 12.871489583886, + 16.492797146702, + 21.111930096292, + 23.604825905972, + 1.0, + 17.076780673377, + 13.822857369732, + 12.657327161949, + 13.844243327444, + 18.394040442122, + 24.177095047609, + 26.875755182857, + 22.286877254943, + 16.524147918814, + 1.0, + 14.78688402888, + 16.955436226642, + 19.583814559198, + 21.207497912158, + 21.086104210765, + 19.762387260906, + 18.01580729857, + 16.560400516805, + 15.925483182077, + 1.0, + 16.839842480405, + 17.631486281248, + 18.316424919572, + 18.838801662172, + 19.090519236086, + 18.916123882868, + 18.351053373456, + 17.686443472634, + 17.22978250121, + 1.0, + 17.274942745502, + 17.627499616297, + 18.057203477689, + 18.459767910032, + 18.71258916698, + 18.697676856206, + 18.393953233621, + 17.933893574539, + 17.525376258025, + 1.0, + 17.351122895857, + 17.582937029527, + 17.945418830961, + 18.349438462816, + 18.663599844966, + 18.732421975047, + 18.481794789461, + 18.016239352733, + 17.563224434047, + 1.0, + 17.329596270767, + 17.569134747951, + 17.948264701093, + 18.365393393799, + 18.685119597977, + 18.751572027634, + 18.490741872405, + 18.01150653458, + 17.549321466036, + 1.0, + 17.320921554858, + 17.567559395177, + 17.952242972374, + 18.372655309583, + 18.693052145052, + 18.756923979086, + 18.491045337906, + 18.007256591287, + 17.543518384167, + 1.0, + 17.319092007013, + 17.56806022435, + 17.954106145974, + 18.37478664885, + 18.694464732585, + 18.756990732992, + 18.489894847968, + 18.005725349514, + 17.542443070398, + 1.0, + 17.31921485639, + 17.56830735034, + 17.954261434713, + 18.374782825847, + 18.694298515626, + 18.756711456524, + 18.489638180005, + 18.005634731327, + 17.54253856897, + 1.0, + 17.31935622975, + 17.56835273935, + 17.954212491666, + 18.374670496718, + 18.694165096641, + 18.756609810404, + 18.489614250599, + 18.005691611934, + 17.542633219608, + 1.0, + 17.319395433613, + 17.568349809437, + 17.954181714083, + 18.37462998164, + 18.694132478306, + 18.756599034792, + 18.489628097813, + 18.005718631584, + 17.542657447049, + 1.0, + 17.319397408738 + ], + "alpha": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.5, + 0.05, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05 + ], + "mama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 99.960502830948, + 99.841125139401, + 99.706410382431, + 99.571089863309, + 99.449876870144, + 99.356030476637, + 99.300061152805, + 99.288705545165, + 99.324270267906, + 99.404409304511, + 100.583882652256, + 100.676041069643, + 100.784897516161, + 100.895652640353, + 100.993528508335, + 101.065204632918, + 101.100112201272, + 101.091459141209, + 101.036886184148, + 100.938689324941, + 99.58766666247, + 99.486930779347, + 99.36992574038, + 99.251429453361, + 99.146199480693, + 99.067536956658, + 99.025992308825, + 99.028340143384, + 99.076923136215, + 99.169429529404, + 100.466392764702, + 100.564425676467, + 100.678862892643, + 100.794919748011, + 100.897832260611, + 100.97429319758, + 101.013746337701, + 101.009411570816, + 100.958940992275, + 100.864641392662, + 99.550642696331, + 99.451758011514, + 99.336511610939, + 99.219686030392, + 99.116043228872, + 99.038888517428, + 98.998776291557, + 99.002484926979, + 99.05236068063, + 99.146095196599, + 100.454725598299, + 100.553341868384, + 100.668333274965, + 100.784916611217, + 100.888329280656, + 100.965265366623, + 101.005169898292, + 101.001263953377, + 100.951200755709, + 100.857288167923, + 99.546966083962, + 99.448265229763, + 99.333193468275, + 99.216533794862, + 99.113048605118, + 99.036043624863, + 98.996073643619, + 98.999917411438, + 99.049921540867, + 99.143778013823, + 100.453567006912, + 100.552241206566, + 100.667287646238, + 100.783923263926, + 100.88738560073, + 100.964368870693, + 101.004318227158, + 101.0004548658, + 100.95043212251, + 100.856557966385, + 99.546600983192, + 99.447918384033, + 99.332863964831, + 99.21622076659, + 99.11275122826, + 99.035761116847, + 98.995805261005, + 98.999662447955, + 99.049679325557, + 99.143547909279, + 100.453451954639, + 100.552131906907, + 100.667183811562, + 100.783824620984, + 100.887291889935, + 100.964279845438, + 101.004233653166, + 101.000374520508, + 100.950355794482, + 100.856485454758, + 99.546564727379, + 99.44788394101, + 99.33283124396, + 99.216189681762, + 99.112721697674, + 99.03573306279, + 98.99577860965, + 98.999637129168, + 99.04965527271, + 99.143525059074, + 100.453440529537, + 100.55212105306 + ], + "fama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 93.858273469059, + 94.007844760818, + 94.150308901358, + 94.285828425407, + 94.414929636525, + 94.538457157528, + 94.65749725741, + 94.773277464604, + 94.887052284686, + 94.999986210182, + 96.3959603207, + 96.502962339424, + 96.610010718842, + 96.71715176688, + 96.824061185416, + 96.930089771604, + 97.034340332346, + 97.135768302567, + 97.233296249607, + 97.32593107649, + 97.891364972985, + 97.931254118144, + 97.9672209087, + 97.999326122317, + 98.027997956276, + 98.053986431286, + 98.078286578224, + 98.102037917353, + 98.126410047825, + 98.152485534864, + 98.730962342324, + 98.776798925677, + 98.824350524851, + 98.87361475543, + 98.92422019306, + 98.975472018173, + 99.026428876161, + 99.076003443527, + 99.123076882246, + 99.166615995006, + 99.262622670338, + 99.267351053867, + 99.269080067794, + 99.267845216859, + 99.264050167159, + 99.258421125916, + 99.251930005057, + 99.245693878105, + 99.240860548168, + 99.238491414379, + 99.542549960359, + 99.567819758059, + 99.595332595982, + 99.625072196363, + 99.65665362347, + 99.689368917049, + 99.72226394158, + 99.754238941875, + 99.784162987221, + 99.810991116739, + 99.744984858544, + 99.737566867825, + 99.727457532836, + 99.714684439387, + 99.69964354353, + 99.683053545563, + 99.665879048015, + 99.6492300071, + 99.634247295444, + 99.621985563404, + 99.829880924281, + 99.847939931338, + 99.86842362421, + 99.891311115203, + 99.916212977341, + 99.942416874675, + 99.968964408487, + 99.99475166992, + 100.018643681235, + 100.039591538364, + 99.916343899571, + 99.904633261682, + 99.890339029261, + 99.873486072694, + 99.854467701583, + 99.834000036965, + 99.813045167566, + 99.792710599576, + 99.774134817725, + 99.758370145014, + 99.93214059742, + 99.947640380158, + 99.965628965943, + 99.986083857319, + 100.008614058134, + 100.032505702817, + 100.056798901575, + 100.080388292049, + 100.10213747961, + 100.120996178988, + 99.977388316086, + 99.964150706709, + 99.94836772014, + 99.930063269181, + 99.909629729893, + 99.887782313216, + 99.865482220627, + 99.84383609334, + 99.823981572824, + 99.806970159981, + 99.96858775237, + 99.983176084887 + ] + } }, { - "index": 79, - "value": 107.74003, - "phase": -80.146549032588, - "delta_phase": 39.164916875397, - "alpha": 0.05, - "mama": 106.550063234142, - "fama": 105.512403493614 + "id": "step-and-trend", + "classification": "synthetic teaching input", + "lesson": "A level jump followed by changing slopes shows MAMA's ratchet and FAMA's slower response.", + "observations": [ + { + "index": 0, + "timestamp": "2026-01-01T00:00:00Z", + "value": 98.0 + }, + { + "index": 1, + "timestamp": "2026-01-02T00:00:00Z", + "value": 98.05 + }, + { + "index": 2, + "timestamp": "2026-01-03T00:00:00Z", + "value": 98.1 + }, + { + "index": 3, + "timestamp": "2026-01-04T00:00:00Z", + "value": 98.15 + }, + { + "index": 4, + "timestamp": "2026-01-05T00:00:00Z", + "value": 98.2 + }, + { + "index": 5, + "timestamp": "2026-01-06T00:00:00Z", + "value": 98.25 + }, + { + "index": 6, + "timestamp": "2026-01-07T00:00:00Z", + "value": 98.3 + }, + { + "index": 7, + "timestamp": "2026-01-08T00:00:00Z", + "value": 98.35 + }, + { + "index": 8, + "timestamp": "2026-01-09T00:00:00Z", + "value": 98.4 + }, + { + "index": 9, + "timestamp": "2026-01-10T00:00:00Z", + "value": 98.45 + }, + { + "index": 10, + "timestamp": "2026-01-11T00:00:00Z", + "value": 98.5 + }, + { + "index": 11, + "timestamp": "2026-01-12T00:00:00Z", + "value": 98.55 + }, + { + "index": 12, + "timestamp": "2026-01-13T00:00:00Z", + "value": 98.6 + }, + { + "index": 13, + "timestamp": "2026-01-14T00:00:00Z", + "value": 98.65 + }, + { + "index": 14, + "timestamp": "2026-01-15T00:00:00Z", + "value": 98.7 + }, + { + "index": 15, + "timestamp": "2026-01-16T00:00:00Z", + "value": 98.75 + }, + { + "index": 16, + "timestamp": "2026-01-17T00:00:00Z", + "value": 98.8 + }, + { + "index": 17, + "timestamp": "2026-01-18T00:00:00Z", + "value": 98.85 + }, + { + "index": 18, + "timestamp": "2026-01-19T00:00:00Z", + "value": 98.9 + }, + { + "index": 19, + "timestamp": "2026-01-20T00:00:00Z", + "value": 98.95 + }, + { + "index": 20, + "timestamp": "2026-01-21T00:00:00Z", + "value": 99.0 + }, + { + "index": 21, + "timestamp": "2026-01-22T00:00:00Z", + "value": 99.05 + }, + { + "index": 22, + "timestamp": "2026-01-23T00:00:00Z", + "value": 99.1 + }, + { + "index": 23, + "timestamp": "2026-01-24T00:00:00Z", + "value": 99.15 + }, + { + "index": 24, + "timestamp": "2026-01-25T00:00:00Z", + "value": 99.2 + }, + { + "index": 25, + "timestamp": "2026-01-26T00:00:00Z", + "value": 99.25 + }, + { + "index": 26, + "timestamp": "2026-01-27T00:00:00Z", + "value": 99.3 + }, + { + "index": 27, + "timestamp": "2026-01-28T00:00:00Z", + "value": 99.35 + }, + { + "index": 28, + "timestamp": "2026-01-29T00:00:00Z", + "value": 99.4 + }, + { + "index": 29, + "timestamp": "2026-01-30T00:00:00Z", + "value": 99.45 + }, + { + "index": 30, + "timestamp": "2026-01-31T00:00:00Z", + "value": 99.5 + }, + { + "index": 31, + "timestamp": "2026-02-01T00:00:00Z", + "value": 99.55 + }, + { + "index": 32, + "timestamp": "2026-02-02T00:00:00Z", + "value": 99.6 + }, + { + "index": 33, + "timestamp": "2026-02-03T00:00:00Z", + "value": 99.65 + }, + { + "index": 34, + "timestamp": "2026-02-04T00:00:00Z", + "value": 99.7 + }, + { + "index": 35, + "timestamp": "2026-02-05T00:00:00Z", + "value": 99.75 + }, + { + "index": 36, + "timestamp": "2026-02-06T00:00:00Z", + "value": 99.8 + }, + { + "index": 37, + "timestamp": "2026-02-07T00:00:00Z", + "value": 99.85 + }, + { + "index": 38, + "timestamp": "2026-02-08T00:00:00Z", + "value": 99.9 + }, + { + "index": 39, + "timestamp": "2026-02-09T00:00:00Z", + "value": 99.95 + }, + { + "index": 40, + "timestamp": "2026-02-10T00:00:00Z", + "value": 100.0 + }, + { + "index": 41, + "timestamp": "2026-02-11T00:00:00Z", + "value": 100.05 + }, + { + "index": 42, + "timestamp": "2026-02-12T00:00:00Z", + "value": 100.1 + }, + { + "index": 43, + "timestamp": "2026-02-13T00:00:00Z", + "value": 100.15 + }, + { + "index": 44, + "timestamp": "2026-02-14T00:00:00Z", + "value": 100.2 + }, + { + "index": 45, + "timestamp": "2026-02-15T00:00:00Z", + "value": 100.25 + }, + { + "index": 46, + "timestamp": "2026-02-16T00:00:00Z", + "value": 100.3 + }, + { + "index": 47, + "timestamp": "2026-02-17T00:00:00Z", + "value": 100.35 + }, + { + "index": 48, + "timestamp": "2026-02-18T00:00:00Z", + "value": 108.4 + }, + { + "index": 49, + "timestamp": "2026-02-19T00:00:00Z", + "value": 108.675291 + }, + { + "index": 50, + "timestamp": "2026-02-20T00:00:00Z", + "value": 108.94 + }, + { + "index": 51, + "timestamp": "2026-02-21T00:00:00Z", + "value": 109.184264 + }, + { + "index": 52, + "timestamp": "2026-02-22T00:00:00Z", + "value": 109.399615 + }, + { + "index": 53, + "timestamp": "2026-02-23T00:00:00Z", + "value": 109.579555 + }, + { + "index": 54, + "timestamp": "2026-02-24T00:00:00Z", + "value": 109.72 + }, + { + "index": 55, + "timestamp": "2026-02-25T00:00:00Z", + "value": 109.819555 + }, + { + "index": 56, + "timestamp": "2026-02-26T00:00:00Z", + "value": 109.879615 + }, + { + "index": 57, + "timestamp": "2026-02-27T00:00:00Z", + "value": 109.904264 + }, + { + "index": 58, + "timestamp": "2026-02-28T00:00:00Z", + "value": 109.9 + }, + { + "index": 59, + "timestamp": "2026-03-01T00:00:00Z", + "value": 109.875291 + }, + { + "index": 60, + "timestamp": "2026-03-02T00:00:00Z", + "value": 109.84 + }, + { + "index": 61, + "timestamp": "2026-03-03T00:00:00Z", + "value": 109.804709 + }, + { + "index": 62, + "timestamp": "2026-03-04T00:00:00Z", + "value": 109.78 + }, + { + "index": 63, + "timestamp": "2026-03-05T00:00:00Z", + "value": 109.775736 + }, + { + "index": 64, + "timestamp": "2026-03-06T00:00:00Z", + "value": 109.800385 + }, + { + "index": 65, + "timestamp": "2026-03-07T00:00:00Z", + "value": 109.860445 + }, + { + "index": 66, + "timestamp": "2026-03-08T00:00:00Z", + "value": 109.96 + }, + { + "index": 67, + "timestamp": "2026-03-09T00:00:00Z", + "value": 110.100445 + }, + { + "index": 68, + "timestamp": "2026-03-10T00:00:00Z", + "value": 110.280385 + }, + { + "index": 69, + "timestamp": "2026-03-11T00:00:00Z", + "value": 110.495736 + }, + { + "index": 70, + "timestamp": "2026-03-12T00:00:00Z", + "value": 110.74 + }, + { + "index": 71, + "timestamp": "2026-03-13T00:00:00Z", + "value": 111.004709 + }, + { + "index": 72, + "timestamp": "2026-03-14T00:00:00Z", + "value": 111.28 + }, + { + "index": 73, + "timestamp": "2026-03-15T00:00:00Z", + "value": 111.555291 + }, + { + "index": 74, + "timestamp": "2026-03-16T00:00:00Z", + "value": 111.82 + }, + { + "index": 75, + "timestamp": "2026-03-17T00:00:00Z", + "value": 112.064264 + }, + { + "index": 76, + "timestamp": "2026-03-18T00:00:00Z", + "value": 112.279615 + }, + { + "index": 77, + "timestamp": "2026-03-19T00:00:00Z", + "value": 112.459555 + }, + { + "index": 78, + "timestamp": "2026-03-20T00:00:00Z", + "value": 112.6 + }, + { + "index": 79, + "timestamp": "2026-03-21T00:00:00Z", + "value": 112.699555 + }, + { + "index": 80, + "timestamp": "2026-03-22T00:00:00Z", + "value": 112.759615 + }, + { + "index": 81, + "timestamp": "2026-03-23T00:00:00Z", + "value": 112.784264 + }, + { + "index": 82, + "timestamp": "2026-03-24T00:00:00Z", + "value": 112.78 + }, + { + "index": 83, + "timestamp": "2026-03-25T00:00:00Z", + "value": 112.755291 + }, + { + "index": 84, + "timestamp": "2026-03-26T00:00:00Z", + "value": 112.72 + }, + { + "index": 85, + "timestamp": "2026-03-27T00:00:00Z", + "value": 112.684709 + }, + { + "index": 86, + "timestamp": "2026-03-28T00:00:00Z", + "value": 112.66 + }, + { + "index": 87, + "timestamp": "2026-03-29T00:00:00Z", + "value": 112.655736 + }, + { + "index": 88, + "timestamp": "2026-03-30T00:00:00Z", + "value": 112.680385 + }, + { + "index": 89, + "timestamp": "2026-03-31T00:00:00Z", + "value": 112.740445 + }, + { + "index": 90, + "timestamp": "2026-04-01T00:00:00Z", + "value": 112.84 + }, + { + "index": 91, + "timestamp": "2026-04-02T00:00:00Z", + "value": 112.980445 + }, + { + "index": 92, + "timestamp": "2026-04-03T00:00:00Z", + "value": 113.160385 + }, + { + "index": 93, + "timestamp": "2026-04-04T00:00:00Z", + "value": 113.375736 + }, + { + "index": 94, + "timestamp": "2026-04-05T00:00:00Z", + "value": 113.62 + }, + { + "index": 95, + "timestamp": "2026-04-06T00:00:00Z", + "value": 113.884709 + }, + { + "index": 96, + "timestamp": "2026-04-07T00:00:00Z", + "value": 114.16 + }, + { + "index": 97, + "timestamp": "2026-04-08T00:00:00Z", + "value": 114.17101 + }, + { + "index": 98, + "timestamp": "2026-04-09T00:00:00Z", + "value": 114.161394 + }, + { + "index": 99, + "timestamp": "2026-04-10T00:00:00Z", + "value": 114.113013 + }, + { + "index": 100, + "timestamp": "2026-04-11T00:00:00Z", + "value": 114.012404 + }, + { + "index": 101, + "timestamp": "2026-04-12T00:00:00Z", + "value": 113.852404 + }, + { + "index": 102, + "timestamp": "2026-04-13T00:00:00Z", + "value": 113.633013 + }, + { + "index": 103, + "timestamp": "2026-04-14T00:00:00Z", + "value": 113.361394 + }, + { + "index": 104, + "timestamp": "2026-04-15T00:00:00Z", + "value": 113.05101 + }, + { + "index": 105, + "timestamp": "2026-04-16T00:00:00Z", + "value": 112.72 + }, + { + "index": 106, + "timestamp": "2026-04-17T00:00:00Z", + "value": 112.38899 + }, + { + "index": 107, + "timestamp": "2026-04-18T00:00:00Z", + "value": 112.078606 + }, + { + "index": 108, + "timestamp": "2026-04-19T00:00:00Z", + "value": 111.806987 + }, + { + "index": 109, + "timestamp": "2026-04-20T00:00:00Z", + "value": 111.587596 + }, + { + "index": 110, + "timestamp": "2026-04-21T00:00:00Z", + "value": 111.427596 + }, + { + "index": 111, + "timestamp": "2026-04-22T00:00:00Z", + "value": 111.326987 + }, + { + "index": 112, + "timestamp": "2026-04-23T00:00:00Z", + "value": 111.278606 + }, + { + "index": 113, + "timestamp": "2026-04-24T00:00:00Z", + "value": 111.26899 + }, + { + "index": 114, + "timestamp": "2026-04-25T00:00:00Z", + "value": 111.28 + }, + { + "index": 115, + "timestamp": "2026-04-26T00:00:00Z", + "value": 111.29101 + }, + { + "index": 116, + "timestamp": "2026-04-27T00:00:00Z", + "value": 111.281394 + }, + { + "index": 117, + "timestamp": "2026-04-28T00:00:00Z", + "value": 111.233013 + }, + { + "index": 118, + "timestamp": "2026-04-29T00:00:00Z", + "value": 111.132404 + }, + { + "index": 119, + "timestamp": "2026-04-30T00:00:00Z", + "value": 110.972404 + }, + { + "index": 120, + "timestamp": "2026-05-01T00:00:00Z", + "value": 110.753013 + }, + { + "index": 121, + "timestamp": "2026-05-02T00:00:00Z", + "value": 110.481394 + }, + { + "index": 122, + "timestamp": "2026-05-03T00:00:00Z", + "value": 110.17101 + }, + { + "index": 123, + "timestamp": "2026-05-04T00:00:00Z", + "value": 109.84 + }, + { + "index": 124, + "timestamp": "2026-05-05T00:00:00Z", + "value": 109.50899 + }, + { + "index": 125, + "timestamp": "2026-05-06T00:00:00Z", + "value": 109.198606 + }, + { + "index": 126, + "timestamp": "2026-05-07T00:00:00Z", + "value": 108.926987 + }, + { + "index": 127, + "timestamp": "2026-05-08T00:00:00Z", + "value": 108.707596 + }, + { + "index": 128, + "timestamp": "2026-05-09T00:00:00Z", + "value": 108.547596 + }, + { + "index": 129, + "timestamp": "2026-05-10T00:00:00Z", + "value": 108.446987 + }, + { + "index": 130, + "timestamp": "2026-05-11T00:00:00Z", + "value": 108.398606 + }, + { + "index": 131, + "timestamp": "2026-05-12T00:00:00Z", + "value": 108.38899 + }, + { + "index": 132, + "timestamp": "2026-05-13T00:00:00Z", + "value": 108.4 + }, + { + "index": 133, + "timestamp": "2026-05-14T00:00:00Z", + "value": 108.41101 + }, + { + "index": 134, + "timestamp": "2026-05-15T00:00:00Z", + "value": 108.401394 + }, + { + "index": 135, + "timestamp": "2026-05-16T00:00:00Z", + "value": 108.353013 + }, + { + "index": 136, + "timestamp": "2026-05-17T00:00:00Z", + "value": 108.252404 + }, + { + "index": 137, + "timestamp": "2026-05-18T00:00:00Z", + "value": 108.092404 + }, + { + "index": 138, + "timestamp": "2026-05-19T00:00:00Z", + "value": 107.873013 + }, + { + "index": 139, + "timestamp": "2026-05-20T00:00:00Z", + "value": 107.601394 + }, + { + "index": 140, + "timestamp": "2026-05-21T00:00:00Z", + "value": 107.29101 + }, + { + "index": 141, + "timestamp": "2026-05-22T00:00:00Z", + "value": 106.96 + }, + { + "index": 142, + "timestamp": "2026-05-23T00:00:00Z", + "value": 106.62899 + }, + { + "index": 143, + "timestamp": "2026-05-24T00:00:00Z", + "value": 106.318606 + } + ], + "expected": { + "smooth": [ + null, + null, + null, + 98.1, + 98.15, + 98.2, + 98.25, + 98.3, + 98.35, + 98.4, + 98.45, + 98.5, + 98.55, + 98.6, + 98.65, + 98.7, + 98.75, + 98.8, + 98.85, + 98.9, + 98.95, + 99.0, + 99.05, + 99.1, + 99.15, + 99.2, + 99.25, + 99.3, + 99.35, + 99.4, + 99.45, + 99.5, + 99.55, + 99.6, + 99.65, + 99.7, + 99.75, + 99.8, + 99.85, + 99.9, + 99.95, + 100.0, + 100.05, + 100.1, + 100.15, + 100.2, + 100.25, + 100.3, + 103.55, + 106.0901164, + 107.8935873, + 108.9307638, + 109.1706543, + 109.3825593, + 109.5602159, + 109.6996945, + 109.799668, + 109.8615011, + 109.8891577, + 109.8889307, + 109.8690137, + 109.8389418, + 109.8089418, + 109.7892362, + 109.7893457, + 109.8174407, + 109.8797841, + 109.9803055, + 110.120332, + 110.2984989, + 110.5108423, + 110.7510693, + 111.0109863, + 111.2810582, + 111.5510582, + 111.8107638, + 112.0506543, + 112.2625593, + 112.4402159, + 112.5796945, + 112.679668, + 112.7415011, + 112.7691577, + 112.7689307, + 112.7490137, + 112.7189418, + 112.6889418, + 112.6692362, + 112.6693457, + 112.6974407, + 112.7597841, + 112.8603055, + 113.000332, + 113.1784989, + 113.3908423, + 113.6310693, + 113.8909863, + 114.0553458, + 114.1363315, + 114.1438254, + 114.0882453, + 113.9834248, + 113.8227085, + 113.6061827, + 113.3406652, + 113.0388831, + 112.7179374, + 112.3972404, + 112.0961746, + 111.8317547, + 111.6165752, + 111.4572915, + 111.3538173, + 111.2993348, + 111.2811169, + 111.2820626, + 111.2827596, + 111.2638254, + 111.2082453, + 111.1034248, + 110.9427085, + 110.7261827, + 110.4606652, + 110.1588831, + 109.8379374, + 109.5172404, + 109.2161746, + 108.9517547, + 108.7365752, + 108.5772915, + 108.4738173, + 108.4193348, + 108.4011169, + 108.4020626, + 108.4027596, + 108.3838254, + 108.3282453, + 108.2234248, + 108.0627085, + 107.8461827, + 107.5806652, + 107.2788831, + 106.9579374, + 106.6372404 + ], + "detrender": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 5.1194754, + 5.9757516, + 46.57322475, + 50.420181888, + 7.7002382592, + 8.056616364, + 0.07554070152, + 0.078421071672, + 0.081589478839, + 0.085074726723, + 0.088908499395, + 0.093125649335, + 0.097764514268, + 0.102867265695, + 0.108480292265, + 0.114654621491, + 0.12144638364, + 0.128917322005, + 0.137135354205, + 0.146175189625, + 0.156119008588, + 0.167057209447, + 0.179089230391, + 0.192276440865, + 0.203145241731, + 0.212112097431, + 0.219521385196, + 0.22565869266, + 0.230760978611, + 0.235028602081, + 0.238631539843, + 0.241712320144, + 0.244393635937, + 0.246783346181, + 0.248978897989, + 0.251071140418, + 1.153542586313, + 1.873262329818, + 7.939049356266, + 13.556730127509, + 11.613996101459, + 8.191372086479, + 4.050878599878, + 1.770767692171, + 1.124892125532, + 0.811490452732, + 0.583876442915, + 0.378847829841, + 0.207312814056, + 0.072691652907, + -0.026144990992, + -0.085651017579, + -0.104386652193, + -0.083062011301, + -0.023882603008, + 0.069426104365, + 0.191293980131, + 0.334212250867, + 0.488954056304, + 0.645091823343, + 0.791738984134, + 0.918429215967, + 1.016027641758, + 1.077549843005, + 1.098770254373, + 1.07853326935, + 1.018744515865, + 0.924056303929, + 0.801304559113, + 0.658795045408, + 0.505593686809, + 0.351001320159, + 0.204327809865, + 0.074883231847, + -0.028112921198, + -0.095994445468, + -0.121508130687, + -0.099816735168, + -0.029419937134, + 0.0869978622, + 0.241711375436, + 0.421462389977, + 0.608389633021, + 0.783281531657, + 0.930230455945, + 1.012342844288, + 1.034287556589, + 0.848604598211, + 0.507664054412, + 0.200457152199, + -0.078453168599, + -0.30029051535, + -0.494888034957, + -0.68925843272, + -0.871697609476, + -1.022284911644, + -1.117989627136, + -1.147518675853, + -1.113363722339, + -1.0243491699, + -0.88850160593, + -0.716403435827, + -0.524602269081, + -0.336056014368, + -0.176503310909, + -0.069465795682, + -0.032358148697, + -0.074256197348, + -0.195103258783, + -0.385226136014, + -0.624364606723, + -0.881419569489, + -1.117702664763, + -1.295731908514, + -1.391091325526, + -1.398054674029, + -1.322499382472, + -1.174700277732, + -0.973981739797, + -0.748835057757, + -0.526948952073, + -0.32918400227, + -0.171268205237, + -0.067571524321, + -0.031744574375, + -0.073521504252, + -0.194490112031, + -0.385505408781, + -0.626086115314, + -0.885094438891, + -1.123850133112, + -1.304374506725 + ], + "i1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 5.1194754, + 5.9757516, + 46.57322475, + 50.420181888, + 7.7002382592, + 8.056616364, + 0.07554070152, + 0.078421071672, + 0.081589478839, + 0.085074726723, + 0.088908499395, + 0.093125649335, + 0.097764514268, + 0.102867265695, + 0.108480292265, + 0.114654621491, + 0.12144638364, + 0.128917322005, + 0.137135354205, + 0.146175189625, + 0.156119008588, + 0.167057209447, + 0.179089230391, + 0.192276440865, + 0.203145241731, + 0.212112097431, + 0.219521385196, + 0.22565869266, + 0.230760978611, + 0.235028602081, + 0.238631539843, + 0.241712320144, + 0.244393635937, + 0.246783346181, + 0.248978897989, + 0.251071140418, + 1.153542586313, + 1.873262329818, + 7.939049356266, + 13.556730127509, + 11.613996101459, + 8.191372086479, + 4.050878599878, + 1.770767692171, + 1.124892125532, + 0.811490452732, + 0.583876442915, + 0.378847829841, + 0.207312814056, + 0.072691652907, + -0.026144990992, + -0.085651017579, + -0.104386652193, + -0.083062011301, + -0.023882603008, + 0.069426104365, + 0.191293980131, + 0.334212250867, + 0.488954056304, + 0.645091823343, + 0.791738984134, + 0.918429215967, + 1.016027641758, + 1.077549843005, + 1.098770254373, + 1.07853326935, + 1.018744515865, + 0.924056303929, + 0.801304559113, + 0.658795045408, + 0.505593686809, + 0.351001320159, + 0.204327809865, + 0.074883231847, + -0.028112921198, + -0.095994445468, + -0.121508130687, + -0.099816735168, + -0.029419937134, + 0.0869978622, + 0.241711375436, + 0.421462389977, + 0.608389633021, + 0.783281531657, + 0.930230455945, + 1.012342844288, + 1.034287556589, + 0.848604598211, + 0.507664054412, + 0.200457152199, + -0.078453168599, + -0.30029051535, + -0.494888034957, + -0.68925843272, + -0.871697609476, + -1.022284911644, + -1.117989627136, + -1.147518675853, + -1.113363722339, + -1.0243491699, + -0.88850160593, + -0.716403435827, + -0.524602269081, + -0.336056014368, + -0.176503310909, + -0.069465795682, + -0.032358148697, + -0.074256197348, + -0.195103258783, + -0.385226136014, + -0.624364606723, + -0.881419569489, + -1.117702664763, + -1.295731908514, + -1.391091325526, + -1.398054674029, + -1.322499382472, + -1.174700277732, + -0.973981739797, + -0.748835057757, + -0.526948952073, + -0.32918400227, + -0.171268205237, + -0.067571524321, + -0.031744574375, + -0.073521504252, + -0.194490112031, + -0.385505408781, + -0.626086115314 + ], + "q1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.265946508079, + 0.36216640147, + 5.218506244605, + 6.303033639668, + 19.864387584069, + 22.255832052491, + -19.996729898451, + -22.658175454795, + -8.362740900256, + -9.283867452474, + -0.748578113857, + -0.820161319958, + 0.007184391373, + 0.008315313301, + 0.009645948807, + 0.011214459742, + 0.013066644141, + 0.015257502049, + 0.017853126382, + 0.020932986715, + 0.024592688097, + 0.028947304186, + 0.034135404814, + 0.040303595656, + 0.046007930963, + 0.051201250609, + 0.050669293491, + 0.044533770263, + 0.038442084409, + 0.032390196455, + 0.027290027851, + 0.023048665178, + 0.019577574483, + 0.016788762624, + 0.014604222116, + 0.012963355912, + 0.265168493479, + 0.471104883481, + 3.782842057799, + 7.187478624224, + 17.289455034672, + 24.464945597604, + 7.389977719947, + -9.045292770421, + -13.833463314283, + -14.682108854427, + -7.744546200631, + -3.480140071322, + -1.738027716954, + -1.027311449525, + -0.799217806431, + -0.62921545293, + -0.473830846435, + -0.31723396261, + -0.156704241475, + 0.00274133768, + 0.156893909285, + 0.300108897143, + 0.425620432201, + 0.525745444962, + 0.59286254082, + 0.620705054337, + 0.605598531469, + 0.547329254174, + 0.449493146247, + 0.319245793314, + 0.16648993075, + 0.002657025718, + -0.160648303106, + -0.312850682458, + -0.445205286419, + -0.551034808588, + -0.625402984857, + -0.664413330568, + -0.664480047723, + -0.62199295278, + -0.533783908245, + -0.39853144946, + -0.218786293864, + -0.003027999825, + 0.232744283718, + 0.464523024794, + 0.662313439682, + 0.796248687774, + 0.846001996418, + 0.801558725477, + 0.680958278722, + 0.435416113512, + 0.122495361409, + -0.355242566507, + -0.916589997349, + -1.106510274466, + -1.045301026449, + -0.929484104377, + -0.793061437916, + -0.728631079553, + -0.675429464101, + -0.580536923571, + -0.427860864952, + -0.223729364525, + 0.002291755095, + 0.223804365901, + 0.426095718143, + 0.596748334329, + 0.715174753558, + 0.756706311195, + 0.701816021735, + 0.545071853753, + 0.296637077903, + -0.019771062744, + -0.368188165172, + -0.700693209525, + -0.959928113776, + -1.09023054709, + -1.058286377439, + -0.869677130244, + -0.566962702228, + -0.21423462252, + 0.127497372146, + 0.422473564897, + 0.651121616124, + 0.796656034247, + 0.852575978124, + 0.824320749034, + 0.71927974336, + 0.540477361983, + 0.289573649497, + -0.023367993756, + -0.371007882399, + -0.706676799267, + -0.970683676917, + -1.105279267094 + ], + "i2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + -0.00276307784, + -0.006600353658, + -0.097304738637, + 0.822193095704, + 1.084594523482, + 9.244013463761, + 16.344619793933, + 13.349297540955, + 16.87266705743, + 18.901868256629, + 14.165671187878, + 10.166201552308, + 6.722877002528, + 3.717111607639, + 2.681118736454, + 1.800908608929, + 1.440339354471, + 1.149527675182, + 0.941602471181, + 0.776373393581, + 0.645367275472, + 0.541798396953, + 0.460225946948, + 0.396279753225, + 0.34657950531, + 0.308443044476, + 0.280462771115, + 0.260939090362, + 0.249518802219, + 0.246021803663, + 0.246831844255, + 0.249043369255, + 0.251562942012, + 0.253571992243, + 0.255079305374, + 0.256121651612, + 0.242545832249, + 0.219663193189, + -0.077731111131, + -0.450333019061, + -2.53434459737, + -4.499931040575, + -6.111841652453, + -7.840327163707, + -0.55138598235, + 13.136430828742, + 19.118632764538, + 18.688185209657, + 13.769767963, + 7.533425758931, + 3.802567826481, + 1.759198410953, + 0.836466079802, + 0.414456134105, + 0.156360149591, + -0.025516221176, + -0.165096364154, + -0.264973693944, + -0.323722333112, + -0.339951891142, + -0.312768960156, + -0.242606343955, + -0.131653250994, + 0.015502250016, + 0.191477443778, + 0.386135296306, + 0.587151764682, + 0.78104360148, + 0.954484082398, + 1.095660712608, + 1.195408323546, + 1.247904942169, + 1.250841771835, + 1.205112807778, + 1.114169883353, + 0.983240945656, + 0.818627019843, + 0.627299477465, + 0.417024410156, + 0.197162679036, + -0.020001156297, + -0.218062582622, + -0.37655497942, + -0.473329272946, + -0.48940676951, + -0.414557328101, + -0.252512780184, + -0.016096477503, + 0.261201316077, + 0.567801292715, + 0.848848526941, + 1.063631381582, + 1.220811408401, + 1.201279091364, + 0.97000526003, + 0.648817969552, + 0.309393209696, + 0.002536802219, + -0.256449312191, + -0.494422026609, + -0.720591908098, + -0.931655830398, + -1.111740817063, + -1.240452420157, + -1.304606114611, + -1.299065189879, + -1.222481596386, + -1.075581164241, + -0.863944323807, + -0.601907509723, + -0.3146822714, + -0.037132229842, + 0.189582466846, + 0.323890131671, + 0.332646636507, + 0.201020725699, + -0.060075700017, + -0.411750377882, + -0.794326204785, + -1.143784644913, + -1.408903536031, + -1.563136840094, + -1.603168695499, + -1.537263785703, + -1.37984477244, + -1.151804402386, + -0.877452050223, + -0.580186674174, + -0.281757703951, + -0.006057833024, + 0.216162121415, + 0.348086463879 + ], + "q2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.053189301616, + 0.114984721587, + 1.13568902619, + 2.243977566492, + 5.860691387892, + 10.392375112081, + 5.763021112567, + 4.546731690082, + 6.94505487426, + -0.804834787982, + -5.931244379674, + -6.818062333551, + -7.586743714445, + -6.240953106543, + -5.1819113504, + -4.141601070454, + -3.308704094907, + -2.641619138093, + -2.107042021579, + -1.678301567371, + -1.334027346165, + -1.057082708479, + -0.833709798846, + -0.652849440511, + -0.506037854477, + -0.386504084019, + -0.289866511785, + -0.21276510885, + -0.151383097982, + -0.103778714174, + -0.068146173125, + -0.041853915459, + -0.022831451906, + -0.009262954461, + 0.00025879592, + 0.006822205422, + 0.061935815964, + 0.146769924417, + 0.876663229119, + 2.197629410232, + 5.32607862633, + 9.9767794628, + 10.824943629772, + 9.768494554368, + 9.184923918743, + 5.8402580955, + 1.37378870169, + -2.273794168749, + -4.679966302167, + -5.317254829749, + -5.049656141984, + -4.491924387647, + -3.883102947921, + -3.323177406701, + -2.812181814452, + -2.342582043846, + -1.905939497705, + -1.496236091694, + -1.11131074939, + -0.752109680383, + -0.422279285538, + -0.127496927364, + 0.12535916285, + 0.329241802076, + 0.478070497922, + 0.567799688779, + 0.597234116596, + 0.568457924706, + 0.486822598385, + 0.360528377018, + 0.199922543621, + 0.016709569696, + -0.176730673059, + -0.367810458823, + -0.54401864636, + -0.693152350145, + -0.803635851677, + -0.865010309936, + -0.868644288734, + -0.808772549048, + -0.684021111032, + -0.499343406147, + -0.267619696714, + -0.009528961598, + 0.249309776977, + 0.48177985573, + 0.666122154459, + 0.772723985381, + 0.787583542011, + 0.682641108989, + 0.442021073974, + 0.154587288603, + -0.15024410698, + -0.476677407383, + -0.752689269515, + -0.954623313176, + -1.084706229663, + -1.142119599095, + -1.144456934907, + -1.096234492588, + -0.995730967675, + -0.84162123323, + -0.635741837753, + -0.388752741905, + -0.120068479844, + 0.14610946478, + 0.384001576771, + 0.567956261399, + 0.674482507694, + 0.685056492311, + 0.590300654953, + 0.394607173775, + 0.119613515459, + -0.196325466297, + -0.505092176178, + -0.760009406142, + -0.924991650783, + -0.979120931461, + -0.918468806806, + -0.754989680657, + -0.513744995395, + -0.227252792635, + 0.072649424506, + 0.357385476268, + 0.599232889621, + 0.772060060509, + 0.855064424755, + 0.835594054665, + 0.710658242733, + 0.488655728521, + 0.191934727615, + -0.142335578377 + ], + "re": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.001226838866, + 0.027227297527, + 0.515473320621, + 3.220979881978, + 16.763285844964, + 55.606901199133, + 93.36394166853, + 126.054264123875, + 163.51047291715, + 185.314642808278, + 185.141846709789, + 172.128080202398, + 152.170103341126, + 130.197299336269, + 109.415811350985, + 90.792099473693, + 74.712888780756, + 61.099991150327, + 49.73345032692, + 40.334749495086, + 32.619766835182, + 26.321943446654, + 21.202887797405, + 17.055852032126, + 13.705178772739, + 11.003851294514, + 8.830052471672, + 7.083505627458, + 5.682223983771, + 4.559338814567, + 3.660335855314, + 2.940989817914, + 2.365592014947, + 1.905409326044, + 1.537394080544, + 1.242424020036, + 1.006412957436, + 0.827448992308, + 1.054276350073, + 3.412630296919, + 15.638401793064, + 39.610909686136, + 62.421175954264, + 68.746125918938, + 64.276717226332, + 103.256149268671, + 153.438686878957, + 176.345600318038, + 166.800099872478, + 144.53941408271, + 121.505960236427, + 100.987591115125, + 83.440256588534, + 68.634241969317, + 56.224148955934, + 45.873125620612, + 37.277596828193, + 30.171789693503, + 24.326607273177, + 19.546071166137, + 15.662800741974, + 12.533431994741, + 10.034592106807, + 8.059747510138, + 6.516874903995, + 5.326665796429, + 4.42095135622, + 3.741207454826, + 3.237226778098, + 2.866149359641, + 2.591938802621, + 2.385146749186, + 2.222599165286, + 2.086638561108, + 1.963827899482, + 1.843452256461, + 1.716497324953, + 1.575794951963, + 1.417587422679, + 1.243924741346, + 1.064324380128, + 0.894608840547, + 0.751843998927, + 0.64733017656, + 0.58246405947, + 0.551092299363, + 0.544632465937, + 0.556582027208, + 0.58245509126, + 0.622707882418, + 0.692404860094, + 0.808977387243, + 0.954812547955, + 1.068657439753, + 1.124504265307, + 1.146848558024, + 1.165408669127, + 1.1936181622, + 1.231172000957, + 1.274503829498, + 1.321477459098, + 1.371344696001, + 1.422317350738, + 1.470849633186, + 1.512124756282, + 1.538537715423, + 1.537425028062, + 1.492403783468, + 1.39033766624, + 1.231029916676, + 1.033748278853, + 0.835030769392, + 0.675608757704, + 0.581867690145, + 0.555642886743, + 0.582699488271, + 0.652242566395, + 0.76706528284, + 0.934046743718, + 1.147108275112, + 1.381498421333, + 1.60309118991, + 1.780564357356, + 1.891519991928, + 1.923607006448, + 1.873048450327, + 1.743153307551, + 1.545981419582, + 1.306579948157, + 1.063760064548, + 0.860592845239 + ], + "im": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + -6.671293e-06, + -0.000743858847, + 0.229825978285, + -0.29310206052, + 8.3464777444, + 29.994377236797, + 24.519038346849, + 16.416007887769, + 42.103650646652, + 53.825035496393, + 50.316869064272, + 46.51176950396, + 39.960693000906, + 32.474355705334, + 26.333879657721, + 21.065776261501, + 16.852897224808, + 13.469267381492, + 10.764302212896, + 8.601958255901, + 6.873453146696, + 5.491803665762, + 4.387458120335, + 3.50482016026, + 2.799430235765, + 2.235745649199, + 1.785403556982, + 1.425605420139, + 1.138214575641, + 0.908801571115, + 0.725713162209, + 0.579601955287, + 0.462989724096, + 0.369906096999, + 0.295590093563, + 0.233630393653, + 0.182505632051, + 0.105208658927, + 0.039373682591, + -0.602709284986, + -0.218645308883, + -2.627915532304, + -7.135853963236, + 7.616636335564, + 30.86877990305, + 43.417237827425, + 48.562880940056, + 50.080396538155, + 47.656554533348, + 41.689641129271, + 34.99121292234, + 28.607731568322, + 23.120255123006, + 18.625386795762, + 14.987917983004, + 12.057958267283, + 9.697966751924, + 7.79635278636, + 6.26394572717, + 5.029492965926, + 4.03610848318, + 3.238326449176, + 2.599718979879, + 2.090901425956, + 1.687896952841, + 1.370871845608, + 1.12323643883, + 0.931060024088, + 0.782702778859, + 0.668548492318, + 0.580740708162, + 0.512881388151, + 0.459723568198, + 0.416938955037, + 0.381028776991, + 0.349369908007, + 0.320296018871, + 0.293070753926, + 0.267659335165, + 0.244335432318, + 0.22330273876, + 0.204576671768, + 0.188278149121, + 0.175156350054, + 0.166611705602, + 0.164187414429, + 0.168230023861, + 0.177486787631, + 0.195766269545, + 0.222308768153, + 0.245632273199, + 0.26621107308, + 0.293258481013, + 0.322968842663, + 0.345901336446, + 0.358405653672, + 0.356846995627, + 0.344637405806, + 0.332653151745, + 0.325647797744, + 0.324760860434, + 0.328483105891, + 0.334069526776, + 0.338901614971, + 0.340439708721, + 0.336397156875, + 0.32537596832, + 0.307256393192, + 0.282980030846, + 0.254330277511, + 0.223915562441, + 0.19498287355, + 0.171178599535, + 0.156600352713, + 0.155536397544, + 0.170749236035, + 0.201008246106, + 0.240718903932, + 0.282739609219, + 0.321410486098, + 0.353703681998, + 0.378540056593, + 0.395085620961, + 0.401677004617, + 0.396366395331, + 0.378577373418, + 0.350281245058, + 0.315600872056, + 0.279156191069, + 0.244683266345, + 0.215262101317 + ], + "period": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.2, + 2.16, + 2.928, + 3.5424, + 4.03392, + 4.437312, + 4.8810432, + 5.36914752, + 5.906062272, + 6.4966684992, + 7.14633534912, + 7.860968884032, + 8.647065772435, + 9.511772349679, + 10.462949584647, + 11.509244543111, + 12.660168997422, + 13.926185897165, + 15.318804486881, + 16.850684935569, + 18.535753429126, + 20.389328772039, + 22.420865143879, + 24.095242323233, + 25.476618129199, + 26.618045090783, + 27.56351899243, + 28.349544172767, + 29.006986648311, + 29.562031941915, + 30.03663703359, + 30.449703206127, + 30.817846513525, + 31.156079027712, + 31.478396367066, + 31.798371706953, + 32.199411103862, + 32.764460904063, + 36.040906994469, + 38.832725595575, + 36.269765706267, + 33.875961169654, + 31.640147732457, + 29.551897982115, + 32.507087780326, + 30.361619986824, + 28.357753067694, + 26.785864773215, + 25.970126994933, + 25.291567064698, + 24.708305628353, + 24.248350633794, + 23.950932462782, + 23.809689555408, + 23.78996021077, + 23.855610191215, + 23.973366281925, + 24.116099770498, + 24.262425063562, + 24.396220394621, + 24.506577100633, + 24.58794637848, + 24.640338548832, + 24.669378128188, + 24.686214592691, + 24.707392412849, + 24.754670618122, + 24.854392534117, + 25.035539690232, + 25.325576536083, + 25.744146133521, + 26.296517555328, + 26.97017237623, + 27.737203259418, + 28.561631223661, + 29.406503019385, + 30.234494146892, + 30.99948424269, + 31.633523970072, + 32.040619329305, + 32.111549539908, + 31.76560464399, + 31.002214943173, + 29.923050769032, + 28.693838603417, + 27.465506006402, + 26.312258952038, + 25.244327651362, + 24.266292851397, + 23.288633597551, + 22.295638466394, + 21.522719826328, + 21.170987857283, + 21.153809478536, + 21.204728107937, + 21.174782740432, + 21.088551263753, + 21.100030923571, + 21.350632120175, + 21.842460185071, + 22.497355942741, + 23.212574221564, + 23.915087541506, + 24.57924182473, + 25.212445112594, + 25.844602135853, + 26.513453439144, + 27.236079510653, + 27.977878283153, + 28.640746557191, + 29.080649921746, + 29.155644510008, + 28.802597850094, + 28.106154167997, + 27.264747413744, + 26.415944789109, + 25.541214096225, + 24.636550108938, + 23.841756837688, + 23.348617610792, + 23.278814869996, + 23.63666636672, + 24.328586144324, + 25.218011302761, + 26.179891496017, + 27.12785799544, + 28.003380767292, + 28.739567266151, + 29.231913468545, + 29.355603927616, + 29.042737022185, + 28.361160590156 + ], + "phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 50.915666667084, + 73.257274690702, + 25.541621137121, + -21.633361152927, + -71.229994351207, + -46.068105882258, + -89.533807663001, + -84.019506270322, + -84.318918905099, + 4.827061625778, + 5.343138747402, + 5.913604715922, + 6.543734667605, + 7.239188176715, + 8.006003441588, + 8.850578851647, + 9.779637462137, + 10.800168823746, + 11.91934148329, + 13.144378422408, + 14.475393070541, + 15.397675741686, + 15.955126417434, + 14.763133282406, + 12.364856781309, + 10.272485051653, + 8.39338379846, + 6.895577093388, + 5.703849219553, + 4.761670413163, + 4.02437518665, + 3.457599100332, + 3.036290892459, + 47.056714664745, + 62.143551368977, + 86.202789027202, + 80.882163402694, + 83.81629015987, + 72.021383480078, + 28.595466443679, + -37.912418522694, + -59.368450871534, + -74.575511707228, + -77.120880495974, + -72.087514984201, + -64.971985533, + -60.388097516072, + -64.637960035336, + -71.764071918244, + -81.278102130781, + 85.288588397473, + 61.339975019109, + -1.504320555093, + -62.102577815513, + -85.450002689961, + 80.735651991664, + 70.005938943927, + 60.588897215439, + 51.771089647007, + 43.191361042323, + 34.65610986159, + 26.077824884016, + 17.443227273372, + 8.783195487476, + 0.138551314382, + -8.471959979073, + -17.071426198697, + -25.724513500276, + -34.515219199762, + -43.51051544994, + -52.730222688446, + -62.155438011082, + -71.814388342114, + -82.014232065691, + 85.964966012623, + 66.310106053334, + 1.427523484915, + -66.787022265357, + -86.376089521759, + 82.516782782637, + 73.113668507749, + 63.518371674041, + 52.801204302991, + 41.002584390634, + 25.083042874671, + 6.899353859894, + -18.955851959963, + -47.205622049174, + -65.354465161769, + -79.14419663641, + 85.175381382947, + 69.26096755387, + 55.815555784572, + 44.419417128624, + 33.662992093634, + 22.710961705552, + 11.31640936026, + -0.114427523311, + -11.365917047499, + -22.585711418524, + -33.886671691535, + -44.950824697116, + -55.26756641388, + -64.413140325159, + -72.057186288163, + -76.82010428743, + 31.425231784383, + 78.597541552737, + 74.440500328865, + 68.134049489626, + 60.200645643728, + 50.20995272442, + 37.886251571177, + 23.632346563112, + 8.755036856382, + -5.210747789684, + -17.716126246055, + -28.999053023132, + -39.281015212969, + -48.70649567834, + -57.411158031366, + -65.408428195069, + -72.417465293961, + -76.865163416943, + 36.357735705125, + 78.791089038246, + 74.612141870338, + 68.339580775405, + 60.470588844344 + ], + "delta_phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 47.715653553581, + 47.174982290049, + 49.59663319828, + 1.0, + 43.465701780744, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.191993135028, + 2.398276501096, + 2.092371729657, + 1.879101253193, + 1.497806705072, + 1.191727873835, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 5.320625624508, + 1.0, + 11.794906679792, + 43.425917036399, + 66.507884966373, + 21.45603234884, + 15.207060835694, + 2.545368788746, + 1.0, + 1.0, + 1.0, + 4.249862519264, + 7.126111882908, + 9.514030212537, + 1.0, + 23.948613378364, + 62.844295574202, + 60.59825726042, + 23.347424874447, + 1.0, + 10.729713047737, + 9.417041728488, + 8.817807568432, + 8.579728604684, + 8.535251180733, + 8.578284977574, + 8.634597610644, + 8.660031785896, + 8.644644173094, + 8.610511293455, + 8.599466219624, + 8.653087301579, + 8.790705699486, + 8.995296250178, + 9.219707238505, + 9.425215322637, + 9.658950331032, + 10.199843723577, + 1.0, + 19.654859959288, + 64.88258256842, + 68.214545750272, + 19.589067256402, + 1.0, + 9.403114274888, + 9.595296833708, + 10.71716737105, + 11.798619912357, + 15.919541515964, + 18.183689014776, + 25.855205819857, + 28.24977008921, + 18.148843112596, + 13.78973147464, + 1.0, + 15.914413829077, + 13.445411769298, + 11.396138655948, + 10.75642503499, + 10.952030388082, + 11.394552345291, + 11.430836883572, + 11.251489524188, + 11.219794371024, + 11.300960273011, + 11.064153005582, + 10.316741716764, + 9.145573911279, + 7.644045963004, + 4.762917999267, + 1.0, + 1.0, + 4.157041223872, + 6.306450839239, + 7.933403845898, + 9.990692919307, + 12.323701153243, + 14.253905008065, + 14.87730970673, + 13.965784646066, + 12.505378456371, + 11.282926777078, + 10.281962189836, + 9.425480465372, + 8.704662353026, + 7.997270163703, + 7.009037098891, + 4.447698122983, + 1.0, + 1.0, + 4.178947167908, + 6.272561094933, + 7.868991931061 + ], + "alpha": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.419465503036, + 0.208483050128, + 0.238963274505, + 0.266084650388, + 0.333821445923, + 0.419558869921, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.093973911206, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.196435189357, + 0.5, + 0.5, + 0.5, + 0.117650864642, + 0.070164489165, + 0.052553963865, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.053095230372, + 0.056703437461, + 0.058276901641, + 0.058580584146, + 0.058286708976, + 0.057906577995, + 0.057736508637, + 0.057839280598, + 0.058068560967, + 0.058143143682, + 0.057782844732, + 0.056878254954, + 0.055584606231, + 0.054231656935, + 0.053049185921, + 0.051765459275, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.053173872547, + 0.05210886215, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.054671254626, + 0.065410386387, + 0.104977662869, + 0.5, + 0.5, + 0.120277854626, + 0.079283897194, + 0.063024649912, + 0.050046578755, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.053047693625, + 0.057440481862, + 0.062521334126, + 0.071336475032, + 0.112417701511, + 0.5, + 0.5, + 0.119647360905, + 0.079712256674, + 0.063540540438 + ], + "mama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 99.549336158099, + 99.59966807905, + 99.649834039525, + 99.699917019762, + 99.749958509881, + 99.799979254941, + 99.841934507081, + 99.864464330658, + 99.896852378016, + 99.93760260947, + 99.991814341191, + 100.058182537438, + 100.129091268719, + 100.18954563436, + 100.24477281718, + 100.29738640859, + 104.348693204295, + 106.511992102147, + 107.725996051074, + 107.863035193821, + 108.631325096911, + 108.678736592065, + 108.730799762462, + 108.785237524339, + 108.839956398122, + 108.893171778216, + 109.090948270612, + 109.483119635306, + 109.661559817653, + 109.733134408826, + 109.73864818615, + 109.741250433663, + 109.744358189525, + 109.802401594763, + 109.810281515025, + 109.824789689273, + 109.84756945481, + 109.879977782069, + 110.309988891035, + 110.344724896483, + 110.394383543566, + 110.46021098692, + 110.539455277487, + 110.628779463163, + 110.725001233665, + 110.825443306623, + 110.927900014476, + 111.030371264307, + 111.1307859596, + 111.226924370879, + 111.316665498813, + 111.398492006853, + 111.471947508284, + 111.537717573446, + 111.597253742549, + 111.65204656274, + 111.703463484603, + 112.221954242302, + 112.252856530187, + 112.289235953677, + 112.332793405993, + 112.384940535694, + 113.002470267847, + 113.049382317747, + 113.107255341453, + 113.16044307438, + 113.210490620661, + 113.255616739628, + 113.293456102647, + 113.321403497514, + 113.336983972639, + 113.338204474007, + 113.323844750306, + 113.021922375153, + 112.990275756396, + 112.944692268576, + 112.887807005147, + 112.82279645489, + 112.753036432145, + 112.681733960538, + 112.611577562511, + 112.544448184385, + 112.481225775166, + 112.421714986408, + 112.364698937087, + 112.308114640233, + 112.243837064455, + 112.160672136444, + 112.012899370184, + 111.247146685092, + 110.709078342546, + 110.604547464002, + 110.517687398656, + 110.4345527553, + 110.359104246999, + 110.276528834649, + 110.190082192917, + 110.102927433271, + 110.017711361607, + 109.936275293527, + 109.859461528851, + 109.787038952408, + 109.713533683499, + 109.635384719856, + 109.548918920181, + 109.445016279944, + 109.268295284445, + 108.434844642223, + 107.862927321111, + 107.754894450052, + 107.665146065539, + 107.579586182054 + ], + "fama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 98.384914164262, + 98.688602642959, + 98.9289104921, + 99.121662124016, + 99.278736220482, + 99.409046979097, + 99.499837671439, + 99.537846910475, + 99.580741471519, + 99.628219107084, + 99.688907050474, + 99.766373453474, + 99.857052907285, + 99.940176089054, + 100.016325271085, + 100.086590555461, + 101.15211621767, + 102.492085188789, + 103.80056290436, + 103.991446109465, + 105.151415856326, + 105.23959887472, + 105.326878896913, + 105.413337862599, + 105.499003325987, + 105.583857537293, + 105.928315553438, + 106.817016573905, + 107.528152384842, + 108.079397890838, + 108.177004006788, + 108.231881282524, + 108.271624610882, + 108.654318856852, + 108.683217923307, + 108.711757217456, + 108.74015252339, + 108.768648154857, + 109.153983338901, + 109.183751877841, + 109.215891261435, + 109.251169864302, + 109.288708505457, + 109.327959575207, + 109.368674055494, + 109.410852316625, + 109.454646835379, + 109.500216219074, + 109.547558638269, + 109.596380439812, + 109.646081922042, + 109.695918935835, + 109.745278860263, + 109.793882320948, + 109.841716013863, + 109.888572310014, + 109.933944589379, + 110.50594700261, + 110.549619740799, + 110.593110146121, + 110.636602227618, + 110.68031068532, + 111.260850580951, + 111.308402160261, + 111.355270256485, + 111.400399576932, + 111.445651853025, + 111.49090097519, + 111.535964853377, + 111.58060081948, + 111.624510398309, + 111.667352750202, + 111.708765050204, + 112.037054381442, + 112.060884915815, + 112.082980099634, + 112.103100772272, + 112.121093164338, + 112.136891746033, + 112.150512801395, + 112.162039420423, + 112.171599639522, + 112.179340292913, + 112.185399660251, + 112.189882142172, + 112.192837954623, + 112.194232047283, + 112.193134463915, + 112.183674134462, + 111.949542272119, + 111.639426289726, + 111.577189787248, + 111.535189048021, + 111.500505439506, + 111.47194382717, + 111.442058452357, + 111.410759045871, + 111.378063255556, + 111.344054458208, + 111.308859979091, + 111.272625017835, + 111.235485366199, + 111.195117352911, + 111.150321455902, + 111.100260544399, + 111.041220898828, + 110.941566787568, + 110.314886251232, + 109.701896518702, + 109.585419689107, + 109.508885017124, + 109.447590671801 + ] + } }, { - "index": 95, - "value": 107.74003, - "phase": -70.253914512864, - "delta_phase": 62.506243546588, - "alpha": 0.05, - "mama": 107.235009349112, - "fama": 107.0832571867 - }, - { - "index": 96, - "value": 107.78003, - "phase": 88.689744454216, - "delta_phase": 1.0, - "alpha": 0.5, - "mama": 107.507519674556, - "fama": 107.189322808664 - }, - { - "index": 119, - "value": 107.74003, - "phase": 37.225902763516, - "delta_phase": 29.262512225095, - "alpha": 0.05, - "mama": 107.708336006236, - "fama": 107.603888156388 - }, - { - "index": 120, - "value": 107.86205, - "phase": -2.106311140505, - "delta_phase": 39.33221390402, - "alpha": 0.05, - "mama": 107.716021705925, - "fama": 107.606691495126 - }, - { - "index": 127, - "value": 106.32205, - "phase": -60.243344534554, - "delta_phase": 54.976868765635, - "alpha": 0.05, - "mama": 107.643066958931, - "fama": 107.663868636861 - }, - { - "index": 143, - "value": 103.326055, - "phase": 66.23371246664, - "delta_phase": 20.80705766932, - "alpha": 0.05, - "mama": 104.378584497396, - "fama": 106.227821220431 + "id": "flat-zero-energy", + "classification": "synthetic teaching input", + "lesson": "A flat series and epsilon-scale cycle exercise zero I/Q divisions and scale sensitivity.", + "observations": [ + { + "index": 0, + "timestamp": "2026-01-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 1, + "timestamp": "2026-01-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 2, + "timestamp": "2026-01-03T00:00:00Z", + "value": 100.0 + }, + { + "index": 3, + "timestamp": "2026-01-04T00:00:00Z", + "value": 100.0 + }, + { + "index": 4, + "timestamp": "2026-01-05T00:00:00Z", + "value": 100.0 + }, + { + "index": 5, + "timestamp": "2026-01-06T00:00:00Z", + "value": 100.0 + }, + { + "index": 6, + "timestamp": "2026-01-07T00:00:00Z", + "value": 100.0 + }, + { + "index": 7, + "timestamp": "2026-01-08T00:00:00Z", + "value": 100.0 + }, + { + "index": 8, + "timestamp": "2026-01-09T00:00:00Z", + "value": 100.0 + }, + { + "index": 9, + "timestamp": "2026-01-10T00:00:00Z", + "value": 100.0 + }, + { + "index": 10, + "timestamp": "2026-01-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 11, + "timestamp": "2026-01-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 12, + "timestamp": "2026-01-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 13, + "timestamp": "2026-01-14T00:00:00Z", + "value": 100.0 + }, + { + "index": 14, + "timestamp": "2026-01-15T00:00:00Z", + "value": 100.0 + }, + { + "index": 15, + "timestamp": "2026-01-16T00:00:00Z", + "value": 100.0 + }, + { + "index": 16, + "timestamp": "2026-01-17T00:00:00Z", + "value": 100.0 + }, + { + "index": 17, + "timestamp": "2026-01-18T00:00:00Z", + "value": 100.0 + }, + { + "index": 18, + "timestamp": "2026-01-19T00:00:00Z", + "value": 100.0 + }, + { + "index": 19, + "timestamp": "2026-01-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 20, + "timestamp": "2026-01-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 21, + "timestamp": "2026-01-22T00:00:00Z", + "value": 100.0 + }, + { + "index": 22, + "timestamp": "2026-01-23T00:00:00Z", + "value": 100.0 + }, + { + "index": 23, + "timestamp": "2026-01-24T00:00:00Z", + "value": 100.0 + }, + { + "index": 24, + "timestamp": "2026-01-25T00:00:00Z", + "value": 100.0 + }, + { + "index": 25, + "timestamp": "2026-01-26T00:00:00Z", + "value": 100.0 + }, + { + "index": 26, + "timestamp": "2026-01-27T00:00:00Z", + "value": 100.0 + }, + { + "index": 27, + "timestamp": "2026-01-28T00:00:00Z", + "value": 100.0 + }, + { + "index": 28, + "timestamp": "2026-01-29T00:00:00Z", + "value": 100.0 + }, + { + "index": 29, + "timestamp": "2026-01-30T00:00:00Z", + "value": 100.0 + }, + { + "index": 30, + "timestamp": "2026-01-31T00:00:00Z", + "value": 100.0 + }, + { + "index": 31, + "timestamp": "2026-02-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 32, + "timestamp": "2026-02-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 33, + "timestamp": "2026-02-03T00:00:00Z", + "value": 100.0 + }, + { + "index": 34, + "timestamp": "2026-02-04T00:00:00Z", + "value": 100.0 + }, + { + "index": 35, + "timestamp": "2026-02-05T00:00:00Z", + "value": 100.0 + }, + { + "index": 36, + "timestamp": "2026-02-06T00:00:00Z", + "value": 100.0 + }, + { + "index": 37, + "timestamp": "2026-02-07T00:00:00Z", + "value": 100.0 + }, + { + "index": 38, + "timestamp": "2026-02-08T00:00:00Z", + "value": 100.0 + }, + { + "index": 39, + "timestamp": "2026-02-09T00:00:00Z", + "value": 100.0 + }, + { + "index": 40, + "timestamp": "2026-02-10T00:00:00Z", + "value": 100.0 + }, + { + "index": 41, + "timestamp": "2026-02-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 42, + "timestamp": "2026-02-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 43, + "timestamp": "2026-02-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 44, + "timestamp": "2026-02-14T00:00:00Z", + "value": 100.0 + }, + { + "index": 45, + "timestamp": "2026-02-15T00:00:00Z", + "value": 100.0 + }, + { + "index": 46, + "timestamp": "2026-02-16T00:00:00Z", + "value": 100.0 + }, + { + "index": 47, + "timestamp": "2026-02-17T00:00:00Z", + "value": 100.0 + }, + { + "index": 48, + "timestamp": "2026-02-18T00:00:00Z", + "value": 100.0 + }, + { + "index": 49, + "timestamp": "2026-02-19T00:00:00Z", + "value": 100.0 + }, + { + "index": 50, + "timestamp": "2026-02-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 51, + "timestamp": "2026-02-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 52, + "timestamp": "2026-02-22T00:00:00Z", + "value": 100.0 + }, + { + "index": 53, + "timestamp": "2026-02-23T00:00:00Z", + "value": 100.0 + }, + { + "index": 54, + "timestamp": "2026-02-24T00:00:00Z", + "value": 100.0 + }, + { + "index": 55, + "timestamp": "2026-02-25T00:00:00Z", + "value": 100.0 + }, + { + "index": 56, + "timestamp": "2026-02-26T00:00:00Z", + "value": 100.0 + }, + { + "index": 57, + "timestamp": "2026-02-27T00:00:00Z", + "value": 100.0 + }, + { + "index": 58, + "timestamp": "2026-02-28T00:00:00Z", + "value": 100.0 + }, + { + "index": 59, + "timestamp": "2026-03-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 60, + "timestamp": "2026-03-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 61, + "timestamp": "2026-03-03T00:00:00Z", + "value": 100.0 + }, + { + "index": 62, + "timestamp": "2026-03-04T00:00:00Z", + "value": 100.0 + }, + { + "index": 63, + "timestamp": "2026-03-05T00:00:00Z", + "value": 100.0 + }, + { + "index": 64, + "timestamp": "2026-03-06T00:00:00Z", + "value": 100.0 + }, + { + "index": 65, + "timestamp": "2026-03-07T00:00:00Z", + "value": 100.0 + }, + { + "index": 66, + "timestamp": "2026-03-08T00:00:00Z", + "value": 100.0 + }, + { + "index": 67, + "timestamp": "2026-03-09T00:00:00Z", + "value": 100.0 + }, + { + "index": 68, + "timestamp": "2026-03-10T00:00:00Z", + "value": 100.0 + }, + { + "index": 69, + "timestamp": "2026-03-11T00:00:00Z", + "value": 100.0 + }, + { + "index": 70, + "timestamp": "2026-03-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 71, + "timestamp": "2026-03-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 72, + "timestamp": "2026-03-14T00:00:00Z", + "value": 100.0 + }, + { + "index": 73, + "timestamp": "2026-03-15T00:00:00Z", + "value": 100.0 + }, + { + "index": 74, + "timestamp": "2026-03-16T00:00:00Z", + "value": 100.000001 + }, + { + "index": 75, + "timestamp": "2026-03-17T00:00:00Z", + "value": 100.000001 + }, + { + "index": 76, + "timestamp": "2026-03-18T00:00:00Z", + "value": 100.000001 + }, + { + "index": 77, + "timestamp": "2026-03-19T00:00:00Z", + "value": 100.0 + }, + { + "index": 78, + "timestamp": "2026-03-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 79, + "timestamp": "2026-03-21T00:00:00Z", + "value": 100.0 + }, + { + "index": 80, + "timestamp": "2026-03-22T00:00:00Z", + "value": 99.999999 + }, + { + "index": 81, + "timestamp": "2026-03-23T00:00:00Z", + "value": 99.999999 + }, + { + "index": 82, + "timestamp": "2026-03-24T00:00:00Z", + "value": 99.999999 + }, + { + "index": 83, + "timestamp": "2026-03-25T00:00:00Z", + "value": 100.0 + }, + { + "index": 84, + "timestamp": "2026-03-26T00:00:00Z", + "value": 100.0 + }, + { + "index": 85, + "timestamp": "2026-03-27T00:00:00Z", + "value": 100.0 + }, + { + "index": 86, + "timestamp": "2026-03-28T00:00:00Z", + "value": 100.000001 + }, + { + "index": 87, + "timestamp": "2026-03-29T00:00:00Z", + "value": 100.000001 + }, + { + "index": 88, + "timestamp": "2026-03-30T00:00:00Z", + "value": 100.000001 + }, + { + "index": 89, + "timestamp": "2026-03-31T00:00:00Z", + "value": 100.0 + }, + { + "index": 90, + "timestamp": "2026-04-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 91, + "timestamp": "2026-04-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 92, + "timestamp": "2026-04-03T00:00:00Z", + "value": 99.999999 + }, + { + "index": 93, + "timestamp": "2026-04-04T00:00:00Z", + "value": 99.999999 + }, + { + "index": 94, + "timestamp": "2026-04-05T00:00:00Z", + "value": 99.999999 + }, + { + "index": 95, + "timestamp": "2026-04-06T00:00:00Z", + "value": 100.0 + }, + { + "index": 96, + "timestamp": "2026-04-07T00:00:00Z", + "value": 100.0 + }, + { + "index": 97, + "timestamp": "2026-04-08T00:00:00Z", + "value": 100.0 + }, + { + "index": 98, + "timestamp": "2026-04-09T00:00:00Z", + "value": 100.000001 + }, + { + "index": 99, + "timestamp": "2026-04-10T00:00:00Z", + "value": 100.000001 + }, + { + "index": 100, + "timestamp": "2026-04-11T00:00:00Z", + "value": 100.000001 + }, + { + "index": 101, + "timestamp": "2026-04-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 102, + "timestamp": "2026-04-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 103, + "timestamp": "2026-04-14T00:00:00Z", + "value": 100.0 + }, + { + "index": 104, + "timestamp": "2026-04-15T00:00:00Z", + "value": 99.999999 + }, + { + "index": 105, + "timestamp": "2026-04-16T00:00:00Z", + "value": 99.999999 + }, + { + "index": 106, + "timestamp": "2026-04-17T00:00:00Z", + "value": 99.999999 + }, + { + "index": 107, + "timestamp": "2026-04-18T00:00:00Z", + "value": 100.0 + }, + { + "index": 108, + "timestamp": "2026-04-19T00:00:00Z", + "value": 100.0 + }, + { + "index": 109, + "timestamp": "2026-04-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 110, + "timestamp": "2026-04-21T00:00:00Z", + "value": 100.000001 + }, + { + "index": 111, + "timestamp": "2026-04-22T00:00:00Z", + "value": 100.000001 + }, + { + "index": 112, + "timestamp": "2026-04-23T00:00:00Z", + "value": 100.000001 + }, + { + "index": 113, + "timestamp": "2026-04-24T00:00:00Z", + "value": 100.0 + }, + { + "index": 114, + "timestamp": "2026-04-25T00:00:00Z", + "value": 100.0 + }, + { + "index": 115, + "timestamp": "2026-04-26T00:00:00Z", + "value": 100.0 + }, + { + "index": 116, + "timestamp": "2026-04-27T00:00:00Z", + "value": 99.999999 + }, + { + "index": 117, + "timestamp": "2026-04-28T00:00:00Z", + "value": 99.999999 + }, + { + "index": 118, + "timestamp": "2026-04-29T00:00:00Z", + "value": 99.999999 + }, + { + "index": 119, + "timestamp": "2026-04-30T00:00:00Z", + "value": 100.0 + }, + { + "index": 120, + "timestamp": "2026-05-01T00:00:00Z", + "value": 100.0 + }, + { + "index": 121, + "timestamp": "2026-05-02T00:00:00Z", + "value": 100.0 + }, + { + "index": 122, + "timestamp": "2026-05-03T00:00:00Z", + "value": 100.000001 + }, + { + "index": 123, + "timestamp": "2026-05-04T00:00:00Z", + "value": 100.000001 + }, + { + "index": 124, + "timestamp": "2026-05-05T00:00:00Z", + "value": 100.000001 + }, + { + "index": 125, + "timestamp": "2026-05-06T00:00:00Z", + "value": 100.0 + }, + { + "index": 126, + "timestamp": "2026-05-07T00:00:00Z", + "value": 100.0 + }, + { + "index": 127, + "timestamp": "2026-05-08T00:00:00Z", + "value": 100.0 + }, + { + "index": 128, + "timestamp": "2026-05-09T00:00:00Z", + "value": 99.999999 + }, + { + "index": 129, + "timestamp": "2026-05-10T00:00:00Z", + "value": 99.999999 + }, + { + "index": 130, + "timestamp": "2026-05-11T00:00:00Z", + "value": 99.999999 + }, + { + "index": 131, + "timestamp": "2026-05-12T00:00:00Z", + "value": 100.0 + }, + { + "index": 132, + "timestamp": "2026-05-13T00:00:00Z", + "value": 100.0 + }, + { + "index": 133, + "timestamp": "2026-05-14T00:00:00Z", + "value": 100.0 + }, + { + "index": 134, + "timestamp": "2026-05-15T00:00:00Z", + "value": 100.000001 + }, + { + "index": 135, + "timestamp": "2026-05-16T00:00:00Z", + "value": 100.000001 + }, + { + "index": 136, + "timestamp": "2026-05-17T00:00:00Z", + "value": 100.000001 + }, + { + "index": 137, + "timestamp": "2026-05-18T00:00:00Z", + "value": 100.0 + }, + { + "index": 138, + "timestamp": "2026-05-19T00:00:00Z", + "value": 100.0 + }, + { + "index": 139, + "timestamp": "2026-05-20T00:00:00Z", + "value": 100.0 + }, + { + "index": 140, + "timestamp": "2026-05-21T00:00:00Z", + "value": 99.999999 + }, + { + "index": 141, + "timestamp": "2026-05-22T00:00:00Z", + "value": 99.999999 + }, + { + "index": 142, + "timestamp": "2026-05-23T00:00:00Z", + "value": 99.999999 + }, + { + "index": 143, + "timestamp": "2026-05-24T00:00:00Z", + "value": 100.0 + } + ], + "expected": { + "smooth": [ + null, + null, + null, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994, + 99.9999997, + 99.9999999, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994, + 99.9999997, + 99.9999999, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994, + 99.9999997, + 99.9999999, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994, + 99.9999997, + 99.9999999, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994, + 99.9999997, + 99.9999999, + 100.0000004, + 100.0000007, + 100.0000009, + 100.0000006, + 100.0000003, + 100.0000001, + 99.9999996, + 99.9999993, + 99.9999991, + 99.9999994 + ], + "detrender": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 5.1948, + 6.0606, + 47.25162, + 51.128676, + 7.7506416, + 8.10527328, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.10501e-07, + 1.93379e-07, + 9.11309e-07, + 1.32545e-06, + 9.11237e-07, + -1.38046e-07, + -1.215053e-06, + -1.215144e-06, + -1.657004e-06, + -1.656922e-06, + -9.94138e-07, + 1.10422e-07, + 1.215071e-06, + 1.215158e-06, + 1.65702e-06, + 1.656935e-06, + 9.94144e-07, + -1.10422e-07, + -1.215076e-06, + -1.215162e-06, + -1.657024e-06, + -1.656938e-06, + -9.94146e-07, + 1.10422e-07, + 1.215077e-06, + 1.215163e-06, + 1.657025e-06, + 1.656939e-06, + 9.94146e-07, + -1.10422e-07, + -1.215077e-06, + -1.215163e-06, + -1.657024e-06, + -1.656937e-06, + -9.94145e-07, + 1.10422e-07, + 1.215075e-06, + 1.21516e-06, + 1.65702e-06, + 1.656931e-06, + 9.94141e-07, + -1.10422e-07, + -1.215067e-06, + -1.21515e-06, + -1.657001e-06, + -1.656908e-06, + -9.94123e-07, + 1.1042e-07, + 1.215038e-06, + 1.215112e-06, + 1.656933e-06, + 1.656819e-06, + 9.94058e-07, + -1.10411e-07, + -1.214927e-06, + -1.214964e-06, + -1.656669e-06, + -1.656478e-06, + -9.93809e-07, + 1.1038e-07, + 1.214503e-06, + 1.214403e-06, + 1.655669e-06, + 1.655185e-06, + 9.92863e-07, + -1.1026e-07, + -1.212895e-06, + -1.212282e-06, + -1.651897e-06, + -1.65032e-06 + ], + "i1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 5.1948, + 6.0606, + 47.25162, + 51.128676, + 7.7506416, + 8.10527328, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 1.10501e-07, + 1.93379e-07, + 9.11309e-07, + 1.32545e-06, + 9.11237e-07, + -1.38046e-07, + -1.215053e-06, + -1.215144e-06, + -1.657004e-06, + -1.656922e-06, + -9.94138e-07, + 1.10422e-07, + 1.215071e-06, + 1.215158e-06, + 1.65702e-06, + 1.656935e-06, + 9.94144e-07, + -1.10422e-07, + -1.215076e-06, + -1.215162e-06, + -1.657024e-06, + -1.656938e-06, + -9.94146e-07, + 1.10422e-07, + 1.215077e-06, + 1.215163e-06, + 1.657025e-06, + 1.656939e-06, + 9.94146e-07, + -1.10422e-07, + -1.215077e-06, + -1.215163e-06, + -1.657024e-06, + -1.656937e-06, + -9.94145e-07, + 1.10422e-07, + 1.215075e-06, + 1.21516e-06, + 1.65702e-06, + 1.656931e-06, + 9.94141e-07, + -1.10422e-07, + -1.215067e-06, + -1.21515e-06, + -1.657001e-06, + -1.656908e-06, + -9.94123e-07, + 1.1042e-07, + 1.215038e-06, + 1.215112e-06, + 1.656933e-06, + 1.656819e-06, + 9.94058e-07, + -1.10411e-07, + -1.214927e-06, + -1.214964e-06, + -1.656669e-06, + -1.656478e-06, + -9.93809e-07, + 1.1038e-07, + 1.214503e-06, + 1.214403e-06, + 1.655669e-06, + 1.655185e-06, + 9.92863e-07, + -1.1026e-07, + -1.212895e-06 + ], + "q1": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.2698594704, + 0.3673087236, + 5.294825146728, + 6.391987490604, + 20.148599469838, + 22.562907329356, + -20.325601884286, + -23.01731460752, + -8.500154031483, + -9.430969187727, + -0.765929743819, + -0.838967188241, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 3.0526e-08, + 5.3422e-08, + 4.34822e-07, + 6.86542e-07, + 1.578453e-06, + 1.837395e-06, + -3.66324e-07, + -2.813762e-06, + -4.232265e-06, + -2.608417e-06, + -1.2586e-06, + -6.63274e-07, + 1.769579e-06, + 3.599485e-06, + 4.575699e-06, + 2.745808e-06, + 1.281509e-06, + 6.70907e-07, + -1.769608e-06, + -3.599523e-06, + -4.575735e-06, + -2.745824e-06, + -1.281513e-06, + -6.70907e-07, + 1.769616e-06, + 3.599533e-06, + 4.575744e-06, + 2.745827e-06, + 1.281513e-06, + 6.70906e-07, + -1.769617e-06, + -3.599533e-06, + -4.575741e-06, + -2.745824e-06, + -1.28151e-06, + -6.70904e-07, + 1.769614e-06, + 3.599523e-06, + 4.575722e-06, + 2.745808e-06, + 1.281498e-06, + 6.70895e-07, + -1.7696e-06, + -3.599478e-06, + -4.575646e-06, + -2.745745e-06, + -1.281453e-06, + -6.7086e-07, + 1.769546e-06, + 3.599308e-06, + 4.575355e-06, + 2.745506e-06, + 1.28128e-06, + 6.70729e-07, + -1.769339e-06, + -3.598658e-06, + -4.574243e-06, + -2.744592e-06, + -1.280621e-06, + -6.70228e-07, + 1.76855e-06, + 3.596185e-06, + 4.570019e-06, + 2.741122e-06, + 1.278118e-06, + 6.6833e-07, + -1.76556e-06, + -3.586829e-06, + -4.554075e-06, + -2.72807e-06 + ], + "i2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + -0.002803731954, + -0.006695208063, + -0.098728359156, + 0.834368398358, + 1.100167986968, + 9.37902587923, + 16.578981340151, + 13.530414809862, + 17.097852139307, + 19.146930059914, + 14.329304113325, + 10.2612127108, + 6.759232127758, + 3.702798064668, + 2.646491316944, + 1.748586882145, + 1.378191363508, + 1.078509781312, + 0.86280782505, + 0.69024626004, + 0.552197008032, + 0.441757606425, + 0.35340608514, + 0.282724868112, + 0.22617989449, + 0.180943915592, + 0.144755132473, + 0.115804105979, + 0.092643284783, + 0.074114627826, + 0.059291702261, + 0.047433361809, + 0.037946689447, + 0.030357351558, + 0.024285881246, + 0.019428704997, + 0.015542963998, + 0.012434371198, + 0.009947496958, + 0.007957997567, + 0.006366398053, + 0.005093118443, + 0.004074494754, + 0.003259595803, + 0.002607676643, + 0.002086141314, + 0.001668913051, + 0.001335130441, + 0.001068104353, + 0.000854483482, + 0.000683586786, + 0.000546869429, + 0.000437495543, + 0.000349996434, + 0.000279997147, + 0.000223997718, + 0.000179198174, + 0.00014335854, + 0.000114686832, + 9.1749465e-05, + 7.3399572e-05, + 5.8719658e-05, + 4.697404e-05, + 3.757628e-05, + 3.0026885e-05, + 2.3987974e-05, + 1.9007881e-05, + 1.5077264e-05, + 1.196989e-05, + 9.535248e-06, + 8.502862e-06, + 8.282499e-06, + 7.82071e-06, + 5.995298e-06, + 3.361508e-06, + 1.491494e-06, + -2.74791e-07, + -1.685138e-06, + -2.175246e-06, + -1.199643e-06, + 6.58767e-07, + 1.811143e-06, + 2.943483e-06, + 3.830228e-06, + 3.892587e-06, + 2.573929e-06, + 4.40647e-07, + -9.31621e-07, + -2.239872e-06, + -3.267344e-06, + -3.44228e-06, + -2.213682e-06, + -1.52446e-07, + 1.162183e-06, + 2.424322e-06, + 3.414902e-06, + 3.560324e-06, + 2.308116e-06, + 2.27996e-07, + -1.10174e-06, + -2.37596e-06, + -3.376202e-06, + -3.529353e-06, + -2.283339e-06, + -2.08187e-07, + 1.117572e-06, + 2.388595e-06, + 3.386265e-06, + 3.537364e-06, + 2.289747e-06, + 2.13362e-07, + -1.113372e-06, + -2.38512e-06, + -3.383313e-06, + -3.534849e-06, + -2.287732e-06, + -2.1194e-07, + 1.114284e-06, + 2.385407e-06, + 3.382889e-06, + 3.533926e-06, + 2.286984e-06, + 2.12063e-07, + -1.113326e-06, + -2.382957e-06, + -3.378447e-06, + -3.528153e-06, + -2.282331e-06, + -2.1108e-07, + 1.110858e-06, + 2.374631e-06, + 3.362444e-06 + ], + "q2": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.05397189408, + 0.116639259984, + 1.152276437333, + 2.276139112326, + 5.94457826079, + 10.539219333314, + 5.835164108914, + 4.596543935605, + 7.026136695324, + -0.843465490978, + -6.047052797247, + -6.945838714885, + -7.724210398087, + -6.356604688439, + -5.280743125115, + -4.224594500092, + -3.379675600074, + -2.703740480059, + -2.162992384047, + -1.730393907238, + -1.38431512579, + -1.107452100632, + -0.885961680506, + -0.708769344405, + -0.567015475524, + -0.453612380419, + -0.362889904335, + -0.290311923468, + -0.232249538774, + -0.18579963102, + -0.148639704816, + -0.118911763853, + -0.095129411082, + -0.076103528866, + -0.060882823092, + -0.048706258474, + -0.038965006779, + -0.031172005423, + -0.024937604339, + -0.019950083471, + -0.015960066777, + -0.012768053421, + -0.010214442737, + -0.00817155419, + -0.006537243352, + -0.005229794681, + -0.004183835745, + -0.003347068596, + -0.002677654877, + -0.002142123902, + -0.001713699121, + -0.001370959297, + -0.001096767438, + -0.00087741395, + -0.00070193116, + -0.000561544928, + -0.000449235942, + -0.000359388754, + -0.000287511003, + -0.000230008803, + -0.000184007042, + -0.000147205634, + -0.000117758402, + -9.4196037e-05, + -7.5269865e-05, + -6.0072478e-05, + -4.7731607e-05, + -3.7730841e-05, + -3.0120626e-05, + -2.4343558e-05, + -1.9953816e-05, + -1.6558002e-05, + -1.4060878e-05, + -1.2227816e-05, + -9.950023e-06, + -7.491842e-06, + -5.210989e-06, + -3.265713e-06, + -1.63637e-06, + -2.59773e-07, + -1.2578e-08, + -4.73665e-07, + -1.159897e-06, + -1.831004e-06, + -2.441011e-06, + -3.002138e-06, + -2.596952e-06, + -1.613957e-06, + -5.10198e-07, + 4.9493e-07, + 1.372153e-06, + 2.147052e-06, + 1.912884e-06, + 1.066703e-06, + 7.2395e-08, + -8.45172e-07, + -1.652346e-06, + -2.371205e-06, + -2.092205e-06, + -1.210161e-06, + -1.87165e-07, + 7.53351e-07, + 1.578883e-06, + 2.312427e-06, + 2.045181e-06, + 1.172548e-06, + 1.57087e-07, + -7.77396e-07, + -1.598094e-06, + -2.327766e-06, + -2.057445e-06, + -1.18238e-06, + -1.65001e-07, + 7.70995e-07, + 1.592881e-06, + 2.323479e-06, + 2.053989e-06, + 1.179696e-06, + 1.63039e-07, + -7.72301e-07, + -1.59357e-06, + -2.323592e-06, + -2.053975e-06, + -1.179994e-06, + -1.63979e-07, + 7.70544e-07, + 1.590817e-06, + 2.319723e-06, + 2.050486e-06, + 1.178371e-06, + 1.65331e-07, + -7.65684e-07 + ], + "re": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.001262802671, + 0.028022577707, + 0.530491191031, + 3.314119450201, + 17.245239191319, + 57.194745239111, + 95.984212762345, + 129.514765773901, + 167.900827668851, + 190.213194939414, + 189.97813413846, + 176.584314960678, + 156.093016702999, + 133.547817249217, + 112.225577472029, + 93.117991235919, + 76.619224707825, + 62.651123115363, + 50.988574235717, + 41.346171864366, + 33.432337476, + 26.973325970885, + 21.724232610362, + 17.472552061828, + 14.037667872527, + 11.268295080783, + 9.039058965594, + 7.246877829094, + 5.807505883512, + 4.65240702376, + 3.726023101857, + 2.983440870509, + 2.388431025382, + 1.911818950849, + 1.530142604228, + 1.224554047253, + 0.97992481468, + 0.784120060945, + 0.627411382645, + 0.502002919805, + 0.401649576605, + 0.321349895371, + 0.257099266112, + 0.205691796772, + 0.164561363102, + 0.13165416292, + 0.105326576696, + 0.084263339028, + 0.067412000931, + 0.053930451759, + 0.043144906056, + 0.03451627342, + 0.027613241824, + 0.022090736236, + 0.017672680366, + 0.014138202774, + 0.011310599647, + 0.009048503671, + 0.007238818268, + 0.005791064426, + 0.00463285782, + 0.003706290275, + 0.002965034791, + 0.002372029477, + 0.00189762463, + 0.001518100368, + 0.001214480712, + 0.000971584833, + 0.000777268036, + 0.000621814542, + 0.000497451714, + 0.000397961431, + 0.000318369188, + 0.000254695379, + 0.000203756319, + 0.000163005063, + 0.000130404054, + 0.000104323245, + 8.3458597e-05, + 6.6766877e-05, + 5.3413502e-05, + 4.2730803e-05, + 3.4184645e-05, + 2.734772e-05, + 2.1878179e-05, + 1.7502545e-05, + 1.4002037e-05, + 1.120163e-05, + 8.961306e-06, + 7.169047e-06, + 5.73524e-06, + 4.588193e-06, + 3.670554e-06, + 2.936444e-06, + 2.349157e-06, + 1.879328e-06, + 1.503465e-06, + 1.202773e-06, + 9.62219e-07, + 7.69776e-07, + 6.15822e-07, + 4.9266e-07, + 3.94131e-07, + 3.15306e-07, + 2.52245e-07, + 2.01796e-07, + 1.61439e-07, + 1.29154e-07, + 1.03325e-07, + 8.2661e-08, + 6.6129e-08, + 5.2904e-08, + 4.2325e-08, + 3.3863e-08, + 2.7092e-08, + 2.1675e-08, + 1.734e-08, + 1.3873e-08, + 1.11e-08, + 8.883e-09, + 7.108e-09, + 5.688e-09, + 4.551e-09, + 3.641e-09, + 2.914e-09, + 2.334e-09, + 1.87e-09, + 1.497e-09, + 1.198e-09, + 9.59e-10, + 7.69e-10 + ], + "im": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + -6.865568e-06, + -0.000765666906, + 0.236615971526, + -0.3018737942, + 8.590389290824, + 30.8725845286, + 25.247302570811, + 16.902738969503, + 43.312270404827, + 55.389061013496, + 51.807036859136, + 47.907875431684, + 41.199215409433, + 33.505537589643, + 27.193732972825, + 21.772457731428, + 17.434217902431, + 13.947374321945, + 11.157899457556, + 8.926319566045, + 7.141055652836, + 5.712844522269, + 4.570275617815, + 3.656220494252, + 2.924976395402, + 2.339981116321, + 1.871984893057, + 1.497587914446, + 1.198070331556, + 0.958456265245, + 0.766765012196, + 0.613412009757, + 0.490729607806, + 0.392583686244, + 0.314066948996, + 0.251253559196, + 0.201002847357, + 0.160802277886, + 0.128641822309, + 0.102913457847, + 0.082330766277, + 0.065864613022, + 0.052691690418, + 0.042153352334, + 0.033722681867, + 0.026978145494, + 0.021582516395, + 0.017266013116, + 0.013812810493, + 0.011050248394, + 0.008840198715, + 0.007072158972, + 0.005657727178, + 0.004526181742, + 0.003620945394, + 0.002896756315, + 0.002317405052, + 0.001853924042, + 0.001483139233, + 0.001186511387, + 0.000949209109, + 0.000759367287, + 0.00060749383, + 0.000485995064, + 0.000388796051, + 0.000311036841, + 0.000248829473, + 0.000199063579, + 0.000159250864, + 0.000127400688, + 0.000101920545, + 8.1536434e-05, + 6.5229149e-05, + 5.2183323e-05, + 4.174666e-05, + 3.339733e-05, + 2.6717866e-05, + 2.1374294e-05, + 1.7099435e-05, + 1.3679548e-05, + 1.0943638e-05, + 8.754911e-06, + 7.003929e-06, + 5.603144e-06, + 4.482516e-06, + 3.586014e-06, + 2.868812e-06, + 2.29505e-06, + 1.836041e-06, + 1.468833e-06, + 1.175067e-06, + 9.40055e-07, + 7.52044e-07, + 6.01636e-07, + 4.81309e-07, + 3.85048e-07, + 3.08039e-07, + 2.46432e-07, + 1.97146e-07, + 1.57718e-07, + 1.26175e-07, + 1.0094e-07, + 8.0753e-08, + 6.4603e-08, + 5.1683e-08, + 4.1347e-08, + 3.3078e-08, + 2.6463e-08, + 2.1171e-08, + 1.6938e-08, + 1.3551e-08, + 1.0841e-08, + 8.673e-09, + 6.939e-09, + 5.552e-09, + 4.443e-09, + 3.555e-09, + 2.844e-09, + 2.276e-09, + 1.821e-09, + 1.458e-09, + 1.167e-09, + 9.34e-10, + 7.48e-10, + 5.99e-10, + 4.8e-10, + 3.85e-10, + 3.08e-10, + 2.47e-10, + 1.98e-10, + 1.59e-10 + ], + "period": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.2, + 2.16, + 2.928, + 3.5424, + 4.03392, + 4.437312, + 4.8810432, + 5.36914752, + 5.906062272, + 6.4966684992, + 7.14633534912, + 7.860968884032, + 8.647065772435, + 9.511772349679, + 10.462949584647, + 11.509244543111, + 12.660168997422, + 13.926185897165, + 15.318804486881, + 16.850684935569, + 18.535753429126, + 20.389328772039, + 22.332383552773, + 23.926279535835, + 25.232963372654, + 26.303567436794, + 27.180258404171, + 27.897778694567, + 28.484729793248, + 28.964639107882, + 29.356845653661, + 29.677234385788, + 29.938844308399, + 30.152371485708, + 30.326584676217, + 30.468668424157, + 30.58450600233, + 30.678912543682, + 30.75582696938, + 30.818469870148, + 30.869473282844, + 30.910987289168, + 30.944767516764, + 30.972246917893, + 30.994594614695, + 31.012764113275, + 31.027532785318, + 31.039534181667, + 31.049284465829, + 31.057204026894, + 31.06363514278, + 31.068856409144, + 31.073094521179, + 31.076533889973, + 31.079324488349, + 31.081588249727, + 31.083424284974, + 31.08491313409, + 31.086120230118, + 31.08709872033, + 31.087891763211, + 31.088534398086, + 31.089055066292, + 31.089476848438, + 31.089818466814, + 31.090095109698, + 31.090319060797, + 31.09050031368, + 31.090646940974, + 31.090765530246, + 31.090861663575, + 31.090939835852, + 31.091003472025, + 31.091055002463, + 31.091096470468, + 31.091129817533, + 31.091156425758, + 31.091177517485, + 31.091194249316, + 31.091207579849, + 31.091218246484, + 31.091226774973, + 31.091233666638, + 31.091239490643, + 31.091244527388, + 31.091248057684, + 31.09124969017, + 31.091250002431, + 31.09124891118, + 31.09124716303, + 31.091245487623, + 31.091241893734, + 31.091235161332, + 31.091226550956, + 31.091215823497, + 31.091205701606, + 31.091198055528, + 31.091183524226, + 31.091156362161, + 31.091121658969, + 31.091077889343, + 31.091035132569, + 31.091001086904, + 31.090941527798, + 31.090835403547, + 31.090701663973, + 31.090534957073, + 31.09037391597, + 31.09024724339, + 31.090022847744, + 31.089619525407, + 31.089109970938, + 31.088473289948, + 31.087856594582, + 31.087369969423, + 31.086511443916, + 31.084972582632, + 31.083030157299, + 31.080605356906, + 31.078258971125, + 31.076409691455, + 31.073146610409, + 31.067298349369, + 31.059919556819, + 31.050714870632, + 31.041814487308, + 31.034807429216, + 31.022484779825, + 31.000466261676, + 30.972751253675, + 30.938294368142, + 30.905094525672 + ], + "phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.0, + 0.0, + 0.0, + 50.89906785073, + 73.258970517552, + 25.524730881682, + -21.679710942509, + -71.39002930802, + -46.362249624069, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 80.856511525525, + 83.015406097696, + 63.619566547512, + -15.44957298479, + -72.055445171761, + 88.131813363128, + 65.022950016128, + 46.006400520706, + 21.815495670087, + -46.883099644774, + -74.560433415634, + 88.617595123009, + 66.129722362798, + 46.522325260475, + 22.042412953611, + -46.8833509557, + -74.5604997125, + 88.617598892147, + 66.129757745141, + 46.522305428392, + 22.042357251141, + -46.883419534177, + -74.560516775328, + 88.617599817998, + 66.129762865271, + 46.522287735525, + 22.042327802713, + -46.88343052718, + -74.56051364105, + 88.617598917594, + 66.129740732172, + 46.522232659227, + 22.042268644174, + -46.883403616902, + -74.560485045332, + 88.617594935659, + 66.129650290719, + 46.522030018566, + 22.042055811901, + -46.883280976606, + -74.56036904812, + 88.617578913302, + 66.129298116711, + 46.521255186572, + 22.041249534226, + -46.882808561506, + -74.559927011345, + 88.617518254373, + 66.127958508143, + 46.518303679771, + 22.038174524762, + -46.881005011278, + -74.558239440823, + 88.617286446307, + 66.12284791483, + 46.50705331482, + 22.02646263149, + -46.874136074716, + -74.551816080605, + 88.616404786345, + 66.103417024022, + 46.464309804798, + 21.982022503299, + -46.848087664954, + -74.527491226656, + 88.61307103033, + 66.030153047004 + ], + "delta_phase": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 47.734239635871, + 47.20444182419, + 49.710318365512, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 19.395839550184, + 79.069139532303, + 56.605872186971, + 1.0, + 23.108863347, + 19.016549495421, + 24.190904850619, + 68.698595314861, + 27.677333770859, + 1.0, + 22.48787276021, + 19.607397102323, + 24.479912306865, + 68.92576390931, + 27.6771487568, + 1.0, + 22.487841147006, + 19.607452316749, + 24.479948177251, + 68.925776785318, + 27.677097241151, + 1.0, + 22.487836952726, + 19.607475129747, + 24.479959932811, + 68.925758329893, + 27.67708311387, + 1.0, + 22.487858185422, + 19.607508072946, + 24.479964015053, + 68.925672261075, + 27.677081428431, + 1.0, + 22.48794464494, + 19.607620272153, + 24.479974206665, + 68.925336788508, + 27.677088071514, + 1.0, + 22.488280796591, + 19.608042930139, + 24.480005652346, + 68.924058095731, + 27.67711844984, + 1.0, + 22.48955974623, + 19.609654828372, + 24.480129155009, + 68.91917953604, + 27.677234429545, + 1.0, + 22.494438531477, + 19.61579460001, + 24.480590683329, + 68.900598706206, + 27.677680005889, + 1.0, + 22.512987762323, + 19.639107219223, + 24.4822873015, + 68.830110168253, + 27.679403561702, + 1.0, + 22.582917983326 + ], + "alpha": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.5, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05, + 0.05, + 0.05, + 0.05, + 0.05, + 0.5, + 0.05 + ], + "mama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 99.999672937393, + 99.999836468697, + 99.999918234348, + 99.999959117174, + 99.999979558587, + 99.999989779294, + 99.999994889647, + 99.999997444823, + 99.999998722412, + 99.999999361206, + 99.999999680603, + 99.999999840301, + 99.999999920151, + 99.999999960075, + 99.999999980038, + 99.999999990019, + 99.999999995009, + 99.999999997505, + 99.999999998752, + 99.999999999376, + 99.999999999688, + 99.999999999844, + 99.999999999922, + 99.999999999961, + 99.999999999981, + 99.99999999999, + 99.999999999995, + 99.999999999998, + 99.999999999999, + 99.999999999999, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0, + 100.0000005, + 100.00000075, + 100.000000875, + 100.0000004375, + 100.00000021875, + 100.000000207813, + 100.000000147422, + 100.000000090051, + 99.999999545025, + 99.999999567774, + 99.999999589385, + 99.999999609916, + 99.99999967942, + 99.999999745449, + 100.000000372725, + 100.000000354088, + 100.000000336384, + 100.000000319565, + 100.000000253587, + 100.000000190907, + 99.999999595454, + 99.999999615681, + 99.999999634897, + 99.999999653152, + 99.999999720494, + 99.99999978447, + 100.000000392235, + 100.000000372623, + 100.000000353992, + 100.000000336292, + 100.000000269478, + 100.000000206004, + 99.999999603002, + 99.999999622852, + 99.999999641709, + 99.999999659624, + 99.999999726643, + 99.99999979031, + 100.000000395155, + 100.000000375397, + 100.000000356628, + 100.000000338796, + 100.000000271856, + 100.000000208264, + 99.999999604132, + 99.999999623925, + 99.999999642729, + 99.999999660592, + 99.999999727563, + 99.999999791185, + 100.000000395592, + 100.000000375813, + 100.000000357022, + 100.000000339171, + 100.000000272212, + 100.000000208602, + 99.999999604301, + 99.999999624086, + 99.999999642882, + 99.999999660737, + 99.999999727701, + 99.999999791316, + 100.000000395658, + 100.000000375875, + 100.000000357081, + 100.000000339227, + 100.000000272266, + 100.000000208652, + 99.999999604326, + 99.99999962411 + ], + "fama": [ + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + 99.214037481106, + 99.410487228004, + 99.55784497959, + 99.668373513986, + 99.751275025136, + 99.813453713676, + 99.860089007668, + 99.895066116957, + 99.921299268321, + 99.940974291542, + 99.955730638807, + 99.966797939181, + 99.975098434423, + 99.981323815836, + 99.985992856887, + 99.98949464017, + 99.99212097888, + 99.994090733536, + 99.99556804984, + 99.996676037224, + 99.99750702784, + 99.998130270841, + 99.998597703111, + 99.998948277324, + 99.999211207988, + 99.999408405989, + 99.99955630449, + 99.999667228367, + 99.999750421275, + 99.999812815956, + 99.999859611967, + 99.999894708975, + 99.999921031731, + 99.999940773799, + 99.999955580349, + 99.999966685262, + 99.999975013946, + 99.99998126046, + 99.999985945345, + 99.999989459009, + 99.999992094256, + 99.999994070692, + 99.999995678019, + 99.999996946014, + 99.999997928261, + 99.999998555571, + 99.999998971365, + 99.999999002277, + 99.999999030905, + 99.999999057384, + 99.999999179294, + 99.999999189006, + 99.999999199016, + 99.999999209288, + 99.999999221042, + 99.999999234152, + 99.999999518795, + 99.999999539677, + 99.999999559595, + 99.999999578594, + 99.999999595469, + 99.999999610355, + 99.99999960663, + 99.999999606856, + 99.999999607557, + 99.999999608697, + 99.999999611492, + 99.999999615816, + 99.999999809921, + 99.999999823988, + 99.999999837239, + 99.999999849715, + 99.999999860209, + 99.999999868854, + 99.999999802391, + 99.999999797902, + 99.999999793998, + 99.999999790638, + 99.999999789038, + 99.99999978907, + 99.999999940591, + 99.999999951462, + 99.999999961591, + 99.999999971021, + 99.999999978542, + 99.999999984285, + 99.999999889247, + 99.999999882613, + 99.999999876616, + 99.999999871216, + 99.999999867624, + 99.999999865713, + 99.999999998183, + 100.000000007624, + 100.000000016359, + 100.000000024429, + 100.000000030624, + 100.000000035073, + 99.99999992738, + 99.999999919798, + 99.999999912875, + 99.999999906571, + 99.9999999021, + 99.99999989933, + 100.000000023412, + 100.000000032224, + 100.000000040345, + 100.000000047817, + 100.000000053428, + 100.000000057309, + 99.999999944063, + 99.999999936064 + ] + } } - ], - "independent_reference": { - "library": "TA-Lib Python 0.7.1 / core MAMA", - "result": "MAMA maximum absolute difference 0; FAMA maximum absolute difference 2.842170943040401e-14 before fixture rounding.", - "note": "The reference library was used only as an oracle; expected arrays are stored for repeatable cross-language checks." - } + ] } diff --git a/test/fixtures/D07-F02-A01.json b/test/fixtures/D07-F02-A01.json index 402917f..ccf4d8c 100644 --- a/test/fixtures/D07-F02-A01.json +++ b/test/fixtures/D07-F02-A01.json @@ -1,4 +1,13 @@ { + "topicId": "D07-F02-A01", + "input": {"values": [10, 11, 12, 13, 14, 15, 16, 15, 14, 13, 12, 13, 15, 18], "fastSpan": 3, "slowSpan": 5, "signalSpan": 3}, + "expected": { + "4": {"fastEma": 13, "slowEma": 12, "macd": 1, "signal": null, "histogram": null, "status": "warming_signal"}, + "6": {"fastEma": 15, "slowEma": 14, "macd": 1, "signal": 1, "histogram": 0, "status": "ready"}, + "7": {"fastEma": 15, "slowEma": 14.333333333333334, "macd": 0.6666666666666661, "signal": 0.833333333333333, "histogram": -0.16666666666666696, "status": "ready"}, + "9": {"macd": -0.06481481481481488, "signal": 0.24537037037037002, "histogram": -0.3101851851851849, "status": "ready"}, + "12": {"macd": 0.2088048696844993, "signal": 0.04260973936899856, "histogram": 0.16619513031550073, "status": "ready"} + }, "title": "A 3/5/3 MACD through rise, reversal, and recovery", "spans": {"fast": 3, "slow": 5, "signal": 3}, "alphas": {"fast": "1/2", "slow": "1/3", "signal": "1/2"}, diff --git a/test/fixtures/D08-F01-A01.json b/test/fixtures/D08-F01-A01.json index 2e22dec..60a4cab 100644 --- a/test/fixtures/D08-F01-A01.json +++ b/test/fixtures/D08-F01-A01.json @@ -1,5 +1,27 @@ { - "topic_id": "D08-F01-A01", + "topicId": "D08-F01-A01", + "input": { + "bars": [ + {"timestamp": "2026-01-01T00:00:00Z", "high": 10, "low": 8, "close": 9}, + {"timestamp": "2026-01-01T01:00:00Z", "high": 12, "low": 10, "close": 11}, + {"timestamp": "2026-01-01T02:00:00Z", "high": 15, "low": 13, "close": 14}, + {"timestamp": "2026-01-01T03:00:00Z", "high": 13, "low": 11, "close": 12}, + {"timestamp": "2026-01-01T04:00:00Z", "high": 11, "low": 9, "close": 10} + ], + "leftSpan": 2, + "rightSpan": 2, + "minSeparation": 0 + }, + "expected": { + "0": { + "kind": "high", + "event_index": 2, + "confirmation_index": 4, + "price": 15, + "separation": 2, + "latency": 2 + } + }, "classification": "author-derived calculation over synthetic teaching input", "selected_variant": "Asymmetric left/right OHLC extrema with earliest-plateau equality and a price-unit separation floor.", "formulae": [ diff --git a/test/fixtures/D08-F01-A02.json b/test/fixtures/D08-F01-A02.json index 7f4b669..c612376 100644 --- a/test/fixtures/D08-F01-A02.json +++ b/test/fixtures/D08-F01-A02.json @@ -1,5 +1,16 @@ { - "topic_id": "D08-F01-A02", + "topicId": "D08-F01-A02", + "input": { + "closes": [100, 103, 106, 101, 100], + "threshold": 0.05, + "minBars": 2 + }, + "expected": { + "pivots": [ + {"kind": "low", "event_index": 0, "confirmation_index": 2, "price": 100}, + {"kind": "high", "event_index": 2, "confirmation_index": 4, "price": 106} + ] + }, "classification": "author-derived calculation over synthetic teaching input", "selected_variant": "Close-only percentage reversal, minimum bar separation, strict extreme updates, and a separate provisional endpoint.", "formulae": [ @@ -39,24 +50,24 @@ "index_or_object": "0", "value": "100", "calculation_state": "searching", - "published_interpretation": "running high and low both 100" + "published_interpretation": "running high and low both 100; no confirmation yet" }, { "index_or_object": "1", "value": "103", "calculation_state": "searching", - "published_interpretation": "running high becomes 103" + "published_interpretation": "running high becomes 103; the rise is below 5%" }, { "index_or_object": "2", "value": "106", - "calculation_state": "searching", - "published_interpretation": "running high becomes 106" + "calculation_state": "up", + "published_interpretation": "rise reaches 6%; confirm the low at index 0 and start an up leg" }, { "index_or_object": "3", "value": "101", - "calculation_state": "searching", + "calculation_state": "up", "published_interpretation": "decline 4.71698%; below 5%" }, { @@ -66,7 +77,7 @@ "published_interpretation": "decline 5.66038%; confirm high event 2 at index 4" } ], - "explanation": "Start at 100 with a 5% threshold. Prices rise through 103 to\n106, so the running high is 106. A fall to 101 is only 4.72% and does not\nconfirm the high. A fall to 100 is 5.66%; the high at 106 becomes confirmed on\nthe 100 observation. Its event time and confirmation time are different, while\nthe new low endpoint remains provisional.", + "explanation": "Start at 100 with a 5% threshold and a two-bar minimum separation. The rise to 106 confirms the low at index 0 on index 2 and starts an up leg. A fall to 101 is only 4.72% and does not confirm the high. A fall to 100 is 5.66%; the high at 106 becomes confirmed on index 4. Each pivot therefore keeps separate event and confirmation indexes, while the newest endpoint remains provisional.", "historical_example_decision": "not useful", "evidence_boundary": "Definition and detection behavior only; no prediction or profitability claim." } diff --git a/test/fixtures/D08-F01-A03.json b/test/fixtures/D08-F01-A03.json index 545559a..7af3251 100644 --- a/test/fixtures/D08-F01-A03.json +++ b/test/fixtures/D08-F01-A03.json @@ -1,5 +1,33 @@ { - "topic_id": "D08-F01-A03", + "topicId": "D08-F01-A03", + "input": { + "pivots": [ + {"kind": "high", "event_index": 0, "confirmation_index": 1, "price": 100}, + {"kind": "high", "event_index": 2, "confirmation_index": 3, "price": 100.3}, + {"kind": "high", "event_index": 4, "confirmation_index": 5, "price": 99.9}, + {"kind": "high", "event_index": 6, "confirmation_index": 7, "price": 105} + ], + "epsBps": 50, + "minTouches": 3 + }, + "expected": { + "clusters": [ + { + "kind": "high", + "cluster_id": "high-0", + "level": 100, + "lower": 99.9, + "upper": 100.3, + "touch_count": 3, + "first_confirmation_index": 1, + "last_confirmation_index": 5, + "member_event_indexes": [0, 2, 4] + } + ], + "noise": [ + {"kind": "high", "event_index": 6, "confirmation_index": 7, "price": 105} + ] + }, "classification": "author-derived calculation over synthetic teaching input", "selected_variant": "Same-kind one-dimensional DBSCAN in log-price space, median cluster level, and confirmation-time availability.", "formulae": [ diff --git a/test/fixtures/D08-F01-A04.json b/test/fixtures/D08-F01-A04.json index 9f394f3..1f9cbf8 100644 --- a/test/fixtures/D08-F01-A04.json +++ b/test/fixtures/D08-F01-A04.json @@ -1,5 +1,29 @@ { - "topic_id": "D08-F01-A04", + "topicId": "D08-F01-A04", + "input": { + "pivots": [ + {"kind": "low", "event_index": 0, "confirmation_index": 2, "price": 99.48431564193378}, + {"kind": "low", "event_index": 10, "confirmation_index": 12, "price": 109.94717245212352}, + {"kind": "low", "event_index": 20, "confirmation_index": 22, "price": 121.51041751873485}, + {"kind": "low", "event_index": 30, "confirmation_index": 32, "price": 244.69193226422038} + ], + "kind": "low", + "toleranceBps": 50, + "minInliers": 3, + "maxPoints": 12 + }, + "expected": { + "kind": "low", + "slope_log_per_bar": 0.010000000000000009, + "intercept_log": 4.6, + "projected_index": 31, + "projected_price": 135.63941440846523, + "inlier_count": 3, + "outlier_count": 1, + "median_absolute_residual_bps": 0, + "inlier_event_indexes": [0, 10, 20], + "source_pivot_count": 4 + }, "classification": "author-derived calculation over synthetic teaching input", "selected_variant": "Exhaustive two-point consensus in log-price space, inclusive residual tolerance, deterministic tie-breaking, then least-squares refit on inliers.", "formulae": [ diff --git a/test/fixtures/D09-F02-A01.json b/test/fixtures/D09-F02-A01.json index 006777f..1660ffe 100644 --- a/test/fixtures/D09-F02-A01.json +++ b/test/fixtures/D09-F02-A01.json @@ -1,5 +1,12 @@ { - "topic_id": "D09-F02-A01", + "topicId": "D09-F02-A01", + "input": { + "values": [10, 12, 11], + "ar": [0.5], + "intercept": 5, + "horizon": 2 + }, + "expected": {"forecast": [10.5, 10.25]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Fixed-coefficient AR(p) with an intercept, contiguous lags 1 through p, recursive point forecasts, and no exogenous or seasonal terms.", "values": [ diff --git a/test/fixtures/D09-F02-A02.json b/test/fixtures/D09-F02-A02.json index 3cf029a..b36651c 100644 --- a/test/fixtures/D09-F02-A02.json +++ b/test/fixtures/D09-F02-A02.json @@ -1,5 +1,13 @@ { - "topic_id": "D09-F02-A02", + "topicId": "D09-F02-A02", + "input": { + "values": [10, 12, 11], + "ar": [0.5], + "ma": [0.25], + "intercept": 5, + "horizon": 2 + }, + "expected": {"forecast": [10.375, 10.1875]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Fixed-coefficient ARMA(p,q) with an intercept, contiguous lags, zero pre-sample innovations, recursively reconstructed in-sample residuals, and zero future innovations.", "values": [ diff --git a/test/fixtures/D09-F02-A03.json b/test/fixtures/D09-F02-A03.json index 058aab3..a0f17f0 100644 --- a/test/fixtures/D09-F02-A03.json +++ b/test/fixtures/D09-F02-A03.json @@ -1,5 +1,14 @@ { - "topic_id": "D09-F02-A03", + "topicId": "D09-F02-A03", + "input": { + "values": [100, 102, 105, 109, 114, 120], + "ar": [0.5], + "ma": [], + "intercept": 1, + "differenceOrder": 1, + "horizon": 2 + }, + "expected": {"forecast": [124, 127]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Fixed-coefficient non-seasonal ARIMA(p,d,q), d in {0,1,2}, conditional ARMA residuals, and recursive reintegration from recorded anchors.", "values": [ diff --git a/test/fixtures/D09-F02-A04.json b/test/fixtures/D09-F02-A04.json index cfe2d78..4fe5dfc 100644 --- a/test/fixtures/D09-F02-A04.json +++ b/test/fixtures/D09-F02-A04.json @@ -1,5 +1,21 @@ { - "topic_id": "D09-F02-A04", + "topicId": "D09-F02-A04", + "input": { + "values": [12, 15, 18, 21, 24, 27, 30, 33], + "exog": [[1], [2], [3], [4], [5], [6], [7], [8]], + "futureExog": [[9], [10]], + "beta": [2], + "ar": [0.5], + "ma": [], + "seasonalAr": [0.25], + "seasonalMa": [], + "intercept": 0, + "differenceOrder": 1, + "seasonalDifferenceOrder": 0, + "period": 2, + "horizon": 2 + }, + "expected": {"forecast": [35.625, 38.0625]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Regression plus multiplicative SARIMA errors with fixed coefficients, d and D in {0,1}, known future exogenous rows, zero future innovations, and explicit polynomial cross-terms.", "values": [ diff --git a/test/fixtures/D09-F02-A05.json b/test/fixtures/D09-F02-A05.json index f0bf3aa..00dda8b 100644 --- a/test/fixtures/D09-F02-A05.json +++ b/test/fixtures/D09-F02-A05.json @@ -1,5 +1,17 @@ { - "topic_id": "D09-F02-A05", + "topicId": "D09-F02-A05", + "input": { + "values": [10, 12, 11, 13], + "alpha": 0.5, + "beta": 0.5, + "gamma": 0.5, + "period": 2, + "horizon": 2, + "initialLevel": 9, + "initialTrend": 1, + "initialSeasonals": [-1, 1] + }, + "expected": {"forecast": [12.35546875, 14.58203125]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Additive trend and additive seasonality, fixed alpha/beta/gamma-star in [0,1], a supplied known initial state with published provenance, no damping, and deterministic recursive updates.", "values": [ diff --git a/test/fixtures/D09-F02-A06.json b/test/fixtures/D09-F02-A06.json index de33a64..4044550 100644 --- a/test/fixtures/D09-F02-A06.json +++ b/test/fixtures/D09-F02-A06.json @@ -1,5 +1,11 @@ { - "topic_id": "D09-F02-A06", + "topicId": "D09-F02-A06", + "input": { + "values": [10, 12, 14, 16], + "alpha": 0.5, + "horizon": 2 + }, + "expected": {"forecast": [16.125, 17.125]}, "classification": "author-derived arithmetic over synthetic teaching input", "selected_variant": "Classical theta-zero/theta-two point forecast in its exact non-seasonal SES-with-drift form, fixed alpha in (0,1], OLS slope over t=0...n-1, and finite-sample correction.", "values": [ diff --git a/test/fixtures/D09-F04-A01.json b/test/fixtures/D09-F04-A01.json index 6b334ce..43dcefb 100644 --- a/test/fixtures/D09-F04-A01.json +++ b/test/fixtures/D09-F04-A01.json @@ -1,5 +1,22 @@ { - "topic_id": "D09-F04-A01", + "topicId": "D09-F04-A01", + "input": { + "observations": [0.1740371542, 0.7180296431, 0.0364260071], + "config": {"a": 0.96, "h": 1.0, "q": 0.08, "r": 0.64, "initial_mean": 0.0, "initial_variance": 2.0} + }, + "expected": { + "2": { + "index": 2, + "predicted_mean": 0.376086443860437, + "predicted_variance": 0.3451182399024169, + "predicted_observation": 0.376086443860437, + "innovation": -0.339660436760437, + "innovation_variance": 0.985118239902417, + "kalman_gain": 0.350331793609469, + "filtered_mean": 0.25709259383197747, + "filtered_variance": 0.22421234791006017 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "a": 0.96, diff --git a/test/fixtures/D09-F04-A02.json b/test/fixtures/D09-F04-A02.json index 83dfcf1..b1fa812 100644 --- a/test/fixtures/D09-F04-A02.json +++ b/test/fixtures/D09-F04-A02.json @@ -1,5 +1,24 @@ { - "topic_id": "D09-F04-A02", + "topicId": "D09-F04-A02", + "input": { + "observations": [0.1740564489, 0.7180957323, 0.0365723689], + "config": {"a": 0.9, "b": 0.22, "c": 0.04, "q": 0.06, "r": 0.49, "initial_mean": 0.0, "initial_variance": 1.5} + }, + "expected": { + "2": { + "index": 2, + "transition_jacobian": 1.0979025313193456, + "measurement_jacobian": 1.040234775932769, + "predicted_mean": 0.5029346991596126, + "predicted_variance": 0.36799793432466277, + "predicted_observation": 0.5130524316243634, + "innovation": -0.47648006272436344, + "innovation_variance": 0.8882062919307445, + "kalman_gain": 0.4309857431023305, + "filtered_mean": 0.2975785852529078, + "filtered_variance": 0.20301476071185573 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "a": 0.9, diff --git a/test/fixtures/D09-F04-A03.json b/test/fixtures/D09-F04-A03.json index d4a9ef0..a56423e 100644 --- a/test/fixtures/D09-F04-A03.json +++ b/test/fixtures/D09-F04-A03.json @@ -1,5 +1,25 @@ { - "topic_id": "D09-F04-A03", + "topicId": "D09-F04-A03", + "input": { + "observations": [0.1740564489, 0.7180957323, 0.0365723689], + "config": {"a": 0.9, "b": 0.22, "c": 0.04, "q": 0.06, "r": 0.49, "alpha": 1.0, "beta": 2.0, "kappa": 0.0, "initial_mean": 0.0, "initial_variance": 1.5} + }, + "expected": { + "2": { + "index": 2, + "sigma_left": -0.0995315114397366, + "sigma_center": 0.4049746384367636, + "sigma_right": 0.9094807883132638, + "predicted_mean": 0.4403571228780741, + "predicted_variance": 0.36471237345744356, + "predicted_measurement": 0.46270219364315, + "innovation": -0.42612982474315003, + "innovation_variance": 0.8812872395279235, + "kalman_gain": 0.4284195343347881, + "filtered_mean": 0.2577947817954489, + "filtered_variance": 0.20295800755826507 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "a": 0.9, diff --git a/test/fixtures/D09-F04-A04.json b/test/fixtures/D09-F04-A04.json index 6cc4ffb..e3efbaa 100644 --- a/test/fixtures/D09-F04-A04.json +++ b/test/fixtures/D09-F04-A04.json @@ -1,5 +1,20 @@ { - "topic_id": "D09-F04-A04", + "topicId": "D09-F04-A04", + "input": { + "observations": [-0.9183368993, -0.5364890278, -0.550167602], + "config": {"transition": [[0.94, 0.06], [0.12, 0.88]], "means": [-0.15, 0.25], "stds": [0.55, 1.45], "initial": [0.8, 0.2]} + }, + "expected": { + "2": { + "index": 2, + "predicted_state_0": 0.8612154040743613, + "predicted_state_1": 0.13878459592563866, + "posterior_state_0": 0.9359801579550974, + "posterior_state_1": 0.0640198420449025, + "most_likely_state": 0, + "log_predictive_density": -0.6690356366768324 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "transition": [ diff --git a/test/fixtures/D09-F04-A05.json b/test/fixtures/D09-F04-A05.json index 4649731..2f10de4 100644 --- a/test/fixtures/D09-F04-A05.json +++ b/test/fixtures/D09-F04-A05.json @@ -1,5 +1,23 @@ { - "topic_id": "D09-F04-A05", + "topicId": "D09-F04-A05", + "input": { + "observations": [-0.0710447869, 0.2119198541, 0.4036856432], + "config": {"transition": [[0.95, 0.05], [0.1, 0.9]], "intercepts": [0.12, -0.18], "phis": [0.72, -0.3], "stds": [0.35, 1.05], "initial": [0.85, 0.15]} + }, + "expected": { + "2": { + "index": 2, + "regime_0_forecast": 0.272582294952, + "regime_1_forecast": -0.24357595623, + "predicted_state_0": 0.8867587273436667, + "predicted_state_1": 0.11324127265633334, + "posterior_state_0": 0.9636140438968227, + "posterior_state_1": 0.03638595610317732, + "most_likely_state": 0, + "next_mixture_forecast": 0.3530523573178951, + "log_predictive_density": -0.022389779102029245 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "transition": [ diff --git a/test/fixtures/D09-F04-A06.json b/test/fixtures/D09-F04-A06.json index e5fcf8a..23d00c8 100644 --- a/test/fixtures/D09-F04-A06.json +++ b/test/fixtures/D09-F04-A06.json @@ -1,5 +1,20 @@ { - "topic_id": "D09-F04-A06", + "topicId": "D09-F04-A06", + "input": { + "observations": [-0.3275053489, 0.2452664583, 0.224748597], + "config": {"hazard": 0.025, "observation_variance": 0.36, "prior_mean": 0.0, "prior_variance": 4.0} + }, + "expected": { + "2": { + "index": 2, + "change_probability": 0.00942784148480789, + "map_run_length": 3, + "expected_run_length": 2.9241612404581354, + "active_hypotheses": 4, + "map_mean": 0.04611964608414239, + "log_predictive_density": -0.6857585614486436 + } + }, "classification": "author-derived from deterministic synthetic input", "configuration": { "hazard": 0.025, diff --git a/test/registry.test.ts b/test/registry.test.ts index 99ff641..11726c7 100644 --- a/test/registry.test.ts +++ b/test/registry.test.ts @@ -1,6 +1,5 @@ /** - * Structural guarantees that hold for all 114 topics, including the 73 without a - * machine-checkable worked example. + * Structural guarantees that hold for every generated topic. * * This is the safety net for the generator: if `scripts/sync.mjs` mis-detects an * entry point, drops a subpath from the exports map, or emits metadata that @@ -20,6 +19,19 @@ const REPO = join(HERE, ".."); const pkg = JSON.parse(readFileSync(join(REPO, "package.json"), "utf8")) as { exports: Record; }; +const testManifest = JSON.parse(readFileSync(join(HERE, "_manifest.json"), "utf8")) as { + topics: Array<{ id: string; entryParams: string[] }>; +}; +const docsPayload = JSON.parse(readFileSync(join(REPO, "docs.json"), "utf8")) as { + topics: Array<{ + id: string; + api: null | { + params: Array<{ name: string; type: string }>; + returns: null | { description?: string }; + warmup: null | { count: string; value: string; note: string }; + }; + }>; +}; describe("registry", () => { test("is non-empty and internally consistent", () => { @@ -39,6 +51,26 @@ describe("registry", () => { ); }); + test("public TypeScript entries use camelCase", () => { + const offenders = topics.filter((t) => t.entry.includes("_")).map((t) => `${t.id}: ${t.entry}`); + assert.deepStrictEqual(offenders, []); + }); + + test("record inputs and readiness rules are machine-readable", () => { + const opaque: string[] = []; + const proseOnlyWarmups: string[] = []; + for (const topic of docsPayload.topics) { + for (const param of topic.api?.params ?? []) { + if (param.type === "Record") opaque.push(`${topic.id}: ${param.name}`); + } + if (/warmup|warm-up/i.test(topic.api?.returns?.description ?? "") && !topic.api?.warmup) { + proseOnlyWarmups.push(topic.id); + } + } + assert.deepStrictEqual(opaque, [], "opaque public input contracts"); + assert.deepStrictEqual(proseOnlyWarmups, [], "warm-up rules present only in prose"); + }); + test("subpath mirrors the article URL", () => { for (const t of topics) { assert.ok( @@ -105,7 +137,7 @@ describe("registry", () => { "D02-F04-A02": "guardSurvivorship", "D04-F03-A04": "evaluateSnapshot", "D04-F03-A05": "evaluateSnapshot", "D04-F03-A06": "evaluateSnapshot", "D07-F01-A04": "calculateRma", - "D07-F04-A02": "average_true_range", // slug is the initialism ATR + "D07-F04-A02": "averageTrueRange", // slug is the initialism ATR // Structural VAR. The module exports nine functions, and the topic's own // catalog test invokes fitRecursiveSVAR() and nothing else — the highest @@ -158,6 +190,35 @@ describe("registry", () => { assert.deepStrictEqual(clashes, [], "topics from a shared implementation file collapsed onto one entry point"); }); + test("reversal subpaths expose only their own public pattern wrapper", async () => { + const entries = [ + "doubleTop", + "doubleBottom", + "tripleTop", + "tripleBottom", + "headAndShoulders", + "inverseHeadAndShoulders", + ]; + const reversalTopics = topics.filter((t) => t.familyId === "D08-F02"); + assert.equal(reversalTopics.length, entries.length, "D08-F02 topic count changed without updating this contract"); + + for (const t of reversalTopics) { + const mod = (await load(t.id)) as Record; + assert.ok(entries.includes(t.entry), `${t.id}: unexpected reversal entry ${t.entry}`); + assert.equal(typeof mod[t.entry], "function", `${t.id}: own wrapper is missing`); + assert.equal(mod.run, mod[t.entry], `${t.id}: run is not the own wrapper alias`); + for (const helper of ["confirmedPivots", "detectReversal", "traceReversal"]) { + assert.equal(typeof mod[helper], "function", `${t.id}: supported helper ${helper} is missing`); + } + for (const peer of entries.filter((entry) => entry !== t.entry)) { + assert.equal(Object.hasOwn(mod, peer), false, `${t.id}: leaked peer wrapper ${peer}`); + } + + const manifestTopic = testManifest.topics.find((candidate) => candidate.id === t.id); + assert.deepStrictEqual(manifestTopic?.entryParams, ["close", "params"], `${t.id}: wrapper parameters`); + } + }); + test("lookup helpers agree with the registry", () => { const sample = topics[0]; assert.equal(topic(sample.id)?.id, sample.id); From 46dd92989fe17d5b938e6210765b6c0c0849cdff Mon Sep 17 00:00:00 2001 From: islam Date: Thu, 6 Aug 2026 07:00:21 +0300 Subject: [PATCH 2/2] Add CommonJS resolution, a self-describing payload, and a changelog MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The exports map now declares a `require` condition alongside `import`, both pointing at the same ES module. CommonJS consumers were failing at resolution rather than loading — `import` is not a condition `require()` matches — so no second build is needed, the tarball is unchanged in size, and there is no dual-package hazard. Refs #1. docs.json moves to schema 2.0.0, so a consumer holding only the payload can find the surface that serves it: - `package` states the runtime facts an agent previously had to infer (type, engines, root export is metadata-only, algorithms are subpath-only) and names the machine surface: /llms.txt, /version.json, /reference/payload.json, and the per-domain and per-topic route patterns. Every route was requested against the live site before being written down. - `archetypes` is new — the five input shapes as data, with derived counts, the canonical input type, a minimal payload that executes, and the validator to run at the boundary. - `domains[].slug` is new, so a domain's URL no longer has to be rediscovered by finding one of its topics and splitting the path. - per-topic `languages` becomes `catalogLanguages`, read from the catalog's implementations/ directories instead of hard-coded. The package ships TypeScript alone and now says so once, as `package.languages`. The generator also refuses to emit a payload whose own structure is inconsistent, and takes --strict-contracts to refuse one where a topic has no api: block at all. CHANGELOG.md records the 0.12.0 migration: 23 snake_case entry points renamed to camelCase, and 110 sibling re-exports removed across 28 subpaths. Both tables are generated by diffing the published 0.11.0 payload, and the file now ships inside the tarball. CI gains the contract-coverage gate and a CommonJS smoke test of the packed tarball alongside the existing ESM one. --- .github/workflows/ci.yml | 39 + .github/workflows/release.yml | 8 + CHANGELOG.md | 167 +++ docs.json | 2180 ++++++++++++++++++--------------- package.json | 976 ++++++++++----- scripts/gen-docs.mjs | 308 ++++- scripts/sync.mjs | 29 +- 7 files changed, 2393 insertions(+), 1314 deletions(-) create mode 100644 CHANGELOG.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5dfc1eb..d52ac12 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,23 @@ jobs: - name: Build run: npm run build + # Contract coverage is invisible to the drift guard: a topic that never had + # an `api:` block round-trips perfectly, which is how a complete 271/271 + # quietly became 280/324. This reads the committed payload, so it runs on + # every pull request whether or not the catalog checkout is available. + - name: Enforce contract coverage + run: | + node -e ' + const p = require("./docs.json"); + const missing = p.topics.filter((t) => !t.api); + if (missing.length) { + console.error(`${missing.length} of ${p.topics.length} topics have no api: contract`); + for (const t of missing.slice(0, 20)) console.error(` ${t.id} ${t.path}`); + process.exit(1); + } + console.log(`contract coverage: ${p.topics.length}/${p.topics.length}`); + ' + # Proves the published tarball is self-contained: the exports map resolves, # dist/ is complete, and no file the package needs was left out of `files`. - name: Pack and smoke-test the tarball @@ -43,6 +60,21 @@ jobs: console.log(`tarball OK — ${topics.length} topics resolvable from a clean consumer`); ' + # The same consumer, from CommonJS. The exports map declares a `require` + # condition pointing at the ES module, so this fails loudly if that + # condition is ever dropped — resolution, not loading, is what breaks. + - name: Smoke-test the tarball from CommonJS + working-directory: /tmp/consumer + run: | + node --input-type=commonjs -e ' + const { topics } = require("fintech-algorithms"); + const { calculateEma } = require("fintech-algorithms/technical-indicators/trend-smoothing/ema"); + if (topics.length === 0) throw new Error("registry is empty"); + const out = calculateEma([10, 13, 16, 19], 3); + if (out[2] !== 13 || out[3] !== 16) throw new Error("EMA regression: " + JSON.stringify(out)); + console.log(`tarball OK from CommonJS — ${topics.length} topics`); + ' + # The package is generated from the edufintech catalog, which lives in a # different repository. This job only runs when that checkout is available. sync-drift: @@ -66,3 +98,10 @@ jobs: - name: Fail if the package has drifted from the catalog working-directory: package run: node scripts/sync.mjs --check --content-root ../catalog + + # With the catalog present the same coverage question can be asked of the + # source rather than the payload: a topic arriving without an `api:` block + # fails here, before it can ever reach a committed docs.json. + - name: Fail if any topic reaches the payload without a contract + working-directory: package + run: node scripts/gen-docs.mjs --check --strict-contracts --content-root ../catalog diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d55a08a..e8154c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,6 +61,14 @@ jobs: if (out[2] !== 13 || out[3] !== 16) throw new Error("EMA regression: " + JSON.stringify(out)); console.log(`tarball OK — ${topics.length} topics resolvable from a clean consumer`); ' + node --input-type=commonjs -e ' + const { topics } = require("fintech-algorithms"); + const { calculateEma } = require("fintech-algorithms/technical-indicators/trend-smoothing/ema"); + if (topics.length === 0) throw new Error("registry is empty"); + const out = calculateEma([10, 13, 16, 19], 3); + if (out[2] !== 13 || out[3] !== 16) throw new Error("EMA regression: " + JSON.stringify(out)); + console.log(`tarball OK from CommonJS — ${topics.length} topics`); + ' # No NODE_AUTH_TOKEN: npm authenticates over OIDC via the trusted # publisher configured on npmjs.com for this repository and workflow file. diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..f7e1ed5 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,167 @@ +# Changelog + +All notable changes to `fintech-algorithms` are recorded here. + +The package is pre-1.0. Breaking changes go in the minor version, additive and +corrective changes in the patch — so `0.11.0 → 0.12.0` can break you and +`0.12.0 → 0.12.1` cannot. + +## 0.12.0 — 2026-08-06 + +The library gains no algorithms in this release and loses none: 324 topics +before, 324 after. What changed is the surface in front of them. Every entry +point now has one spelling, every subpath exports exactly its own function, and +every topic carries a validated input contract. + +**If you are upgrading from 0.11.0, read the two tables below.** 23 functions +were renamed and 110 re-exports were removed; both fail loudly at import time +rather than silently at run time, but both fail. + +### Breaking — entry points renamed to camelCase + +23 entry points were still snake_case, inherited from the reference +implementations they were generated from. TypeScript consumers had to remember +which of the 324 were the exceptions. They are now camelCase like the other 301. + +| Old symbol | New symbol | Import it from | +| --- | --- | --- | +| `accumulation_distribution_line` | `accumulationDistributionLine` | `fintech-algorithms/technical-indicators/volume-indicators/accumulation-distribution-line` | +| `average_true_range` | `averageTrueRange` | `fintech-algorithms/technical-indicators/volatility-and-channels/atr` | +| `bollinger_bands` | `bollingerBands` | `fintech-algorithms/technical-indicators/volatility-and-channels/bollinger-bands` | +| `bollinger_bandwidth` | `bollingerBandwidth` | `fintech-algorithms/technical-indicators/volatility-and-channels/bollinger-bandwidth` | +| `chaikin_money_flow` | `chaikinMoneyFlow` | `fintech-algorithms/technical-indicators/volume-indicators/chaikin-money-flow` | +| `connors_rsi` | `connorsRsi` | `fintech-algorithms/technical-indicators/momentum/connors-rsi` | +| `directional_movement` | `directionalMovement` | `fintech-algorithms/technical-indicators/trend-systems/directional-movement` | +| `donchian_channels` | `donchianChannels` | `fintech-algorithms/technical-indicators/volatility-and-channels/donchian-channels` | +| `double_bottom` | `doubleBottom` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/double-bottom` | +| `double_top` | `doubleTop` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/double-top` | +| `force_index` | `forceIndex` | `fintech-algorithms/technical-indicators/volume-indicators/force-index` | +| `head_and_shoulders` | `headAndShoulders` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/head-and-shoulders` | +| `inverse_head_and_shoulders` | `inverseHeadAndShoulders` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders` | +| `keltner_channels` | `keltnerChannels` | `fintech-algorithms/technical-indicators/volatility-and-channels/keltner-channels` | +| `money_flow_index` | `moneyFlowIndex` | `fintech-algorithms/technical-indicators/volume-indicators/money-flow-index` | +| `parabolic_sar` | `parabolicSar` | `fintech-algorithms/technical-indicators/trend-systems/parabolic-sar` | +| `stochastic_rsi` | `stochasticRsi` | `fintech-algorithms/technical-indicators/momentum/stochastic-rsi` | +| `triple_bottom` | `tripleBottom` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/triple-bottom` | +| `triple_top` | `tripleTop` | `fintech-algorithms/geometric-chart-patterns/reversal-structures/triple-top` | +| `true_range` | `trueRange` | `fintech-algorithms/technical-indicators/volatility-and-channels/true-range` | +| `ultimate_oscillator` | `ultimateOscillator` | `fintech-algorithms/technical-indicators/momentum/ultimate-oscillator` | +| `volume_price_trend` | `volumePriceTrend` | `fintech-algorithms/technical-indicators/volume-indicators/volume-price-trend` | +| `williams_r` | `williamsR` | `fintech-algorithms/technical-indicators/momentum/williams-r` | + +No other entry point changed. The 301 that were already camelCase are untouched. + +### Breaking — subpaths no longer re-export their siblings + +28 subpaths used to re-export the other functions in their family: importing +`.../momentum/rsi` also gave you `williams_r`, `connors_rsi`, `stochastic_rsi` +and `ultimate_oscillator`. 110 such re-exports have been removed. + +**Why.** A subpath is meant to be one function. Re-exporting siblings meant the +same symbol had several valid import paths, so no import told you which module +you actually depended on, and every family member was pulled in whether or not +it was used. + +**The fix.** Import each function from its own subpath — the third column of the +table above. The symbol did not disappear; it stopped being in more than one +place. + +Every removed re-export is one of the 23 renamed functions, so a call site +touched by this is usually touched by the rename too: + +| Symbol | Was also exported by | Now only at | +| --- | --- | --- | +| `accumulationDistributionLine` | 5 sibling subpaths | `technical-indicators/volume-indicators/accumulation-distribution-line` | +| `averageTrueRange` | 1 sibling subpath | `technical-indicators/volatility-and-channels/atr` | +| `bollingerBands` | 1 sibling subpath | `technical-indicators/volatility-and-channels/bollinger-bands` | +| `chaikinMoneyFlow` | 5 sibling subpaths | `technical-indicators/volume-indicators/chaikin-money-flow` | +| `connorsRsi` | 7 sibling subpaths | `technical-indicators/momentum/connors-rsi` | +| `doubleBottom` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/double-bottom` | +| `doubleTop` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/double-top` | +| `forceIndex` | 5 sibling subpaths | `technical-indicators/volume-indicators/force-index` | +| `headAndShoulders` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/head-and-shoulders` | +| `inverseHeadAndShoulders` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders` | +| `moneyFlowIndex` | 5 sibling subpaths | `technical-indicators/volume-indicators/money-flow-index` | +| `stochasticRsi` | 7 sibling subpaths | `technical-indicators/momentum/stochastic-rsi` | +| `tripleBottom` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/triple-bottom` | +| `tripleTop` | 5 sibling subpaths | `geometric-chart-patterns/reversal-structures/triple-top` | +| `trueRange` | 2 sibling subpaths | `technical-indicators/volatility-and-channels/true-range` | +| `ultimateOscillator` | 7 sibling subpaths | `technical-indicators/momentum/ultimate-oscillator` | +| `volumePriceTrend` | 5 sibling subpaths | `technical-indicators/volume-indicators/volume-price-trend` | +| `williamsR` | 7 sibling subpaths | `technical-indicators/momentum/williams-r` | + +### Added — CommonJS can resolve the package + +Every entry in the `exports` map now declares a `require` condition alongside +`import`. Both point at the same ES module: there is no second build, the +tarball is the size it was, and there is no dual-package hazard because there is +only ever one copy of a module's state. + +```js +const { calculateEma } = require("fintech-algorithms/technical-indicators/trend-smoothing/ema"); +``` + +Previously this failed with `ERR_PACKAGE_PATH_NOT_EXPORTED` — resolution, not +loading, was the blocker: `import` is not a condition `require()` will match. +`require()` of an ES module needs a runtime that supports it, which recent +Node 22 does; the package's `engines` floor is unchanged at `node >= 22`. +Resolves [#1](https://github.com/IslamBaraka90/Fintech-Algorithms-Library/issues/1). + +### Added — the payload describes the surface that serves it + +`docs.json` (also published at +[`/reference/payload.json`](https://docs.thefintechbuilder.com/reference/payload.json)) +moves to **schema 2.0.0**. A consumer holding only the payload can now find the +machine endpoints and map its own data onto the library without reading prose. + +- **`package`** gained `type`, `engines`, `license`, the package's own + `languages` (TypeScript, and only TypeScript), an `entryPoints` block stating + that the root export is metadata-only and algorithms are subpath-only, and a + `machineSurface` block naming `/llms.txt`, `/version.json`, + `/reference/payload.json` and the per-domain and per-topic route patterns. + These fields flow into + [`/version.json`](https://docs.thefintechbuilder.com/version.json) unchanged. +- **`archetypes`** is new: the five input shapes as data — topic count, the + canonical TypeScript input type, a runnable minimal payload, the validator to + run at the boundary, and the one mistake each shape invites. This is the + machine half of [the archetypes guide](https://docs.thefintechbuilder.com/guides/archetypes/). +- **`domains[].slug`** is new, so the URL for a domain no longer has to be + rediscovered by finding one of its topics and splitting the path. + +### Changed — `languages` is now `catalogLanguages` (breaking for payload consumers) + +Every topic declared `languages: ["typescript", "python"]`. That is true of the +catalog the package is generated from and false of the package, which ships +TypeScript alone — and an agent reading it would confidently write +`pip install fintech-algorithms`, which does not exist. + +The per-topic field is renamed to `catalogLanguages` and is now read from the +catalog's actual `implementations/` directories rather than hard-coded. What +*this package* ships is stated once, as `package.languages`. + +### Improved + +| | 0.11.0 | 0.12.0 | +| --- | --- | --- | +| Topics with a validated `api` contract | 280 / 324 | **324 / 324** | +| Topics with a fixture-verified worked example | 88 | **158** | +| Topics with any worked example | 279 | **324** | + +Every `api` block is checked against the implementation it documents at +generation time — a declared parameter list that disagrees with the function's +real signature fails the build. Contract coverage is now enforced in CI, so a +topic can no longer arrive without one. + +### Internal + +- The generator refuses to emit a payload whose own structure is inconsistent — + a domain spanning two path roots, or an archetype with no description. +- `gen-docs.mjs` takes `--strict-contracts`. +- CI smoke-tests the packed tarball from CommonJS as well as ESM. +- `CHANGELOG.md` ships inside the tarball. + +## 0.11.0 and earlier + +Not recorded. `docs.json` inside each published version is the reliable record +of what that version contained; the payload for any release is available at +`https://unpkg.com/fintech-algorithms@/docs.json`. diff --git a/docs.json b/docs.json index a165ad9..3cb15d4 100644 --- a/docs.json +++ b/docs.json @@ -1,9 +1,43 @@ { - "schemaVersion": "1.0.0", + "schemaVersion": "2.0.0", "package": { "name": "fintech-algorithms", "version": "0.12.0", - "homepage": "https://docs.thefintechbuilder.com" + "homepage": "https://docs.thefintechbuilder.com", + "license": "MIT", + "type": "module", + "engines": { + "node": ">=22" + }, + "languages": [ + "typescript" + ], + "entryPoints": { + "root": { + "specifier": "fintech-algorithms", + "contains": "metadata", + "note": "The root export carries the topic registry and the lookup helpers (topic, byDomain, byFamily, byArchetype, load, runner). No algorithm is re-exported here." + }, + "topic": { + "pattern": "fintech-algorithms/{topic.path}", + "conditions": [ + "import", + "require" + ], + "note": "Algorithms are subpath-only. Each subpath exports the function named in its `import.entry` and its own types; a sibling topic's function is never re-exported, so import it from its own subpath.", + "commonjs": "The require condition resolves to the same ES module as import — there is no separate CommonJS build — so require() needs a runtime that supports require(esm)." + } + }, + "machineSurface": { + "site": "https://docs.thefintechbuilder.com", + "llms": "https://docs.thefintechbuilder.com/llms.txt", + "versionEndpoint": "https://docs.thefintechbuilder.com/version.json", + "payload": "https://docs.thefintechbuilder.com/reference/payload.json", + "domainLlms": "https://docs.thefintechbuilder.com/{domain.slug}/llms.txt", + "topicPage": "https://docs.thefintechbuilder.com/{topic.path}/", + "topicMarkdown": "https://docs.thefintechbuilder.com/{topic.path}/index.md", + "archetypeGuide": "https://docs.thefintechbuilder.com/guides/archetypes/" + } }, "counts": { "topics": 324, @@ -14,10 +48,196 @@ "withDiagram": 324, "withApiContract": 324 }, + "archetypes": [ + { + "name": "series-transform", + "topicCount": 37, + "firstArgument": "(number | null)[]", + "returns": "an array of the same length, aligned index-for-index with the input", + "type": "type SeriesTransform = (values: (number | null)[], ...params: number[]) => (number | null)[];", + "example": { + "subpath": "fintech-algorithms/technical-indicators/trend-smoothing/sma", + "entry": "calculateSma", + "call": "calculateSma([10, 13, 12, 15, 14, 18], 3)", + "args": [ + [ + 10, + 13, + 12, + 15, + 14, + 18 + ], + 3 + ] + }, + "validator": { + "subpath": "fintech-algorithms/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter", + "note": "A numeric series has no structure to check, so check its values. Takes the same number[] you are about to pass to the indicator." + }, + "caveat": "Leading nulls are warm-up, not missing data. The output is the same length as the input so that bars[i] and result[i] describe the same instant; filtering the nulls shifts the series left and nothing errors." + }, + { + "name": "tape-aggregate", + "topicCount": 7, + "firstArgument": "Trade[]", + "returns": "Bar[]", + "type": "type TapeAggregate = (trades: Trade[], config: object) => Bar[];", + "example": { + "subpath": "fintech-algorithms/market-data-engineering/bar-construction/time-bars", + "entry": "constructBars", + "call": "constructBars(trades, { intervalSeconds: 60, sessionStarts: { RTH: … } })", + "args": [ + [ + { + "tradeId": "1", + "timestamp": "2026-07-20T09:30:01.000Z", + "session": "RTH", + "symbol": "DEMO", + "price": 100, + "volume": 500, + "currency": "USD" + } + ], + { + "intervalSeconds": 60, + "sessionStarts": { + "RTH": "2026-07-20T09:30:00.000Z" + } + } + ] + }, + "validator": { + "subpath": "fintech-algorithms/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver", + "note": "Run before aggregating. A duplicated print inflates volume permanently and is invisible once it is inside a bar." + }, + "caveat": "The only shape that cares about ordering and sessions. Trades must arrive in chronological order, and sessionStarts anchors every bucket boundary — get it wrong and every bar edge is off by the same amount, consistently enough to look correct." + }, + { + "name": "row-classify", + "topicCount": 17, + "firstArgument": "an array of rows", + "returns": "one verdict per row, in the same order — verdicts.length === rows.length", + "type": "type RowClassify = (rows: Row[], config?: object) => Verdict[];", + "example": { + "subpath": "fintech-algorithms/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator", + "entry": "validateBars", + "call": "validateBars(bars, { tickSize: 0.01, toleranceTicks: 1, priceScale: 1 })", + "args": [ + [ + { + "timestamp": "2026-07-20T09:30:00Z", + "symbol": "DEMO", + "open": 100, + "high": 101, + "low": 99.5, + "close": 100.5, + "volume": 1000 + } + ], + { + "tickSize": 0.01, + "toleranceTicks": 1, + "priceScale": 1 + } + ] + }, + "validator": { + "subpath": null, + "note": "This archetype is the boundary. It is what you run before the other four." + }, + "caveat": "Nothing signals failure except the verdict. These never throw on bad input — one malformed record in ten thousand should lose neither the record nor the other 9,999 — so ignoring the return value looks like success." + }, + { + "name": "snapshot-evaluate", + "topicCount": 6, + "firstArgument": "one point-in-time snapshot", + "returns": "a single verdict about that instant", + "type": "type SnapshotEvaluate = (snapshot: object, policyOrTime: object | string) => Verdict;", + "example": { + "subpath": "fintech-algorithms/market-data-engineering/data-quality/price-source-consensus-check", + "entry": "consensus", + "call": "consensus({ as_of, quotes }, policy)", + "args": [ + { + "as_of": "2026-07-13T13:30:01.000Z", + "quotes": [ + { + "source_id": "A", + "owner_id": "OWNER-A", + "price": 100, + "instrument_id": "SYNTH-USD", + "currency": "USD", + "price_type": "last_trade", + "adjustment": "unadjusted", + "session": "regular", + "event_time": "2026-07-13T13:30:01.000Z" + }, + { + "source_id": "B", + "owner_id": "OWNER-B", + "price": 100.01, + "instrument_id": "SYNTH-USD", + "currency": "USD", + "price_type": "last_trade", + "adjustment": "unadjusted", + "session": "regular", + "event_time": "2026-07-13T13:30:01.000Z" + }, + { + "source_id": "C", + "owner_id": "OWNER-C", + "price": 100.02, + "instrument_id": "SYNTH-USD", + "currency": "USD", + "price_type": "last_trade", + "adjustment": "unadjusted", + "session": "regular", + "event_time": "2026-07-13T13:30:01.000Z" + } + ] + }, + { + "minimum_independent_sources": 3, + "z_threshold": 3.5, + "absolute_tolerance": 0.03, + "maximum_tolerance": 0.15, + "max_age_ms": 500, + "expected_contract": { + "instrument_id": "SYNTH-USD", + "currency": "USD", + "price_type": "last_trade", + "adjustment": "unadjusted", + "session": "regular" + } + } + ] + }, + "validator": { + "subpath": null, + "note": "These are themselves validators. Feed them the snapshot you are about to trust." + }, + "caveat": "The second argument is usually a decision time, and it is what makes the result reproducible. Passing 'now' instead of the instant being evaluated turns a point-in-time check into look-ahead." + }, + { + "name": "record-transform", + "topicCount": 257, + "firstArgument": "a domain-specific record or array", + "returns": "a domain-specific result", + "type": null, + "example": null, + "validator": { + "subpath": null, + "note": "Whichever matches the record being passed: a bar → ohlc-consistency-validator, a quote → stale-quote-detector, a corporate action → its own family's guard." + }, + "caveat": "Not a shape. This is the residual bucket — a topic lands here when it is none of the other four — so it spans twelve of the thirteen domains and shares no field names between families. Read the topic's own `api` block and `example` in this payload instead." + } + ], "domains": [ { "id": "D01", "name": "Market Data Engineering", + "slug": "market-data-engineering", "topicCount": 31, "families": [ { @@ -50,6 +270,7 @@ { "id": "D02", "name": "Corporate Actions and Security Master Data", + "slug": "corporate-actions-and-security-master-data", "topicCount": 20, "families": [ { @@ -77,6 +298,7 @@ { "id": "D03", "name": "Index and Benchmark Engineering", + "slug": "index-and-benchmark-engineering", "topicCount": 40, "families": [ { @@ -114,6 +336,7 @@ { "id": "D04", "name": "Market Breadth and Internals", + "slug": "market-breadth-and-internals", "topicCount": 28, "families": [ { @@ -146,6 +369,7 @@ { "id": "D06", "name": "Price Action and Candlesticks", + "slug": "price-action-and-candlesticks", "topicCount": 38, "families": [ { @@ -178,6 +402,7 @@ { "id": "D07", "name": "Technical Indicators", + "slug": "technical-indicators", "topicCount": 37, "families": [ { @@ -210,6 +435,7 @@ { "id": "D08", "name": "Geometric Chart Patterns", + "slug": "geometric-chart-patterns", "topicCount": 27, "families": [ { @@ -237,6 +463,7 @@ { "id": "D09", "name": "Statistical Time Series", + "slug": "statistical-time-series", "topicCount": 29, "families": [ { @@ -269,6 +496,7 @@ { "id": "D11", "name": "Market Microstructure", + "slug": "market-microstructure", "topicCount": 29, "families": [ { @@ -301,6 +529,7 @@ { "id": "D12", "name": "Matching Engines and Venue Logic", + "slug": "matching-engines-and-venue-logic", "topicCount": 21, "families": [ { @@ -328,6 +557,7 @@ { "id": "D13", "name": "Execution and Transaction Cost Analysis", + "slug": "execution-and-transaction-cost-analysis", "topicCount": 9, "families": [ { @@ -345,6 +575,7 @@ { "id": "D25", "name": "Digital Assets and On-Chain Finance", + "slug": "digital-assets-and-on-chain-finance", "topicCount": 10, "families": [ { @@ -362,6 +593,7 @@ { "id": "D46", "name": "Earnings and Per-Share Analytics", + "slug": "earnings-and-per-share-analytics", "topicCount": 5, "families": [ { @@ -619,9 +851,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/time-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -857,9 +1089,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/tick-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -1095,9 +1327,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/volume-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -1295,9 +1527,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/dollar-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -1507,9 +1739,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/tick-imbalance-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -1735,9 +1967,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/volume-imbalance-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -1959,9 +2191,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/bar-construction/tick-run-bars/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -2239,9 +2471,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -2465,9 +2697,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -2683,9 +2915,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -2930,9 +3162,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/stale-quote-detector/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -3420,9 +3652,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -3682,9 +3914,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/cleaning-and-validation/crossed-locked-market-detector/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -3929,9 +4161,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/time-synchronization/previous-tick-interpolation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -4199,9 +4431,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/time-synchronization/linear-quote-interpolation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -4485,9 +4717,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/time-synchronization/refresh-time-sampling/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -4742,9 +4974,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/time-synchronization/exchange-calendar-alignment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -4908,9 +5140,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/time-synchronization/asynchronous-return-alignment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -5070,9 +5302,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/missing-bar-gap-classifier/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -5230,9 +5462,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/feed-latency-monitor/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -5456,9 +5688,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/price-source-consensus-check/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -5727,9 +5959,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/schema-drift-detector/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -5938,9 +6170,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/point-in-time-availability-guard/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -6135,9 +6367,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/data-quality/provider-adjustment-basis-drift-detector/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -6415,9 +6647,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -6694,9 +6926,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -6993,9 +7225,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -7259,9 +7491,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -7512,9 +7744,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -7850,9 +8082,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -8250,9 +8482,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -8422,9 +8654,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -8677,9 +8909,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -8978,9 +9210,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -9212,9 +9444,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -9408,9 +9640,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -9623,9 +9855,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -9868,9 +10100,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -10174,9 +10406,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -10422,9 +10654,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -10646,9 +10878,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -10929,9 +11161,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -11198,9 +11430,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -11482,9 +11714,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -11857,9 +12089,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -12161,9 +12393,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -12410,9 +12642,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -12696,9 +12928,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -12948,9 +13180,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -13164,9 +13396,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -13387,9 +13619,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -13609,9 +13841,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -13808,9 +14040,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -14009,9 +14241,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -14212,9 +14444,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -14476,9 +14708,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -14686,9 +14918,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/price-weighted-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -14912,9 +15144,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -15147,9 +15379,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -15378,9 +15610,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -15604,9 +15836,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -15827,9 +16059,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/equal-weight-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -16060,9 +16292,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -16300,9 +16532,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/weighting-and-capping/group-level-capping/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -16541,9 +16773,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -16764,9 +16996,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -17005,9 +17237,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -17233,9 +17465,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -17468,9 +17700,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -17713,9 +17945,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -17932,9 +18164,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/price-return-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -18159,9 +18391,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/gross-total-return-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -18394,9 +18626,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/net-total-return-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -18622,9 +18854,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/excess-return-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -18851,9 +19083,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/dividend-point-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -19078,9 +19310,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/currency-converted-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -19305,9 +19537,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/return-variants/currency-hedged-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -19528,9 +19760,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -19751,9 +19983,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -19984,9 +20216,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/volatility-control-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -20206,9 +20438,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/fixed-decrement-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -20428,9 +20660,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/percentage-decrement-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -20671,9 +20903,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/strategy-indices/index-of-indices/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -20914,9 +21146,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -21168,9 +21400,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -21398,9 +21630,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -21641,9 +21873,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -21866,9 +22098,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -22100,9 +22332,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -22325,9 +22557,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -22564,9 +22796,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -22777,9 +23009,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/advance-decline-breadth/net-advances/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -22969,9 +23201,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -23211,9 +23443,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -23424,9 +23656,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -23599,9 +23831,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -23813,9 +24045,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -23980,9 +24212,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -24147,9 +24379,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -24320,9 +24552,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -24493,9 +24725,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -24672,9 +24904,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -24837,9 +25069,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25002,9 +25234,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25203,9 +25435,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25372,9 +25604,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25541,9 +25773,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25710,9 +25942,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -25947,9 +26179,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -26089,9 +26321,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -26284,9 +26516,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -26424,9 +26656,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -26633,9 +26865,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/cumulative-tick/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -26880,9 +27112,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27054,9 +27286,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27201,9 +27433,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27355,9 +27587,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27509,9 +27741,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27669,9 +27901,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -27862,9 +28094,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candle-foundations/candle-anatomy/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28077,9 +28309,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28243,9 +28475,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28412,9 +28644,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candle-foundations/gap-classification/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28590,9 +28822,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candle-foundations/trend-context-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28780,9 +29012,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/doji/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -28970,9 +29202,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/dragonfly-doji/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -29160,9 +29392,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/gravestone-doji/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -29350,9 +29582,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/marubozu/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -29540,9 +29772,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/spinning-top/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -29730,9 +29962,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/hammer/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -29920,9 +30152,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/hanging-man/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -30110,9 +30342,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/inverted-hammer/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -30300,9 +30532,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/single-candle-patterns/shooting-star/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -30497,9 +30729,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/bullish-engulfing/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -30694,9 +30926,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/bearish-engulfing/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -30891,9 +31123,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/bullish-harami/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -31088,9 +31320,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/bearish-harami/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -31285,9 +31517,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/piercing-line/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -31482,9 +31714,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -31679,9 +31911,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/tweezer-top/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -31876,9 +32108,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/two-candle-patterns/tweezer-bottom/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -32075,9 +32307,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/morning-star/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -32274,9 +32506,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/evening-star/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -32473,9 +32705,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -32672,9 +32904,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/three-black-crows/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -32870,9 +33102,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33066,9 +33298,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33264,9 +33496,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/multi-candle-patterns/abandoned-baby/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33425,9 +33657,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33580,9 +33812,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33782,9 +34014,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -33929,9 +34161,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34092,9 +34324,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34263,9 +34495,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34438,9 +34670,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34593,9 +34825,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34770,9 +35002,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -34978,9 +35210,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/sma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -35158,9 +35390,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/ema/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -35359,9 +35591,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/wma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -35546,9 +35778,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/wilder-rma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -35743,9 +35975,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/dema/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -35943,9 +36175,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/tema/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -36156,9 +36388,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/hull-ma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -36451,9 +36683,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/kama/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -36787,9 +37019,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-smoothing/mama/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -37055,9 +37287,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/macd/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -37302,9 +37534,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/percentage-price-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -37528,9 +37760,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/aroon/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -37835,9 +38067,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/directional-movement/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -38094,9 +38326,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/adx/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -38427,9 +38659,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/ichimoku-cloud/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -38694,9 +38926,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/parabolic-sar/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -39009,9 +39241,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/trend-systems/supertrend/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -39173,9 +39405,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/rsi/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -39432,9 +39664,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/stochastic-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -39665,9 +39897,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/stochastic-rsi/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -39888,9 +40120,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/williams-r/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -40125,9 +40357,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/cci/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -40384,9 +40616,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/ultimate-oscillator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -40567,9 +40799,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/tsi/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -40788,9 +41020,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/momentum/connors-rsi/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -41026,9 +41258,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/true-range/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -41268,9 +41500,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/atr/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -41500,9 +41732,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/bollinger-bands/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -41799,9 +42031,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/keltner-channels/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -42018,9 +42250,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/donchian-channels/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -42251,9 +42483,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volatility-and-channels/bollinger-bandwidth/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -42499,9 +42731,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/obv/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -42811,9 +43043,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/accumulation-distribution-line/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -43123,9 +43355,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/chaikin-money-flow/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -43450,9 +43682,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/money-flow-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -43698,9 +43930,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/volume-price-trend/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -43955,9 +44187,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/technical-indicators/volume-indicators/force-index/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -44163,9 +44395,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -44342,9 +44574,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -44550,9 +44782,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -44784,9 +45016,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -45023,9 +45255,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/double-top/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -45262,9 +45494,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/double-bottom/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -45513,9 +45745,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/triple-top/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -45764,9 +45996,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/triple-bottom/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -46015,9 +46247,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/head-and-shoulders/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -46266,9 +46498,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -46653,9 +46885,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -47087,9 +47319,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -47521,9 +47753,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -47947,9 +48179,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -48334,9 +48566,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -48734,9 +48966,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -49104,9 +49336,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -49499,9 +49731,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -49685,9 +49917,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -49878,9 +50110,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50060,9 +50292,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50219,9 +50451,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50416,9 +50648,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50574,9 +50806,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50735,9 +50967,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -50916,9 +51148,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -51122,9 +51354,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -51289,9 +51521,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/acf/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -51477,9 +51709,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/pacf/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -51661,9 +51893,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/augmented-dickey-fuller/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -51852,9 +52084,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/kpss/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -52068,9 +52300,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/ljung-box/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -52289,9 +52521,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/diagnostics/zivot-andrews-break-test/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -52486,9 +52718,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/autoreg/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -52699,9 +52931,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/arma/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -52930,9 +53162,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/arima/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -53300,9 +53532,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/sarima-sarimax/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -53578,9 +53810,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/holt-winters/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -53768,9 +54000,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/forecast-models/theta-forecast/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -54028,9 +54260,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/multivariate-systems/var/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -54288,9 +54520,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/multivariate-systems/structural-var/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -54558,9 +54790,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/multivariate-systems/vecm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -54826,9 +55058,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/multivariate-systems/impulse-response-analysis/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -55099,9 +55331,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -55281,9 +55513,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/kalman-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -55466,9 +55698,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/extended-kalman-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -55655,9 +55887,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/unscented-kalman-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -55839,9 +56071,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/hidden-markov-model/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -56036,9 +56268,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/markov-switching-autoregression/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -56202,9 +56434,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -56468,9 +56700,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/stl-decomposition/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -56657,9 +56889,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -56890,9 +57122,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/baxter-king-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -57119,9 +57351,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -57342,9 +57574,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -57599,9 +57831,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/statistical-time-series/decomposition-and-cycles/wavelet-decomposition/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -57842,9 +58074,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/trade-classification/tick-test/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -58132,9 +58364,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/trade-classification/quote-test/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -58420,9 +58652,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/trade-classification/lee-ready-trade-signing/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -58667,9 +58899,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/trade-classification/bulk-volume-classification/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -58837,9 +59069,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/quoted-spread/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -59045,9 +59277,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/effective-spread/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -59291,9 +59523,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/realized-spread/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -59439,9 +59671,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/roll-spread-estimator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -59634,9 +59866,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -59829,9 +60061,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -60071,9 +60303,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/order-flow-imbalance/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -60323,9 +60555,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/queue-imbalance/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -60548,9 +60780,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/kyle-lambda/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -60765,9 +60997,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/hasbrouck-price-impact/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -61006,9 +61238,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/pin/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -61268,9 +61500,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-flow-and-impact/vpin/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -61475,9 +61707,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-book-dynamics/order-book-slope/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -61665,9 +61897,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-book-dynamics/depth-weighted-midprice/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -61843,9 +62075,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-book-dynamics/microprice/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -62032,9 +62264,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-book-dynamics/order-book-resiliency/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -62265,9 +62497,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/order-book-dynamics/hawkes-order-arrival-model/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -62499,9 +62731,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/cumulative-bid-ask-depth/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -62723,9 +62955,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/top-n-depth-imbalance/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -62971,9 +63203,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/depth-at-distance-profile/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -63222,9 +63454,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/expected-market-order-fill-price/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -63501,9 +63733,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -63716,9 +63948,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -63893,9 +64125,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/depth-depletion-and-replenishment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -64209,9 +64441,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -64417,9 +64649,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/continuous-matching/price-time-priority/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -64633,9 +64865,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/continuous-matching/pro-rata-matching/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -64859,9 +65091,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/continuous-matching/size-time-priority/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -65065,9 +65297,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -65295,9 +65527,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -65530,9 +65762,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -65805,9 +66037,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/auctions/opening-cross-price/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -66080,9 +66312,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/auctions/closing-cross-price/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -66251,9 +66483,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/auctions/volatility-auction-reopening/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -66428,9 +66660,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/tick-size-validation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -66633,9 +66865,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/price-band-validation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -66860,9 +67092,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/self-trade-prevention/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -67087,9 +67319,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/cancel-on-disconnect/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -67342,9 +67574,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/fat-finger-limit/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -67530,9 +67762,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -67741,9 +67973,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -67906,9 +68138,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -68100,9 +68332,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -68284,9 +68516,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -68516,9 +68748,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -68744,9 +68976,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -68956,9 +69188,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -69170,9 +69402,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -69431,9 +69663,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -69674,9 +69906,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -69840,9 +70072,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70025,9 +70257,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70176,9 +70408,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70372,9 +70604,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70581,9 +70813,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70781,9 +71013,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -70981,9 +71213,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -71214,9 +71446,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -71448,9 +71680,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -71649,9 +71881,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -71857,9 +72089,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -72086,9 +72318,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -72305,9 +72537,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -72512,9 +72744,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -72733,9 +72965,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -72927,9 +73159,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -73123,9 +73355,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -73292,9 +73524,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -73461,9 +73693,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] }, { @@ -73648,9 +73880,9 @@ "source": "https://github.com/IslamBaraka90/Fintech-Algorithms-Library/blob/main/src/earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion/impl.ts", "npm": "https://www.npmjs.com/package/fintech-algorithms" }, - "languages": [ - "typescript", - "python" + "catalogLanguages": [ + "python", + "typescript" ] } ] diff --git a/package.json b/package.json index 813ef91..55a3538 100644 --- a/package.json +++ b/package.json @@ -33,6 +33,7 @@ "dist", "src", "docs.json", + "CHANGELOG.md", "README.md", "LICENSE" ], @@ -54,1303 +55,1628 @@ "exports": { ".": { "types": "./dist/index.d.ts", - "import": "./dist/index.js" + "import": "./dist/index.js", + "require": "./dist/index.js" }, "./market-data-engineering/bar-construction/time-bars": { "types": "./dist/market-data-engineering/bar-construction/time-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/time-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/time-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/time-bars/index.js" }, "./market-data-engineering/bar-construction/tick-bars": { "types": "./dist/market-data-engineering/bar-construction/tick-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/tick-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/tick-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/tick-bars/index.js" }, "./market-data-engineering/bar-construction/volume-bars": { "types": "./dist/market-data-engineering/bar-construction/volume-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/volume-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/volume-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/volume-bars/index.js" }, "./market-data-engineering/bar-construction/dollar-bars": { "types": "./dist/market-data-engineering/bar-construction/dollar-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/dollar-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/dollar-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/dollar-bars/index.js" }, "./market-data-engineering/bar-construction/tick-imbalance-bars": { "types": "./dist/market-data-engineering/bar-construction/tick-imbalance-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/tick-imbalance-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/tick-imbalance-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/tick-imbalance-bars/index.js" }, "./market-data-engineering/bar-construction/volume-imbalance-bars": { "types": "./dist/market-data-engineering/bar-construction/volume-imbalance-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/volume-imbalance-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/volume-imbalance-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/volume-imbalance-bars/index.js" }, "./market-data-engineering/bar-construction/tick-run-bars": { "types": "./dist/market-data-engineering/bar-construction/tick-run-bars/index.d.ts", - "import": "./dist/market-data-engineering/bar-construction/tick-run-bars/index.js" + "import": "./dist/market-data-engineering/bar-construction/tick-run-bars/index.js", + "require": "./dist/market-data-engineering/bar-construction/tick-run-bars/index.js" }, "./market-data-engineering/cleaning-and-validation/ohlc-consistency-validator": { "types": "./dist/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator/index.js" }, "./market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter": { "types": "./dist/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/hampel-bad-tick-filter/index.js" }, "./market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter": { "types": "./dist/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter/index.js" }, "./market-data-engineering/cleaning-and-validation/stale-quote-detector": { "types": "./dist/market-data-engineering/cleaning-and-validation/stale-quote-detector/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/stale-quote-detector/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/stale-quote-detector/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/stale-quote-detector/index.js" }, "./market-data-engineering/cleaning-and-validation/duplicate-trade-resolver": { "types": "./dist/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver/index.js" }, "./market-data-engineering/cleaning-and-validation/crossed-locked-market-detector": { "types": "./dist/market-data-engineering/cleaning-and-validation/crossed-locked-market-detector/index.d.ts", - "import": "./dist/market-data-engineering/cleaning-and-validation/crossed-locked-market-detector/index.js" + "import": "./dist/market-data-engineering/cleaning-and-validation/crossed-locked-market-detector/index.js", + "require": "./dist/market-data-engineering/cleaning-and-validation/crossed-locked-market-detector/index.js" }, "./market-data-engineering/time-synchronization/previous-tick-interpolation": { "types": "./dist/market-data-engineering/time-synchronization/previous-tick-interpolation/index.d.ts", - "import": "./dist/market-data-engineering/time-synchronization/previous-tick-interpolation/index.js" + "import": "./dist/market-data-engineering/time-synchronization/previous-tick-interpolation/index.js", + "require": "./dist/market-data-engineering/time-synchronization/previous-tick-interpolation/index.js" }, "./market-data-engineering/time-synchronization/linear-quote-interpolation": { "types": "./dist/market-data-engineering/time-synchronization/linear-quote-interpolation/index.d.ts", - "import": "./dist/market-data-engineering/time-synchronization/linear-quote-interpolation/index.js" + "import": "./dist/market-data-engineering/time-synchronization/linear-quote-interpolation/index.js", + "require": "./dist/market-data-engineering/time-synchronization/linear-quote-interpolation/index.js" }, "./market-data-engineering/time-synchronization/refresh-time-sampling": { "types": "./dist/market-data-engineering/time-synchronization/refresh-time-sampling/index.d.ts", - "import": "./dist/market-data-engineering/time-synchronization/refresh-time-sampling/index.js" + "import": "./dist/market-data-engineering/time-synchronization/refresh-time-sampling/index.js", + "require": "./dist/market-data-engineering/time-synchronization/refresh-time-sampling/index.js" }, "./market-data-engineering/time-synchronization/exchange-calendar-alignment": { "types": "./dist/market-data-engineering/time-synchronization/exchange-calendar-alignment/index.d.ts", - "import": "./dist/market-data-engineering/time-synchronization/exchange-calendar-alignment/index.js" + "import": "./dist/market-data-engineering/time-synchronization/exchange-calendar-alignment/index.js", + "require": "./dist/market-data-engineering/time-synchronization/exchange-calendar-alignment/index.js" }, "./market-data-engineering/time-synchronization/asynchronous-return-alignment": { "types": "./dist/market-data-engineering/time-synchronization/asynchronous-return-alignment/index.d.ts", - "import": "./dist/market-data-engineering/time-synchronization/asynchronous-return-alignment/index.js" + "import": "./dist/market-data-engineering/time-synchronization/asynchronous-return-alignment/index.js", + "require": "./dist/market-data-engineering/time-synchronization/asynchronous-return-alignment/index.js" }, "./market-data-engineering/data-quality/missing-bar-gap-classifier": { "types": "./dist/market-data-engineering/data-quality/missing-bar-gap-classifier/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/missing-bar-gap-classifier/index.js" + "import": "./dist/market-data-engineering/data-quality/missing-bar-gap-classifier/index.js", + "require": "./dist/market-data-engineering/data-quality/missing-bar-gap-classifier/index.js" }, "./market-data-engineering/data-quality/feed-latency-monitor": { "types": "./dist/market-data-engineering/data-quality/feed-latency-monitor/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/feed-latency-monitor/index.js" + "import": "./dist/market-data-engineering/data-quality/feed-latency-monitor/index.js", + "require": "./dist/market-data-engineering/data-quality/feed-latency-monitor/index.js" }, "./market-data-engineering/data-quality/price-source-consensus-check": { "types": "./dist/market-data-engineering/data-quality/price-source-consensus-check/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/price-source-consensus-check/index.js" + "import": "./dist/market-data-engineering/data-quality/price-source-consensus-check/index.js", + "require": "./dist/market-data-engineering/data-quality/price-source-consensus-check/index.js" }, "./market-data-engineering/data-quality/schema-drift-detector": { "types": "./dist/market-data-engineering/data-quality/schema-drift-detector/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/schema-drift-detector/index.js" + "import": "./dist/market-data-engineering/data-quality/schema-drift-detector/index.js", + "require": "./dist/market-data-engineering/data-quality/schema-drift-detector/index.js" }, "./market-data-engineering/data-quality/point-in-time-availability-guard": { "types": "./dist/market-data-engineering/data-quality/point-in-time-availability-guard/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/point-in-time-availability-guard/index.js" + "import": "./dist/market-data-engineering/data-quality/point-in-time-availability-guard/index.js", + "require": "./dist/market-data-engineering/data-quality/point-in-time-availability-guard/index.js" }, "./market-data-engineering/data-quality/provider-adjustment-basis-drift-detector": { "types": "./dist/market-data-engineering/data-quality/provider-adjustment-basis-drift-detector/index.d.ts", - "import": "./dist/market-data-engineering/data-quality/provider-adjustment-basis-drift-detector/index.js" + "import": "./dist/market-data-engineering/data-quality/provider-adjustment-basis-drift-detector/index.js", + "require": "./dist/market-data-engineering/data-quality/provider-adjustment-basis-drift-detector/index.js" }, "./market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization": { "types": "./dist/market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/trade-and-quote-event-normalization/index.js" }, "./market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction": { "types": "./dist/market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/level-2-snapshot-and-delta-reconstruction/index.js" }, "./market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction": { "types": "./dist/market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/level-3-order-by-order-reconstruction/index.js" }, "./market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery": { "types": "./dist/market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/sequence-gap-detection-and-recovery/index.js" }, "./market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation": { "types": "./dist/market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/price-level-quantity-aggregation/index.js" }, "./market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation": { "types": "./dist/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/snapshot-incremental-feed-reconciliation/index.js" }, "./market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation": { "types": "./dist/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/index.d.ts", - "import": "./dist/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/index.js" + "import": "./dist/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/index.js", + "require": "./dist/market-data-engineering/order-book-feed-engineering/multi-venue-best-quote-and-book-consolidation/index.js" }, "./corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/adjustment-factors/backward-split-adjustment/index.js" }, "./corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/adjustment-factors/forward-split-adjustment/index.js" }, "./corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/adjustment-factors/cash-dividend-total-return-adjustment/index.js" }, "./corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-price-adjustment/index.js" }, "./corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/adjustment-factors/crsp-cumulative-share-volume-adjustment/index.js" }, "./corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/complex-distributions/rights-issue-terp-adjustment/index.js" }, "./corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/complex-distributions/spin-off-price-adjustment/index.js" }, "./corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/complex-distributions/stock-dividend-adjustment/index.js" }, "./corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/complex-distributions/special-dividend-adjustment/index.js" }, "./corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment": { "types": "./dist/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/index.js" + "import": "./dist/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/index.js", + "require": "./dist/corporate-actions-and-security-master-data/complex-distributions/return-of-capital-adjustment/index.js" }, "./corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping": { "types": "./dist/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/index.js" + "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/index.js", + "require": "./dist/corporate-actions-and-security-master-data/identity-continuity/permanent-security-identifier-mapping/index.js" }, "./corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution": { "types": "./dist/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/index.js" + "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/index.js", + "require": "./dist/corporate-actions-and-security-master-data/identity-continuity/ticker-change-chain-resolution/index.js" }, "./corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping": { "types": "./dist/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/index.js" + "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/index.js", + "require": "./dist/corporate-actions-and-security-master-data/identity-continuity/share-class-relationship-mapping/index.js" }, "./corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping": { "types": "./dist/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/index.js" + "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/index.js", + "require": "./dist/corporate-actions-and-security-master-data/identity-continuity/merger-predecessor-successor-mapping/index.js" }, "./corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction": { "types": "./dist/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/index.js" + "import": "./dist/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/index.js", + "require": "./dist/corporate-actions-and-security-master-data/identity-continuity/delisting-return-reconstruction/index.js" }, "./corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction": { "types": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/index.js" + "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/index.js", + "require": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/historical-constituent-reconstruction/index.js" }, "./corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard": { "types": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/index.js" + "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/index.js", + "require": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/survivorship-bias-guard/index.js" }, "./corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping": { "types": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/index.js" + "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/index.js", + "require": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/ipo-availability-timestamping/index.js" }, "./corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning": { "types": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/index.js" + "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/index.js", + "require": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/filing-revision-versioning/index.js" }, "./corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation": { "types": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/index.d.ts", - "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/index.js" + "import": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/index.js", + "require": "./dist/corporate-actions-and-security-master-data/point-in-time-universe/corporate-action-status-and-effective-date-reconciliation/index.js" }, "./index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization": { "types": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/index.js" + "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/index.js", + "require": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/base-date-base-value-initialization/index.js" }, "./index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization": { "types": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/index.js" + "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/index.js", + "require": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/index-divisor-initialization/index.js" }, "./index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment": { "types": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment/index.js" + "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment/index.js", + "require": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/divisor-continuity-adjustment/index.js" }, "./index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge": { "types": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge/index.js" + "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge/index.js", + "require": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/corporate-action-divisor-bridge/index.js" }, "./index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation": { "types": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation/index.js" + "import": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation/index.js", + "require": "./dist/index-and-benchmark-engineering/index-initialization-and-continuity/intraday-index-level-calculation/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/price-weighted-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/price-weighted-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/price-weighted-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/price-weighted-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/price-weighted-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/total-market-cap-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/free-float-market-cap-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/capped-free-float-market-cap-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/modified-market-cap-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/equal-weight-index": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/equal-weight-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/equal-weight-index/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/equal-weight-index/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/equal-weight-index/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/iterative-cap-redistribution/index.js" }, "./index-and-benchmark-engineering/weighting-and-capping/group-level-capping": { "types": "./dist/index-and-benchmark-engineering/weighting-and-capping/group-level-capping/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/group-level-capping/index.js" + "import": "./dist/index-and-benchmark-engineering/weighting-and-capping/group-level-capping/index.js", + "require": "./dist/index-and-benchmark-engineering/weighting-and-capping/group-level-capping/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/fundamental-weighted-index/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/dividend-yield-weighted-index/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/factor-score-weighted-index/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/minimum-volatility-index/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/equal-risk-contribution-index/index.js" }, "./index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index": { "types": "./dist/index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index/index.js" + "import": "./dist/index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index/index.js", + "require": "./dist/index-and-benchmark-engineering/alternative-weighting/thematic-tilt-index/index.js" }, "./index-and-benchmark-engineering/return-variants/price-return-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/price-return-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/price-return-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/price-return-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/price-return-index/index.js" }, "./index-and-benchmark-engineering/return-variants/gross-total-return-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/gross-total-return-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/gross-total-return-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/gross-total-return-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/gross-total-return-index/index.js" }, "./index-and-benchmark-engineering/return-variants/net-total-return-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/net-total-return-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/net-total-return-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/net-total-return-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/net-total-return-index/index.js" }, "./index-and-benchmark-engineering/return-variants/excess-return-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/excess-return-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/excess-return-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/excess-return-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/excess-return-index/index.js" }, "./index-and-benchmark-engineering/return-variants/dividend-point-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/dividend-point-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/dividend-point-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/dividend-point-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/dividend-point-index/index.js" }, "./index-and-benchmark-engineering/return-variants/currency-converted-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/currency-converted-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/currency-converted-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/currency-converted-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/currency-converted-index/index.js" }, "./index-and-benchmark-engineering/return-variants/currency-hedged-index": { "types": "./dist/index-and-benchmark-engineering/return-variants/currency-hedged-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/return-variants/currency-hedged-index/index.js" + "import": "./dist/index-and-benchmark-engineering/return-variants/currency-hedged-index/index.js", + "require": "./dist/index-and-benchmark-engineering/return-variants/currency-hedged-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/leveraged-daily-reset-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/inverse-daily-reset-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/volatility-control-index": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/volatility-control-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/volatility-control-index/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/volatility-control-index/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/volatility-control-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/fixed-decrement-index": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/fixed-decrement-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/fixed-decrement-index/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/fixed-decrement-index/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/fixed-decrement-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/percentage-decrement-index": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/percentage-decrement-index/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/percentage-decrement-index/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/percentage-decrement-index/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/percentage-decrement-index/index.js" }, "./index-and-benchmark-engineering/strategy-indices/index-of-indices": { "types": "./dist/index-and-benchmark-engineering/strategy-indices/index-of-indices/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/strategy-indices/index-of-indices/index.js" + "import": "./dist/index-and-benchmark-engineering/strategy-indices/index-of-indices/index.js", + "require": "./dist/index-and-benchmark-engineering/strategy-indices/index-of-indices/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/eligibility-screen/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/liquidity-screen/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/free-float-factor-calculation/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/ipo-fast-entry-rule/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/reconstitution-algorithm/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/rebalancing-algorithm/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/turnover-buffer-rule/index.js" }, "./index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator": { "types": "./dist/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/index.d.ts", - "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/index.js" + "import": "./dist/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/index.js", + "require": "./dist/index-and-benchmark-engineering/governance-and-maintenance/index-replication-cost-estimator/index.js" }, "./market-breadth-and-internals/advance-decline-breadth/net-advances": { "types": "./dist/market-breadth-and-internals/advance-decline-breadth/net-advances/index.d.ts", - "import": "./dist/market-breadth-and-internals/advance-decline-breadth/net-advances/index.js" + "import": "./dist/market-breadth-and-internals/advance-decline-breadth/net-advances/index.js", + "require": "./dist/market-breadth-and-internals/advance-decline-breadth/net-advances/index.js" }, "./market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio": { "types": "./dist/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/index.d.ts", - "import": "./dist/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/index.js" + "import": "./dist/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/index.js", + "require": "./dist/market-breadth-and-internals/advance-decline-breadth/advance-decline-ratio/index.js" }, "./market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line": { "types": "./dist/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/index.d.ts", - "import": "./dist/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/index.js" + "import": "./dist/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/index.js", + "require": "./dist/market-breadth-and-internals/advance-decline-breadth/cumulative-advance-decline-line/index.js" }, "./market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line": { "types": "./dist/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/index.d.ts", - "import": "./dist/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/index.js" + "import": "./dist/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/index.js", + "require": "./dist/market-breadth-and-internals/advance-decline-breadth/normalized-advance-decline-line/index.js" }, "./market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index": { "types": "./dist/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/index.js" + "import": "./dist/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/index.js", + "require": "./dist/market-breadth-and-internals/advance-decline-breadth/absolute-breadth-index/index.js" }, "./market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator": { "types": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-oscillator/index.js" }, "./market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator": { "types": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-mcclellan-oscillator/index.js" }, "./market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index": { "types": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/traditional-mcclellan-summation-index/index.js" }, "./market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi": { "types": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/ratio-adjusted-summation-index-rasi/index.js" }, "./market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator": { "types": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-oscillator/index.js" }, "./market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index": { "types": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/index.js" + "import": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/index.js", + "require": "./dist/market-breadth-and-internals/mcclellan-family/mcclellan-volume-summation-index/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/new-highs-new-lows/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-ratio/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/high-low-index": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/high-low-index/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-20-day-ma/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-50-day-ma/index.js" }, "./market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma": { "types": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/index.d.ts", - "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/index.js" + "import": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/index.js", + "require": "./dist/market-breadth-and-internals/high-low-and-trend-breadth/percent-above-200-day-ma/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/zweig-breadth-thrust/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/arms-index-trin": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/arms-index-trin/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/advance-decline-volume-line/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/upside-downside-volume-ratio/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/cumulative-tick": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/cumulative-tick/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/cumulative-tick/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/cumulative-tick/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/cumulative-tick/index.js" }, "./market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector": { "types": "./dist/market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector/index.d.ts", - "import": "./dist/market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector/index.js" + "import": "./dist/market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector/index.js", + "require": "./dist/market-breadth-and-internals/thrust-and-pressure/breadth-divergence-detector/index.js" }, "./market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution": { "types": "./dist/market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution/index.d.ts", - "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution/index.js" + "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution/index.js", + "require": "./dist/market-breadth-and-internals/concentration-and-diffusion/top-n-index-contribution/index.js" }, "./market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration": { "types": "./dist/market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration/index.d.ts", - "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration/index.js" + "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration/index.js", + "require": "./dist/market-breadth-and-internals/concentration-and-diffusion/herfindahl-constituent-concentration/index.js" }, "./market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents": { "types": "./dist/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/index.d.ts", - "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/index.js" + "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/index.js", + "require": "./dist/market-breadth-and-internals/concentration-and-diffusion/effective-number-of-constituents/index.js" }, "./market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index": { "types": "./dist/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/index.js" + "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/index.js", + "require": "./dist/market-breadth-and-internals/concentration-and-diffusion/sector-diffusion-index/index.js" }, "./market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index": { "types": "./dist/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/index.d.ts", - "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/index.js" + "import": "./dist/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/index.js", + "require": "./dist/market-breadth-and-internals/concentration-and-diffusion/factor-diffusion-index/index.js" }, "./price-action-and-candlesticks/candle-foundations/candle-anatomy": { "types": "./dist/price-action-and-candlesticks/candle-foundations/candle-anatomy/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candle-foundations/candle-anatomy/index.js" + "import": "./dist/price-action-and-candlesticks/candle-foundations/candle-anatomy/index.js", + "require": "./dist/price-action-and-candlesticks/candle-foundations/candle-anatomy/index.js" }, "./price-action-and-candlesticks/candle-foundations/scale-aware-body-classification": { "types": "./dist/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/index.js" + "import": "./dist/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/index.js", + "require": "./dist/price-action-and-candlesticks/candle-foundations/scale-aware-body-classification/index.js" }, "./price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio": { "types": "./dist/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/index.js" + "import": "./dist/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/index.js", + "require": "./dist/price-action-and-candlesticks/candle-foundations/shadow-to-body-ratio/index.js" }, "./price-action-and-candlesticks/candle-foundations/gap-classification": { "types": "./dist/price-action-and-candlesticks/candle-foundations/gap-classification/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candle-foundations/gap-classification/index.js" + "import": "./dist/price-action-and-candlesticks/candle-foundations/gap-classification/index.js", + "require": "./dist/price-action-and-candlesticks/candle-foundations/gap-classification/index.js" }, "./price-action-and-candlesticks/candle-foundations/trend-context-filter": { "types": "./dist/price-action-and-candlesticks/candle-foundations/trend-context-filter/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candle-foundations/trend-context-filter/index.js" + "import": "./dist/price-action-and-candlesticks/candle-foundations/trend-context-filter/index.js", + "require": "./dist/price-action-and-candlesticks/candle-foundations/trend-context-filter/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/doji": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/doji/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/doji/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/doji/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/doji/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/dragonfly-doji": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/dragonfly-doji/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/dragonfly-doji/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/dragonfly-doji/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/dragonfly-doji/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/gravestone-doji": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/gravestone-doji/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/gravestone-doji/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/gravestone-doji/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/gravestone-doji/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/marubozu": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/marubozu/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/marubozu/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/marubozu/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/marubozu/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/spinning-top": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/spinning-top/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/spinning-top/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/spinning-top/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/spinning-top/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/hammer": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/hammer/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/hammer/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/hammer/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/hammer/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/hanging-man": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/hanging-man/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/hanging-man/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/hanging-man/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/hanging-man/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/inverted-hammer": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/inverted-hammer/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/inverted-hammer/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/inverted-hammer/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/inverted-hammer/index.js" }, "./price-action-and-candlesticks/single-candle-patterns/shooting-star": { "types": "./dist/price-action-and-candlesticks/single-candle-patterns/shooting-star/index.d.ts", - "import": "./dist/price-action-and-candlesticks/single-candle-patterns/shooting-star/index.js" + "import": "./dist/price-action-and-candlesticks/single-candle-patterns/shooting-star/index.js", + "require": "./dist/price-action-and-candlesticks/single-candle-patterns/shooting-star/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/bullish-engulfing": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-engulfing/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-engulfing/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-engulfing/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-engulfing/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/bearish-engulfing": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-engulfing/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-engulfing/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-engulfing/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-engulfing/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/bullish-harami": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-harami/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-harami/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-harami/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/bullish-harami/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/bearish-harami": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-harami/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-harami/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-harami/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/bearish-harami/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/piercing-line": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/piercing-line/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/piercing-line/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/piercing-line/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/piercing-line/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/dark-cloud-cover/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/tweezer-top": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-top/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-top/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-top/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-top/index.js" }, "./price-action-and-candlesticks/two-candle-patterns/tweezer-bottom": { "types": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-bottom/index.d.ts", - "import": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-bottom/index.js" + "import": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-bottom/index.js", + "require": "./dist/price-action-and-candlesticks/two-candle-patterns/tweezer-bottom/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/morning-star": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/morning-star/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/morning-star/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/morning-star/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/morning-star/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/evening-star": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/evening-star/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/evening-star/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/evening-star/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/evening-star/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-white-soldiers/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/three-black-crows": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-black-crows/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-black-crows/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-black-crows/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-black-crows/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-inside-up-down/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/three-outside-up-down/index.js" }, "./price-action-and-candlesticks/multi-candle-patterns/abandoned-baby": { "types": "./dist/price-action-and-candlesticks/multi-candle-patterns/abandoned-baby/index.d.ts", - "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/abandoned-baby/index.js" + "import": "./dist/price-action-and-candlesticks/multi-candle-patterns/abandoned-baby/index.js", + "require": "./dist/price-action-and-candlesticks/multi-candle-patterns/abandoned-baby/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/unified-candlestick-pattern-registry/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-pattern-occurrence-contract/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/market-wide-candlestick-pattern-scanner/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/contextual-candlestick-confidence-score/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/support-resistance-pattern-context/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/trend-volatility-and-volume-pattern-context/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/overlapping-pattern-conflict-resolver/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-confirmation-and-invalidation-state-machine/index.js" }, "./price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication": { "types": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/index.d.ts", - "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/index.js" + "import": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/index.js", + "require": "./dist/price-action-and-candlesticks/candlestick-scanning-and-context/candlestick-scanner-ranking-and-deduplication/index.js" }, "./technical-indicators/trend-smoothing/sma": { "types": "./dist/technical-indicators/trend-smoothing/sma/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/sma/index.js" + "import": "./dist/technical-indicators/trend-smoothing/sma/index.js", + "require": "./dist/technical-indicators/trend-smoothing/sma/index.js" }, "./technical-indicators/trend-smoothing/ema": { "types": "./dist/technical-indicators/trend-smoothing/ema/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/ema/index.js" + "import": "./dist/technical-indicators/trend-smoothing/ema/index.js", + "require": "./dist/technical-indicators/trend-smoothing/ema/index.js" }, "./technical-indicators/trend-smoothing/wma": { "types": "./dist/technical-indicators/trend-smoothing/wma/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/wma/index.js" + "import": "./dist/technical-indicators/trend-smoothing/wma/index.js", + "require": "./dist/technical-indicators/trend-smoothing/wma/index.js" }, "./technical-indicators/trend-smoothing/wilder-rma": { "types": "./dist/technical-indicators/trend-smoothing/wilder-rma/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/wilder-rma/index.js" + "import": "./dist/technical-indicators/trend-smoothing/wilder-rma/index.js", + "require": "./dist/technical-indicators/trend-smoothing/wilder-rma/index.js" }, "./technical-indicators/trend-smoothing/dema": { "types": "./dist/technical-indicators/trend-smoothing/dema/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/dema/index.js" + "import": "./dist/technical-indicators/trend-smoothing/dema/index.js", + "require": "./dist/technical-indicators/trend-smoothing/dema/index.js" }, "./technical-indicators/trend-smoothing/tema": { "types": "./dist/technical-indicators/trend-smoothing/tema/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/tema/index.js" + "import": "./dist/technical-indicators/trend-smoothing/tema/index.js", + "require": "./dist/technical-indicators/trend-smoothing/tema/index.js" }, "./technical-indicators/trend-smoothing/hull-ma": { "types": "./dist/technical-indicators/trend-smoothing/hull-ma/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/hull-ma/index.js" + "import": "./dist/technical-indicators/trend-smoothing/hull-ma/index.js", + "require": "./dist/technical-indicators/trend-smoothing/hull-ma/index.js" }, "./technical-indicators/trend-smoothing/kama": { "types": "./dist/technical-indicators/trend-smoothing/kama/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/kama/index.js" + "import": "./dist/technical-indicators/trend-smoothing/kama/index.js", + "require": "./dist/technical-indicators/trend-smoothing/kama/index.js" }, "./technical-indicators/trend-smoothing/mama": { "types": "./dist/technical-indicators/trend-smoothing/mama/index.d.ts", - "import": "./dist/technical-indicators/trend-smoothing/mama/index.js" + "import": "./dist/technical-indicators/trend-smoothing/mama/index.js", + "require": "./dist/technical-indicators/trend-smoothing/mama/index.js" }, "./technical-indicators/trend-systems/macd": { "types": "./dist/technical-indicators/trend-systems/macd/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/macd/index.js" + "import": "./dist/technical-indicators/trend-systems/macd/index.js", + "require": "./dist/technical-indicators/trend-systems/macd/index.js" }, "./technical-indicators/trend-systems/percentage-price-oscillator": { "types": "./dist/technical-indicators/trend-systems/percentage-price-oscillator/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/percentage-price-oscillator/index.js" + "import": "./dist/technical-indicators/trend-systems/percentage-price-oscillator/index.js", + "require": "./dist/technical-indicators/trend-systems/percentage-price-oscillator/index.js" }, "./technical-indicators/trend-systems/aroon": { "types": "./dist/technical-indicators/trend-systems/aroon/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/aroon/index.js" + "import": "./dist/technical-indicators/trend-systems/aroon/index.js", + "require": "./dist/technical-indicators/trend-systems/aroon/index.js" }, "./technical-indicators/trend-systems/directional-movement": { "types": "./dist/technical-indicators/trend-systems/directional-movement/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/directional-movement/index.js" + "import": "./dist/technical-indicators/trend-systems/directional-movement/index.js", + "require": "./dist/technical-indicators/trend-systems/directional-movement/index.js" }, "./technical-indicators/trend-systems/adx": { "types": "./dist/technical-indicators/trend-systems/adx/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/adx/index.js" + "import": "./dist/technical-indicators/trend-systems/adx/index.js", + "require": "./dist/technical-indicators/trend-systems/adx/index.js" }, "./technical-indicators/trend-systems/ichimoku-cloud": { "types": "./dist/technical-indicators/trend-systems/ichimoku-cloud/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/ichimoku-cloud/index.js" + "import": "./dist/technical-indicators/trend-systems/ichimoku-cloud/index.js", + "require": "./dist/technical-indicators/trend-systems/ichimoku-cloud/index.js" }, "./technical-indicators/trend-systems/parabolic-sar": { "types": "./dist/technical-indicators/trend-systems/parabolic-sar/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/parabolic-sar/index.js" + "import": "./dist/technical-indicators/trend-systems/parabolic-sar/index.js", + "require": "./dist/technical-indicators/trend-systems/parabolic-sar/index.js" }, "./technical-indicators/trend-systems/supertrend": { "types": "./dist/technical-indicators/trend-systems/supertrend/index.d.ts", - "import": "./dist/technical-indicators/trend-systems/supertrend/index.js" + "import": "./dist/technical-indicators/trend-systems/supertrend/index.js", + "require": "./dist/technical-indicators/trend-systems/supertrend/index.js" }, "./technical-indicators/momentum/rsi": { "types": "./dist/technical-indicators/momentum/rsi/index.d.ts", - "import": "./dist/technical-indicators/momentum/rsi/index.js" + "import": "./dist/technical-indicators/momentum/rsi/index.js", + "require": "./dist/technical-indicators/momentum/rsi/index.js" }, "./technical-indicators/momentum/stochastic-oscillator": { "types": "./dist/technical-indicators/momentum/stochastic-oscillator/index.d.ts", - "import": "./dist/technical-indicators/momentum/stochastic-oscillator/index.js" + "import": "./dist/technical-indicators/momentum/stochastic-oscillator/index.js", + "require": "./dist/technical-indicators/momentum/stochastic-oscillator/index.js" }, "./technical-indicators/momentum/stochastic-rsi": { "types": "./dist/technical-indicators/momentum/stochastic-rsi/index.d.ts", - "import": "./dist/technical-indicators/momentum/stochastic-rsi/index.js" + "import": "./dist/technical-indicators/momentum/stochastic-rsi/index.js", + "require": "./dist/technical-indicators/momentum/stochastic-rsi/index.js" }, "./technical-indicators/momentum/williams-r": { "types": "./dist/technical-indicators/momentum/williams-r/index.d.ts", - "import": "./dist/technical-indicators/momentum/williams-r/index.js" + "import": "./dist/technical-indicators/momentum/williams-r/index.js", + "require": "./dist/technical-indicators/momentum/williams-r/index.js" }, "./technical-indicators/momentum/cci": { "types": "./dist/technical-indicators/momentum/cci/index.d.ts", - "import": "./dist/technical-indicators/momentum/cci/index.js" + "import": "./dist/technical-indicators/momentum/cci/index.js", + "require": "./dist/technical-indicators/momentum/cci/index.js" }, "./technical-indicators/momentum/ultimate-oscillator": { "types": "./dist/technical-indicators/momentum/ultimate-oscillator/index.d.ts", - "import": "./dist/technical-indicators/momentum/ultimate-oscillator/index.js" + "import": "./dist/technical-indicators/momentum/ultimate-oscillator/index.js", + "require": "./dist/technical-indicators/momentum/ultimate-oscillator/index.js" }, "./technical-indicators/momentum/tsi": { "types": "./dist/technical-indicators/momentum/tsi/index.d.ts", - "import": "./dist/technical-indicators/momentum/tsi/index.js" + "import": "./dist/technical-indicators/momentum/tsi/index.js", + "require": "./dist/technical-indicators/momentum/tsi/index.js" }, "./technical-indicators/momentum/connors-rsi": { "types": "./dist/technical-indicators/momentum/connors-rsi/index.d.ts", - "import": "./dist/technical-indicators/momentum/connors-rsi/index.js" + "import": "./dist/technical-indicators/momentum/connors-rsi/index.js", + "require": "./dist/technical-indicators/momentum/connors-rsi/index.js" }, "./technical-indicators/volatility-and-channels/true-range": { "types": "./dist/technical-indicators/volatility-and-channels/true-range/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/true-range/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/true-range/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/true-range/index.js" }, "./technical-indicators/volatility-and-channels/atr": { "types": "./dist/technical-indicators/volatility-and-channels/atr/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/atr/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/atr/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/atr/index.js" }, "./technical-indicators/volatility-and-channels/bollinger-bands": { "types": "./dist/technical-indicators/volatility-and-channels/bollinger-bands/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/bollinger-bands/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/bollinger-bands/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/bollinger-bands/index.js" }, "./technical-indicators/volatility-and-channels/keltner-channels": { "types": "./dist/technical-indicators/volatility-and-channels/keltner-channels/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/keltner-channels/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/keltner-channels/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/keltner-channels/index.js" }, "./technical-indicators/volatility-and-channels/donchian-channels": { "types": "./dist/technical-indicators/volatility-and-channels/donchian-channels/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/donchian-channels/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/donchian-channels/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/donchian-channels/index.js" }, "./technical-indicators/volatility-and-channels/bollinger-bandwidth": { "types": "./dist/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.d.ts", - "import": "./dist/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.js" + "import": "./dist/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.js", + "require": "./dist/technical-indicators/volatility-and-channels/bollinger-bandwidth/index.js" }, "./technical-indicators/volume-indicators/obv": { "types": "./dist/technical-indicators/volume-indicators/obv/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/obv/index.js" + "import": "./dist/technical-indicators/volume-indicators/obv/index.js", + "require": "./dist/technical-indicators/volume-indicators/obv/index.js" }, "./technical-indicators/volume-indicators/accumulation-distribution-line": { "types": "./dist/technical-indicators/volume-indicators/accumulation-distribution-line/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/accumulation-distribution-line/index.js" + "import": "./dist/technical-indicators/volume-indicators/accumulation-distribution-line/index.js", + "require": "./dist/technical-indicators/volume-indicators/accumulation-distribution-line/index.js" }, "./technical-indicators/volume-indicators/chaikin-money-flow": { "types": "./dist/technical-indicators/volume-indicators/chaikin-money-flow/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/chaikin-money-flow/index.js" + "import": "./dist/technical-indicators/volume-indicators/chaikin-money-flow/index.js", + "require": "./dist/technical-indicators/volume-indicators/chaikin-money-flow/index.js" }, "./technical-indicators/volume-indicators/money-flow-index": { "types": "./dist/technical-indicators/volume-indicators/money-flow-index/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/money-flow-index/index.js" + "import": "./dist/technical-indicators/volume-indicators/money-flow-index/index.js", + "require": "./dist/technical-indicators/volume-indicators/money-flow-index/index.js" }, "./technical-indicators/volume-indicators/volume-price-trend": { "types": "./dist/technical-indicators/volume-indicators/volume-price-trend/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/volume-price-trend/index.js" + "import": "./dist/technical-indicators/volume-indicators/volume-price-trend/index.js", + "require": "./dist/technical-indicators/volume-indicators/volume-price-trend/index.js" }, "./technical-indicators/volume-indicators/force-index": { "types": "./dist/technical-indicators/volume-indicators/force-index/index.d.ts", - "import": "./dist/technical-indicators/volume-indicators/force-index/index.js" + "import": "./dist/technical-indicators/volume-indicators/force-index/index.js", + "require": "./dist/technical-indicators/volume-indicators/force-index/index.js" }, "./geometric-chart-patterns/pivots-and-levels/causal-pivot-detection": { "types": "./dist/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/index.d.ts", - "import": "./dist/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/index.js" + "import": "./dist/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/index.js", + "require": "./dist/geometric-chart-patterns/pivots-and-levels/causal-pivot-detection/index.js" }, "./geometric-chart-patterns/pivots-and-levels/zigzag-segmentation": { "types": "./dist/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/index.d.ts", - "import": "./dist/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/index.js" + "import": "./dist/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/index.js", + "require": "./dist/geometric-chart-patterns/pivots-and-levels/zigzag-segmentation/index.js" }, "./geometric-chart-patterns/pivots-and-levels/support-resistance-clustering": { "types": "./dist/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/index.d.ts", - "import": "./dist/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/index.js" + "import": "./dist/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/index.js", + "require": "./dist/geometric-chart-patterns/pivots-and-levels/support-resistance-clustering/index.js" }, "./geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting": { "types": "./dist/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/index.d.ts", - "import": "./dist/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/index.js" + "import": "./dist/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/index.js", + "require": "./dist/geometric-chart-patterns/pivots-and-levels/robust-trendline-fitting/index.js" }, "./geometric-chart-patterns/reversal-structures/double-top": { "types": "./dist/geometric-chart-patterns/reversal-structures/double-top/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/double-top/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/double-top/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/double-top/index.js" }, "./geometric-chart-patterns/reversal-structures/double-bottom": { "types": "./dist/geometric-chart-patterns/reversal-structures/double-bottom/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/double-bottom/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/double-bottom/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/double-bottom/index.js" }, "./geometric-chart-patterns/reversal-structures/triple-top": { "types": "./dist/geometric-chart-patterns/reversal-structures/triple-top/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/triple-top/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/triple-top/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/triple-top/index.js" }, "./geometric-chart-patterns/reversal-structures/triple-bottom": { "types": "./dist/geometric-chart-patterns/reversal-structures/triple-bottom/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/triple-bottom/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/triple-bottom/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/triple-bottom/index.js" }, "./geometric-chart-patterns/reversal-structures/head-and-shoulders": { "types": "./dist/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/head-and-shoulders/index.js" }, "./geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders": { "types": "./dist/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.d.ts", - "import": "./dist/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.js" + "import": "./dist/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.js", + "require": "./dist/geometric-chart-patterns/reversal-structures/inverse-head-and-shoulders/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/price-indicator-pivot-alignment/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/regular-bullish-bearish-divergence-detection/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/hidden-bullish-bearish-divergence-detection/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-adapters/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-strength-and-quality-scoring/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/divergence-confirmation-and-invalidation-state-machine/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/multi-indicator-divergence-confluence/index.js" }, "./geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking": { "types": "./dist/geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking/index.d.ts", - "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking/index.js" + "import": "./dist/geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking/index.js", + "require": "./dist/geometric-chart-patterns/indicator-divergence-detection/market-wide-divergence-scanner-and-ranking/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/price-by-volume-profile-construction/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/poc-value-area-hvn-lvn-detection/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/fibonacci-retracement-extension-projection/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/psychological-round-number-level-generation/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/multi-source-support-resistance-zone-fusion/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-zone-strength-decay-scoring/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/support-resistance-role-reversal-state-machine/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/breakout-and-retest-detection/index.js" }, "./geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking": { "types": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking/index.d.ts", - "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking/index.js" + "import": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking/index.js", + "require": "./dist/geometric-chart-patterns/level-confluence-and-zone-scoring/market-wide-zone-proximity-scanner-ranking/index.js" }, "./statistical-time-series/diagnostics/acf": { "types": "./dist/statistical-time-series/diagnostics/acf/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/acf/index.js" + "import": "./dist/statistical-time-series/diagnostics/acf/index.js", + "require": "./dist/statistical-time-series/diagnostics/acf/index.js" }, "./statistical-time-series/diagnostics/pacf": { "types": "./dist/statistical-time-series/diagnostics/pacf/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/pacf/index.js" + "import": "./dist/statistical-time-series/diagnostics/pacf/index.js", + "require": "./dist/statistical-time-series/diagnostics/pacf/index.js" }, "./statistical-time-series/diagnostics/augmented-dickey-fuller": { "types": "./dist/statistical-time-series/diagnostics/augmented-dickey-fuller/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/augmented-dickey-fuller/index.js" + "import": "./dist/statistical-time-series/diagnostics/augmented-dickey-fuller/index.js", + "require": "./dist/statistical-time-series/diagnostics/augmented-dickey-fuller/index.js" }, "./statistical-time-series/diagnostics/kpss": { "types": "./dist/statistical-time-series/diagnostics/kpss/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/kpss/index.js" + "import": "./dist/statistical-time-series/diagnostics/kpss/index.js", + "require": "./dist/statistical-time-series/diagnostics/kpss/index.js" }, "./statistical-time-series/diagnostics/ljung-box": { "types": "./dist/statistical-time-series/diagnostics/ljung-box/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/ljung-box/index.js" + "import": "./dist/statistical-time-series/diagnostics/ljung-box/index.js", + "require": "./dist/statistical-time-series/diagnostics/ljung-box/index.js" }, "./statistical-time-series/diagnostics/zivot-andrews-break-test": { "types": "./dist/statistical-time-series/diagnostics/zivot-andrews-break-test/index.d.ts", - "import": "./dist/statistical-time-series/diagnostics/zivot-andrews-break-test/index.js" + "import": "./dist/statistical-time-series/diagnostics/zivot-andrews-break-test/index.js", + "require": "./dist/statistical-time-series/diagnostics/zivot-andrews-break-test/index.js" }, "./statistical-time-series/forecast-models/autoreg": { "types": "./dist/statistical-time-series/forecast-models/autoreg/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/autoreg/index.js" + "import": "./dist/statistical-time-series/forecast-models/autoreg/index.js", + "require": "./dist/statistical-time-series/forecast-models/autoreg/index.js" }, "./statistical-time-series/forecast-models/arma": { "types": "./dist/statistical-time-series/forecast-models/arma/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/arma/index.js" + "import": "./dist/statistical-time-series/forecast-models/arma/index.js", + "require": "./dist/statistical-time-series/forecast-models/arma/index.js" }, "./statistical-time-series/forecast-models/arima": { "types": "./dist/statistical-time-series/forecast-models/arima/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/arima/index.js" + "import": "./dist/statistical-time-series/forecast-models/arima/index.js", + "require": "./dist/statistical-time-series/forecast-models/arima/index.js" }, "./statistical-time-series/forecast-models/sarima-sarimax": { "types": "./dist/statistical-time-series/forecast-models/sarima-sarimax/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/sarima-sarimax/index.js" + "import": "./dist/statistical-time-series/forecast-models/sarima-sarimax/index.js", + "require": "./dist/statistical-time-series/forecast-models/sarima-sarimax/index.js" }, "./statistical-time-series/forecast-models/holt-winters": { "types": "./dist/statistical-time-series/forecast-models/holt-winters/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/holt-winters/index.js" + "import": "./dist/statistical-time-series/forecast-models/holt-winters/index.js", + "require": "./dist/statistical-time-series/forecast-models/holt-winters/index.js" }, "./statistical-time-series/forecast-models/theta-forecast": { "types": "./dist/statistical-time-series/forecast-models/theta-forecast/index.d.ts", - "import": "./dist/statistical-time-series/forecast-models/theta-forecast/index.js" + "import": "./dist/statistical-time-series/forecast-models/theta-forecast/index.js", + "require": "./dist/statistical-time-series/forecast-models/theta-forecast/index.js" }, "./statistical-time-series/multivariate-systems/var": { "types": "./dist/statistical-time-series/multivariate-systems/var/index.d.ts", - "import": "./dist/statistical-time-series/multivariate-systems/var/index.js" + "import": "./dist/statistical-time-series/multivariate-systems/var/index.js", + "require": "./dist/statistical-time-series/multivariate-systems/var/index.js" }, "./statistical-time-series/multivariate-systems/structural-var": { "types": "./dist/statistical-time-series/multivariate-systems/structural-var/index.d.ts", - "import": "./dist/statistical-time-series/multivariate-systems/structural-var/index.js" + "import": "./dist/statistical-time-series/multivariate-systems/structural-var/index.js", + "require": "./dist/statistical-time-series/multivariate-systems/structural-var/index.js" }, "./statistical-time-series/multivariate-systems/vecm": { "types": "./dist/statistical-time-series/multivariate-systems/vecm/index.d.ts", - "import": "./dist/statistical-time-series/multivariate-systems/vecm/index.js" + "import": "./dist/statistical-time-series/multivariate-systems/vecm/index.js", + "require": "./dist/statistical-time-series/multivariate-systems/vecm/index.js" }, "./statistical-time-series/multivariate-systems/impulse-response-analysis": { "types": "./dist/statistical-time-series/multivariate-systems/impulse-response-analysis/index.d.ts", - "import": "./dist/statistical-time-series/multivariate-systems/impulse-response-analysis/index.js" + "import": "./dist/statistical-time-series/multivariate-systems/impulse-response-analysis/index.js", + "require": "./dist/statistical-time-series/multivariate-systems/impulse-response-analysis/index.js" }, "./statistical-time-series/multivariate-systems/forecast-error-variance-decomposition": { "types": "./dist/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/index.d.ts", - "import": "./dist/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/index.js" + "import": "./dist/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/index.js", + "require": "./dist/statistical-time-series/multivariate-systems/forecast-error-variance-decomposition/index.js" }, "./statistical-time-series/state-and-regime-models/kalman-filter": { "types": "./dist/statistical-time-series/state-and-regime-models/kalman-filter/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/kalman-filter/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/kalman-filter/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/kalman-filter/index.js" }, "./statistical-time-series/state-and-regime-models/extended-kalman-filter": { "types": "./dist/statistical-time-series/state-and-regime-models/extended-kalman-filter/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/extended-kalman-filter/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/extended-kalman-filter/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/extended-kalman-filter/index.js" }, "./statistical-time-series/state-and-regime-models/unscented-kalman-filter": { "types": "./dist/statistical-time-series/state-and-regime-models/unscented-kalman-filter/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/unscented-kalman-filter/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/unscented-kalman-filter/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/unscented-kalman-filter/index.js" }, "./statistical-time-series/state-and-regime-models/hidden-markov-model": { "types": "./dist/statistical-time-series/state-and-regime-models/hidden-markov-model/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/hidden-markov-model/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/hidden-markov-model/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/hidden-markov-model/index.js" }, "./statistical-time-series/state-and-regime-models/markov-switching-autoregression": { "types": "./dist/statistical-time-series/state-and-regime-models/markov-switching-autoregression/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/markov-switching-autoregression/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/markov-switching-autoregression/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/markov-switching-autoregression/index.js" }, "./statistical-time-series/state-and-regime-models/bayesian-change-point-detection": { "types": "./dist/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/index.d.ts", - "import": "./dist/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/index.js" + "import": "./dist/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/index.js", + "require": "./dist/statistical-time-series/state-and-regime-models/bayesian-change-point-detection/index.js" }, "./statistical-time-series/decomposition-and-cycles/stl-decomposition": { "types": "./dist/statistical-time-series/decomposition-and-cycles/stl-decomposition/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/stl-decomposition/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/stl-decomposition/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/stl-decomposition/index.js" }, "./statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter": { "types": "./dist/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/hodrick-prescott-filter/index.js" }, "./statistical-time-series/decomposition-and-cycles/baxter-king-filter": { "types": "./dist/statistical-time-series/decomposition-and-cycles/baxter-king-filter/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/baxter-king-filter/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/baxter-king-filter/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/baxter-king-filter/index.js" }, "./statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter": { "types": "./dist/statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/christiano-fitzgerald-filter/index.js" }, "./statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram": { "types": "./dist/statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/fast-fourier-transform-periodogram/index.js" }, "./statistical-time-series/decomposition-and-cycles/wavelet-decomposition": { "types": "./dist/statistical-time-series/decomposition-and-cycles/wavelet-decomposition/index.d.ts", - "import": "./dist/statistical-time-series/decomposition-and-cycles/wavelet-decomposition/index.js" + "import": "./dist/statistical-time-series/decomposition-and-cycles/wavelet-decomposition/index.js", + "require": "./dist/statistical-time-series/decomposition-and-cycles/wavelet-decomposition/index.js" }, "./market-microstructure/trade-classification/tick-test": { "types": "./dist/market-microstructure/trade-classification/tick-test/index.d.ts", - "import": "./dist/market-microstructure/trade-classification/tick-test/index.js" + "import": "./dist/market-microstructure/trade-classification/tick-test/index.js", + "require": "./dist/market-microstructure/trade-classification/tick-test/index.js" }, "./market-microstructure/trade-classification/quote-test": { "types": "./dist/market-microstructure/trade-classification/quote-test/index.d.ts", - "import": "./dist/market-microstructure/trade-classification/quote-test/index.js" + "import": "./dist/market-microstructure/trade-classification/quote-test/index.js", + "require": "./dist/market-microstructure/trade-classification/quote-test/index.js" }, "./market-microstructure/trade-classification/lee-ready-trade-signing": { "types": "./dist/market-microstructure/trade-classification/lee-ready-trade-signing/index.d.ts", - "import": "./dist/market-microstructure/trade-classification/lee-ready-trade-signing/index.js" + "import": "./dist/market-microstructure/trade-classification/lee-ready-trade-signing/index.js", + "require": "./dist/market-microstructure/trade-classification/lee-ready-trade-signing/index.js" }, "./market-microstructure/trade-classification/bulk-volume-classification": { "types": "./dist/market-microstructure/trade-classification/bulk-volume-classification/index.d.ts", - "import": "./dist/market-microstructure/trade-classification/bulk-volume-classification/index.js" + "import": "./dist/market-microstructure/trade-classification/bulk-volume-classification/index.js", + "require": "./dist/market-microstructure/trade-classification/bulk-volume-classification/index.js" }, "./market-microstructure/liquidity-and-spreads/quoted-spread": { "types": "./dist/market-microstructure/liquidity-and-spreads/quoted-spread/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/quoted-spread/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/quoted-spread/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/quoted-spread/index.js" }, "./market-microstructure/liquidity-and-spreads/effective-spread": { "types": "./dist/market-microstructure/liquidity-and-spreads/effective-spread/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/effective-spread/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/effective-spread/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/effective-spread/index.js" }, "./market-microstructure/liquidity-and-spreads/realized-spread": { "types": "./dist/market-microstructure/liquidity-and-spreads/realized-spread/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/realized-spread/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/realized-spread/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/realized-spread/index.js" }, "./market-microstructure/liquidity-and-spreads/roll-spread-estimator": { "types": "./dist/market-microstructure/liquidity-and-spreads/roll-spread-estimator/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/roll-spread-estimator/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/roll-spread-estimator/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/roll-spread-estimator/index.js" }, "./market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio": { "types": "./dist/market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/amihud-illiquidity-ratio/index.js" }, "./market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator": { "types": "./dist/market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator/index.d.ts", - "import": "./dist/market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator/index.js" + "import": "./dist/market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator/index.js", + "require": "./dist/market-microstructure/liquidity-and-spreads/corwin-schultz-spread-estimator/index.js" }, "./market-microstructure/order-flow-and-impact/order-flow-imbalance": { "types": "./dist/market-microstructure/order-flow-and-impact/order-flow-imbalance/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/order-flow-imbalance/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/order-flow-imbalance/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/order-flow-imbalance/index.js" }, "./market-microstructure/order-flow-and-impact/queue-imbalance": { "types": "./dist/market-microstructure/order-flow-and-impact/queue-imbalance/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/queue-imbalance/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/queue-imbalance/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/queue-imbalance/index.js" }, "./market-microstructure/order-flow-and-impact/kyle-lambda": { "types": "./dist/market-microstructure/order-flow-and-impact/kyle-lambda/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/kyle-lambda/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/kyle-lambda/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/kyle-lambda/index.js" }, "./market-microstructure/order-flow-and-impact/hasbrouck-price-impact": { "types": "./dist/market-microstructure/order-flow-and-impact/hasbrouck-price-impact/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/hasbrouck-price-impact/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/hasbrouck-price-impact/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/hasbrouck-price-impact/index.js" }, "./market-microstructure/order-flow-and-impact/pin": { "types": "./dist/market-microstructure/order-flow-and-impact/pin/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/pin/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/pin/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/pin/index.js" }, "./market-microstructure/order-flow-and-impact/vpin": { "types": "./dist/market-microstructure/order-flow-and-impact/vpin/index.d.ts", - "import": "./dist/market-microstructure/order-flow-and-impact/vpin/index.js" + "import": "./dist/market-microstructure/order-flow-and-impact/vpin/index.js", + "require": "./dist/market-microstructure/order-flow-and-impact/vpin/index.js" }, "./market-microstructure/order-book-dynamics/order-book-slope": { "types": "./dist/market-microstructure/order-book-dynamics/order-book-slope/index.d.ts", - "import": "./dist/market-microstructure/order-book-dynamics/order-book-slope/index.js" + "import": "./dist/market-microstructure/order-book-dynamics/order-book-slope/index.js", + "require": "./dist/market-microstructure/order-book-dynamics/order-book-slope/index.js" }, "./market-microstructure/order-book-dynamics/depth-weighted-midprice": { "types": "./dist/market-microstructure/order-book-dynamics/depth-weighted-midprice/index.d.ts", - "import": "./dist/market-microstructure/order-book-dynamics/depth-weighted-midprice/index.js" + "import": "./dist/market-microstructure/order-book-dynamics/depth-weighted-midprice/index.js", + "require": "./dist/market-microstructure/order-book-dynamics/depth-weighted-midprice/index.js" }, "./market-microstructure/order-book-dynamics/microprice": { "types": "./dist/market-microstructure/order-book-dynamics/microprice/index.d.ts", - "import": "./dist/market-microstructure/order-book-dynamics/microprice/index.js" + "import": "./dist/market-microstructure/order-book-dynamics/microprice/index.js", + "require": "./dist/market-microstructure/order-book-dynamics/microprice/index.js" }, "./market-microstructure/order-book-dynamics/order-book-resiliency": { "types": "./dist/market-microstructure/order-book-dynamics/order-book-resiliency/index.d.ts", - "import": "./dist/market-microstructure/order-book-dynamics/order-book-resiliency/index.js" + "import": "./dist/market-microstructure/order-book-dynamics/order-book-resiliency/index.js", + "require": "./dist/market-microstructure/order-book-dynamics/order-book-resiliency/index.js" }, "./market-microstructure/order-book-dynamics/hawkes-order-arrival-model": { "types": "./dist/market-microstructure/order-book-dynamics/hawkes-order-arrival-model/index.d.ts", - "import": "./dist/market-microstructure/order-book-dynamics/hawkes-order-arrival-model/index.js" + "import": "./dist/market-microstructure/order-book-dynamics/hawkes-order-arrival-model/index.js", + "require": "./dist/market-microstructure/order-book-dynamics/hawkes-order-arrival-model/index.js" }, "./market-microstructure/market-depth-analytics/cumulative-bid-ask-depth": { "types": "./dist/market-microstructure/market-depth-analytics/cumulative-bid-ask-depth/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/cumulative-bid-ask-depth/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/cumulative-bid-ask-depth/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/cumulative-bid-ask-depth/index.js" }, "./market-microstructure/market-depth-analytics/top-n-depth-imbalance": { "types": "./dist/market-microstructure/market-depth-analytics/top-n-depth-imbalance/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/top-n-depth-imbalance/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/top-n-depth-imbalance/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/top-n-depth-imbalance/index.js" }, "./market-microstructure/market-depth-analytics/depth-at-distance-profile": { "types": "./dist/market-microstructure/market-depth-analytics/depth-at-distance-profile/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/depth-at-distance-profile/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/depth-at-distance-profile/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/depth-at-distance-profile/index.js" }, "./market-microstructure/market-depth-analytics/expected-market-order-fill-price": { "types": "./dist/market-microstructure/market-depth-analytics/expected-market-order-fill-price/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/expected-market-order-fill-price/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/expected-market-order-fill-price/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/expected-market-order-fill-price/index.js" }, "./market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage": { "types": "./dist/market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/multi-level-sweep-cost-and-slippage/index.js" }, "./market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection": { "types": "./dist/market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/liquidity-wall-and-concentration-detection/index.js" }, "./market-microstructure/market-depth-analytics/depth-depletion-and-replenishment": { "types": "./dist/market-microstructure/market-depth-analytics/depth-depletion-and-replenishment/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/depth-depletion-and-replenishment/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/depth-depletion-and-replenishment/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/depth-depletion-and-replenishment/index.js" }, "./market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation": { "types": "./dist/market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation/index.d.ts", - "import": "./dist/market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation/index.js" + "import": "./dist/market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation/index.js", + "require": "./dist/market-microstructure/market-depth-analytics/market-depth-heatmap-aggregation/index.js" }, "./matching-engines-and-venue-logic/continuous-matching/price-time-priority": { "types": "./dist/matching-engines-and-venue-logic/continuous-matching/price-time-priority/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/continuous-matching/price-time-priority/index.js" + "import": "./dist/matching-engines-and-venue-logic/continuous-matching/price-time-priority/index.js", + "require": "./dist/matching-engines-and-venue-logic/continuous-matching/price-time-priority/index.js" }, "./matching-engines-and-venue-logic/continuous-matching/pro-rata-matching": { "types": "./dist/matching-engines-and-venue-logic/continuous-matching/pro-rata-matching/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/continuous-matching/pro-rata-matching/index.js" + "import": "./dist/matching-engines-and-venue-logic/continuous-matching/pro-rata-matching/index.js", + "require": "./dist/matching-engines-and-venue-logic/continuous-matching/pro-rata-matching/index.js" }, "./matching-engines-and-venue-logic/continuous-matching/size-time-priority": { "types": "./dist/matching-engines-and-venue-logic/continuous-matching/size-time-priority/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/continuous-matching/size-time-priority/index.js" + "import": "./dist/matching-engines-and-venue-logic/continuous-matching/size-time-priority/index.js", + "require": "./dist/matching-engines-and-venue-logic/continuous-matching/size-time-priority/index.js" }, "./matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching": { "types": "./dist/matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching/index.js" + "import": "./dist/matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching/index.js", + "require": "./dist/matching-engines-and-venue-logic/continuous-matching/hybrid-pro-rata-time-matching/index.js" }, "./matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction": { "types": "./dist/matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction/index.js" + "import": "./dist/matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction/index.js", + "require": "./dist/matching-engines-and-venue-logic/auctions/maximum-executable-volume-auction/index.js" }, "./matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break": { "types": "./dist/matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break/index.js" + "import": "./dist/matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break/index.js", + "require": "./dist/matching-engines-and-venue-logic/auctions/minimum-imbalance-tie-break/index.js" }, "./matching-engines-and-venue-logic/auctions/opening-cross-price": { "types": "./dist/matching-engines-and-venue-logic/auctions/opening-cross-price/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/auctions/opening-cross-price/index.js" + "import": "./dist/matching-engines-and-venue-logic/auctions/opening-cross-price/index.js", + "require": "./dist/matching-engines-and-venue-logic/auctions/opening-cross-price/index.js" }, "./matching-engines-and-venue-logic/auctions/closing-cross-price": { "types": "./dist/matching-engines-and-venue-logic/auctions/closing-cross-price/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/auctions/closing-cross-price/index.js" + "import": "./dist/matching-engines-and-venue-logic/auctions/closing-cross-price/index.js", + "require": "./dist/matching-engines-and-venue-logic/auctions/closing-cross-price/index.js" }, "./matching-engines-and-venue-logic/auctions/volatility-auction-reopening": { "types": "./dist/matching-engines-and-venue-logic/auctions/volatility-auction-reopening/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/auctions/volatility-auction-reopening/index.js" + "import": "./dist/matching-engines-and-venue-logic/auctions/volatility-auction-reopening/index.js", + "require": "./dist/matching-engines-and-venue-logic/auctions/volatility-auction-reopening/index.js" }, "./matching-engines-and-venue-logic/order-controls/tick-size-validation": { "types": "./dist/matching-engines-and-venue-logic/order-controls/tick-size-validation/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/tick-size-validation/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/tick-size-validation/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/tick-size-validation/index.js" }, "./matching-engines-and-venue-logic/order-controls/price-band-validation": { "types": "./dist/matching-engines-and-venue-logic/order-controls/price-band-validation/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/price-band-validation/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/price-band-validation/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/price-band-validation/index.js" }, "./matching-engines-and-venue-logic/order-controls/self-trade-prevention": { "types": "./dist/matching-engines-and-venue-logic/order-controls/self-trade-prevention/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/self-trade-prevention/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/self-trade-prevention/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/self-trade-prevention/index.js" }, "./matching-engines-and-venue-logic/order-controls/cancel-on-disconnect": { "types": "./dist/matching-engines-and-venue-logic/order-controls/cancel-on-disconnect/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/cancel-on-disconnect/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/cancel-on-disconnect/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/cancel-on-disconnect/index.js" }, "./matching-engines-and-venue-logic/order-controls/fat-finger-limit": { "types": "./dist/matching-engines-and-venue-logic/order-controls/fat-finger-limit/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/fat-finger-limit/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/fat-finger-limit/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/fat-finger-limit/index.js" }, "./matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger": { "types": "./dist/matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-controls/circuit-breaker-trigger/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/limit-order-lifecycle-state-machine/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/cancel-replace-priority-rule/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/partial-fill-and-residual-quantity-processing/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/queue-position-and-ahead-volume-calculation/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/iceberg-reserve-order-replenishment/index.js" }, "./matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep": { "types": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep/index.d.ts", - "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep/index.js" + "import": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep/index.js", + "require": "./dist/matching-engines-and-venue-logic/order-lifecycle-and-queue-state/marketable-order-multi-level-sweep/index.js" }, "./execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution": { "types": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/twap-execution/index.js" }, "./execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution": { "types": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/historical-vwap-execution/index.js" }, "./execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution": { "types": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/adaptive-vwap-execution/index.js" }, "./execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution": { "types": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/schedule-based-execution/percentage-of-volume-execution/index.js" }, "./execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution": { "types": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/almgren-chriss-optimal-execution/index.js" }, "./execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution": { "types": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/implementation-shortfall-execution/index.js" }, "./execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution": { "types": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/arrival-price-execution/index.js" }, "./execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution": { "types": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/liquidity-seeking-execution/index.js" }, "./execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution": { "types": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution/index.d.ts", - "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution/index.js" + "import": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution/index.js", + "require": "./dist/execution-and-transaction-cost-analysis/cost-risk-optimization/opportunistic-dark-pool-execution/index.js" }, "./digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm": { "types": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-product-amm/index.js" }, "./digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm": { "types": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/amm-pricing/constant-sum-amm/index.js" }, "./digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant": { "types": "./dist/digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/amm-pricing/stableswap-invariant/index.js" }, "./digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm": { "types": "./dist/digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/amm-pricing/weighted-product-amm/index.js" }, "./digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position": { "types": "./dist/digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/amm-pricing/concentrated-liquidity-position/index.js" }, "./digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation": { "types": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/impermanent-loss-calculation/index.js" }, "./digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr": { "types": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidity-provider-fee-apr/index.js" }, "./digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor": { "types": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/collateral-health-factor/index.js" }, "./digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation": { "types": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-price-calculation/index.js" }, "./digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall": { "types": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall/index.d.ts", - "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall/index.js" + "import": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall/index.js", + "require": "./dist/digital-assets-and-on-chain-finance/liquidity-and-liquidation/liquidation-waterfall/index.js" }, "./earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement": { "types": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement/index.d.ts", - "import": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement/index.js" + "import": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement/index.js", + "require": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/stock-split-consolidation-eps-restatement/index.js" }, "./earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps": { "types": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps/index.d.ts", - "import": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps/index.js" + "import": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps/index.js", + "require": "./dist/earnings-and-per-share-analytics/earnings-and-share-foundations/basic-eps/index.js" }, "./earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution": { "types": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution/index.d.ts", - "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution/index.js" + "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution/index.js", + "require": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/if-converted-convertible-preference-dilution/index.js" }, "./earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants": { "types": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants/index.d.ts", - "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants/index.js" + "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants/index.js", + "require": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/treasury-share-method-for-options-warrants/index.js" }, "./earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion": { "types": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion/index.d.ts", - "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion/index.js" + "import": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion/index.js", + "require": "./dist/earnings-and-per-share-analytics/basic-and-diluted-eps/contingently-issuable-share-inclusion/index.js" }, "./package.json": "./package.json" } diff --git a/scripts/gen-docs.mjs b/scripts/gen-docs.mjs index 29935d2..ea18bd0 100644 --- a/scripts/gen-docs.mjs +++ b/scripts/gen-docs.mjs @@ -28,7 +28,7 @@ * as source, and playground links are omitted rather than guessed. * * Usage: - * node scripts/gen-docs.mjs [--content-root ] [--check] + * node scripts/gen-docs.mjs [--content-root ] [--check] [--strict-contracts] */ import { readFileSync, writeFileSync, existsSync, readdirSync, statSync } from "node:fs"; @@ -39,8 +39,12 @@ import { parseYaml } from "./lib/yaml-subset.mjs"; const REPO = resolve(dirname(fileURLToPath(import.meta.url)), ".."); /** Payload shape version. Independent of the package version — bump only when - * the structure changes, because the docs site pins a major. */ -const SCHEMA_VERSION = "1.0.0"; + * the structure changes, because the docs site pins a major. + * + * 2.0.0 — per-topic `languages` became `catalogLanguages`; `package` grew the + * runtime and machine-surface facts; `archetypes` and `domains[].slug` added. + * The rename is the reason this is a major and not a minor. */ +const SCHEMA_VERSION = "2.0.0"; const SITE = "https://thefintechbuilder.com"; const GITHUB = "https://github.com/IslamBaraka90/Fintech-Algorithms-Library"; @@ -50,6 +54,7 @@ function argValue(flag, fallback) { return i !== -1 && process.argv[i + 1] ? process.argv[i + 1] : fallback; } const CHECK = process.argv.includes("--check"); +const STRICT_CONTRACTS = process.argv.includes("--strict-contracts"); const CONTENT_ROOT = resolve( argValue("--content-root", process.env.FINTECH_CONTENT_ROOT ?? resolve(REPO, "..", "..")), ); @@ -64,6 +69,12 @@ const registrySrc = readFileSync(join(REPO, "src", "_registry.ts"), "utf8"); const pkg = JSON.parse(readFileSync(join(REPO, "package.json"), "utf8")); const manifest = JSON.parse(readFileSync(join(REPO, "test", "_manifest.json"), "utf8")); +/** + * The documentation site, which doubles as the machine surface. Read off + * `homepage` rather than repeated as a literal, so the two can never disagree. + */ +const DOCS = pkg.homepage.replace(/\/+$/, ""); + /** * The registry is generated TypeScript. Parsing it with a regex rather than * importing avoids needing type-stripping here, and matches what @@ -201,6 +212,25 @@ function references(dir) { return out; } +/** + * Which languages the *catalog* publishes for a topic, read from the + * `implementations//` directories that are actually there. + * + * This is a catalog fact and is named like one. It used to be the literal + * `["typescript", "python"]` on all 324 topics, which read as a promise that a + * Python package exists — it does not, and an agent trusting that field would + * confidently write `pip install fintech-algorithms`. What this *package* ships + * is stated once, as `package.languages`, and it is TypeScript alone. + */ +function implementationLanguages(dir) { + const src = dir ? join(dir, "implementations") : null; + if (!src || !existsSync(src)) return ["typescript"]; + const langs = readdirSync(src) + .filter((d) => statSync(join(src, d)).isDirectory()) + .sort(); + return langs.length ? langs : ["typescript"]; +} + // ------------------------------------------------------------- examples @@ -443,17 +473,33 @@ const topics = topicsFromRegistry.map((t) => { source: `${GITHUB}/blob/main/src/${t.path}/impl.ts`, npm: `https://www.npmjs.com/package/${pkg.name}`, }, - languages: ["typescript", "python"], + catalogLanguages: implementationLanguages(dir), }; }); +/** Inconsistencies in the payload's own structure, collected and reported the + * same way contract errors are: refuse to emit rather than mislead. */ +const structureErrors = []; + /** Domain → family tree, so the site can build navigation without regrouping. */ const domains = [...new Set(topics.map((t) => t.taxonomy.domainId))].sort().map((domainId) => { const inDomain = topics.filter((t) => t.taxonomy.domainId === domainId); const familyIds = [...new Set(inDomain.map((t) => t.taxonomy.familyId))].sort(); + + // The first path segment is the domain's URL slug everywhere — on the site, + // in the per-domain llms.txt route, in the topic page URL. Emitting it means + // a consumer never has to rediscover it by finding a topic in the domain and + // splitting its path; a domain whose topics disagree would silently produce + // two different routes for one domain, so it fails the build instead. + const slugs = [...new Set(inDomain.map((t) => t.path.split("/")[0]))]; + if (slugs.length !== 1) { + structureErrors.push(`${domainId}: topics span more than one path root — ${slugs.join(", ")}`); + } + return { id: domainId, name: inDomain[0].taxonomy.domain, + slug: slugs[0], topicCount: inDomain.length, families: familyIds.map((familyId) => { const inFamily = inDomain.filter((t) => t.taxonomy.familyId === familyId); @@ -462,9 +508,238 @@ const domains = [...new Set(topics.map((t) => t.taxonomy.domainId))].sort().map( }; }); +// ----------------------------------------------------------- archetypes + +/** + * The five fields every quote in a consensus snapshot must agree on. Shared + * between the quotes and the policy's `expected_contract` so the example cannot + * drift apart from itself — a mismatch there is the exact failure the algorithm + * reports, which would make the worked example a demonstration of the error. + */ +const CONSENSUS_CONTRACT = { + instrument_id: "SYNTH-USD", + currency: "USD", + price_type: "last_trade", + adjustment: "unadjusted", + session: "regular", +}; +const CONSENSUS_AS_OF = "2026-07-13T13:30:01.000Z"; + +/** + * The five input shapes, as data. + * + * `import.archetype` already labels every topic, but a label alone does not + * tell a consumer how to map its own data onto it: what the first argument + * actually is, what a minimal payload looks like, or what to run before + * trusting the input. That is the machine half of the prose guide at + * `/guides/archetypes/`, and without it an agent has to read the page. + * + * Counts are derived from the catalog. Everything else is static, because it + * describes a *shape* rather than a catalog row — and every `example` below was + * executed against the built package before being written down. + * + * Insertion order is the emitted order, and it is the guide's order: the + * smallest shapes have the cleanest contracts, and `record-transform` is a + * residual bucket that is deliberately last. + */ +const ARCHETYPES = { + "series-transform": { + firstArgument: "(number | null)[]", + returns: "an array of the same length, aligned index-for-index with the input", + type: "type SeriesTransform = (values: (number | null)[], ...params: number[]) => (number | null)[];", + example: { + subpath: "fintech-algorithms/technical-indicators/trend-smoothing/sma", + entry: "calculateSma", + call: "calculateSma([10, 13, 12, 15, 14, 18], 3)", + args: [[10, 13, 12, 15, 14, 18], 3], + }, + validator: { + subpath: + "fintech-algorithms/market-data-engineering/cleaning-and-validation/median-absolute-deviation-outlier-filter", + note: "A numeric series has no structure to check, so check its values. Takes the same number[] you are about to pass to the indicator.", + }, + caveat: + "Leading nulls are warm-up, not missing data. The output is the same length as the input so that bars[i] and result[i] describe the same instant; filtering the nulls shifts the series left and nothing errors.", + }, + "tape-aggregate": { + firstArgument: "Trade[]", + returns: "Bar[]", + type: "type TapeAggregate = (trades: Trade[], config: object) => Bar[];", + example: { + subpath: "fintech-algorithms/market-data-engineering/bar-construction/time-bars", + entry: "constructBars", + call: "constructBars(trades, { intervalSeconds: 60, sessionStarts: { RTH: … } })", + args: [ + [ + { + tradeId: "1", + timestamp: "2026-07-20T09:30:01.000Z", + session: "RTH", + symbol: "DEMO", + price: 100, + volume: 500, + currency: "USD", + }, + ], + { intervalSeconds: 60, sessionStarts: { RTH: "2026-07-20T09:30:00.000Z" } }, + ], + }, + validator: { + subpath: + "fintech-algorithms/market-data-engineering/cleaning-and-validation/duplicate-trade-resolver", + note: "Run before aggregating. A duplicated print inflates volume permanently and is invisible once it is inside a bar.", + }, + caveat: + "The only shape that cares about ordering and sessions. Trades must arrive in chronological order, and sessionStarts anchors every bucket boundary — get it wrong and every bar edge is off by the same amount, consistently enough to look correct.", + }, + "row-classify": { + firstArgument: "an array of rows", + returns: "one verdict per row, in the same order — verdicts.length === rows.length", + type: "type RowClassify = (rows: Row[], config?: object) => Verdict[];", + example: { + subpath: + "fintech-algorithms/market-data-engineering/cleaning-and-validation/ohlc-consistency-validator", + entry: "validateBars", + call: "validateBars(bars, { tickSize: 0.01, toleranceTicks: 1, priceScale: 1 })", + args: [ + [ + { + timestamp: "2026-07-20T09:30:00Z", + symbol: "DEMO", + open: 100, + high: 101, + low: 99.5, + close: 100.5, + volume: 1000, + }, + ], + { tickSize: 0.01, toleranceTicks: 1, priceScale: 1 }, + ], + }, + validator: { + subpath: null, + note: "This archetype is the boundary. It is what you run before the other four.", + }, + caveat: + "Nothing signals failure except the verdict. These never throw on bad input — one malformed record in ten thousand should lose neither the record nor the other 9,999 — so ignoring the return value looks like success.", + }, + "snapshot-evaluate": { + firstArgument: "one point-in-time snapshot", + returns: "a single verdict about that instant", + type: "type SnapshotEvaluate = (snapshot: object, policyOrTime: object | string) => Verdict;", + example: { + subpath: "fintech-algorithms/market-data-engineering/data-quality/price-source-consensus-check", + entry: "consensus", + call: "consensus({ as_of, quotes }, policy)", + args: [ + { + as_of: CONSENSUS_AS_OF, + quotes: [ + { source_id: "A", owner_id: "OWNER-A", price: 100, ...CONSENSUS_CONTRACT, event_time: CONSENSUS_AS_OF }, + { source_id: "B", owner_id: "OWNER-B", price: 100.01, ...CONSENSUS_CONTRACT, event_time: CONSENSUS_AS_OF }, + { source_id: "C", owner_id: "OWNER-C", price: 100.02, ...CONSENSUS_CONTRACT, event_time: CONSENSUS_AS_OF }, + ], + }, + { + minimum_independent_sources: 3, + z_threshold: 3.5, + absolute_tolerance: 0.03, + maximum_tolerance: 0.15, + max_age_ms: 500, + expected_contract: CONSENSUS_CONTRACT, + }, + ], + }, + validator: { + subpath: null, + note: "These are themselves validators. Feed them the snapshot you are about to trust.", + }, + caveat: + "The second argument is usually a decision time, and it is what makes the result reproducible. Passing 'now' instead of the instant being evaluated turns a point-in-time check into look-ahead.", + }, + "record-transform": { + firstArgument: "a domain-specific record or array", + returns: "a domain-specific result", + type: null, + example: null, + validator: { + subpath: null, + note: "Whichever matches the record being passed: a bar → ohlc-consistency-validator, a quote → stale-quote-detector, a corporate action → its own family's guard.", + }, + caveat: + "Not a shape. This is the residual bucket — a topic lands here when it is none of the other four — so it spans twelve of the thirteen domains and shares no field names between families. Read the topic's own `api` block and `example` in this payload instead.", + }, +}; + +const archetypeCounts = new Map(); +for (const t of topics) { + archetypeCounts.set(t.import.archetype, (archetypeCounts.get(t.import.archetype) ?? 0) + 1); +} + +// A sixth archetype appearing in the catalog, or a documented one going empty, +// means this block is describing a library that no longer exists. Fail rather +// than emit a distribution that silently omits a shape. +for (const name of archetypeCounts.keys()) { + if (!ARCHETYPES[name]) structureErrors.push(`archetype "${name}" has topics but no description`); +} +for (const name of Object.keys(ARCHETYPES)) { + if (!archetypeCounts.get(name)) structureErrors.push(`archetype "${name}" is described but has no topics`); +} + +const archetypes = Object.entries(ARCHETYPES).map(([name, a]) => ({ + name, + topicCount: archetypeCounts.get(name) ?? 0, + ...a, +})); + const payload = { schemaVersion: SCHEMA_VERSION, - package: { name: pkg.name, version: pkg.version, homepage: pkg.homepage }, + package: { + name: pkg.name, + version: pkg.version, + homepage: pkg.homepage, + license: pkg.license, + type: pkg.type, + engines: pkg.engines, + + // What the *package* ships, as opposed to what the catalog publishes per + // topic in `catalogLanguages`. There is no Python package. + languages: ["typescript"], + + entryPoints: { + root: { + specifier: pkg.name, + contains: "metadata", + note: + "The root export carries the topic registry and the lookup helpers " + + "(topic, byDomain, byFamily, byArchetype, load, runner). No algorithm is re-exported here.", + }, + topic: { + pattern: `${pkg.name}/{topic.path}`, + conditions: ["import", "require"], + note: + "Algorithms are subpath-only. Each subpath exports the function named in its `import.entry` " + + "and its own types; a sibling topic's function is never re-exported, so import it from its own subpath.", + commonjs: + "The require condition resolves to the same ES module as import — there is no separate " + + "CommonJS build — so require() needs a runtime that supports require(esm).", + }, + }, + + // Every route below was requested against the live site and returned 200. + // Patterns name the payload field that fills them, so a consumer holding + // only this file can construct them without guessing. + machineSurface: { + site: DOCS, + llms: `${DOCS}/llms.txt`, + versionEndpoint: `${DOCS}/version.json`, + payload: `${DOCS}/reference/payload.json`, + domainLlms: `${DOCS}/{domain.slug}/llms.txt`, + topicPage: `${DOCS}/{topic.path}/`, + topicMarkdown: `${DOCS}/{topic.path}/index.md`, + archetypeGuide: `${DOCS}/guides/archetypes/`, + }, + }, counts: { topics: topics.length, domains: domains.length, @@ -474,17 +749,34 @@ const payload = { withDiagram: topics.filter((t) => t.assets.diagrams.length).length, withApiContract: topics.filter((t) => t.api).length, }, + archetypes, domains, topics, }; -// A contract that contradicts the code is worse than no contract: refuse to -// emit rather than publish documentation the implementation disagrees with. +// `--strict-contracts` refuses to emit when a topic has *no* contract at all. +// It is off by default because the `api:` block was populated family by family +// and a topic without one is not malformed, only undocumented. CI turns it on: +// coverage that nothing enforced is exactly how a complete 271/271 quietly +// became 280/324 as the catalog grew. +if (STRICT_CONTRACTS) { + for (const t of topics.filter((x) => !x.api)) { + apiErrors.push(`${t.id}: no api: block — ${t.path}/metadata.yaml`); + } +} + +// A contract that contradicts the code is worse than no contract, and a payload +// whose own structure is inconsistent will mislead every consumer downstream: +// refuse to emit rather than publish either. +if (structureErrors.length) { + console.error(`gen-docs: ${structureErrors.length} payload structure error(s)`); + for (const e of structureErrors) console.error(` ${e}`); +} if (apiErrors.length) { console.error(`gen-docs: ${apiErrors.length} api: contract error(s)`); for (const e of apiErrors) console.error(` ${e}`); - process.exit(1); } +if (structureErrors.length || apiErrors.length) process.exit(1); const json = JSON.stringify(payload, null, 2) + "\n"; diff --git a/scripts/sync.mjs b/scripts/sync.mjs index 7b0dac9..c2deb30 100644 --- a/scripts/sync.mjs +++ b/scripts/sync.mjs @@ -992,14 +992,29 @@ emit("src/index.ts", rootIndex); const pkgPath = join(REPO, "package.json"); const pkg = JSON.parse(readFileSync(pkgPath, "utf8")); -const exportsMap = { - ".": { types: "./dist/index.d.ts", import: "./dist/index.js" }, -}; + +/** + * One entry of the `exports` map. + * + * `require` points at the *same* ES module as `import`, which is deliberate. + * Node resolves `require()` against the `require` condition only, so a package + * that declares `import` alone is unreachable from CommonJS — not because the + * module cannot be loaded, but because resolution fails before loading is + * attempted. Node can `require()` an ES module, so the fix is the condition, + * not a second CommonJS build: the tarball stays one copy of every module, and + * a dual-package hazard is impossible because there is only ever one copy of a + * module's state. Consumers on a runtime without `require(esm)` still need + * `import`. + */ +const exportEntry = (base) => ({ + types: `${base}/index.d.ts`, + import: `${base}/index.js`, + require: `${base}/index.js`, +}); + +const exportsMap = { ".": exportEntry("./dist") }; for (const t of topics) { - exportsMap[`./${t.path}`] = { - types: `./dist/${t.path}/index.d.ts`, - import: `./dist/${t.path}/index.js`, - }; + exportsMap[`./${t.path}`] = exportEntry(`./dist/${t.path}`); } exportsMap["./package.json"] = "./package.json"; pkg.exports = exportsMap;