Skip to main content

Forming series

:::info Preview This route works and may change with 30 days' notice. Do not build production alarms on it yet. :::

Patternode keeps nothing between calls, not even for a series that is still forming. The series carries itself: each answer returns its edge, a sealed token holding the open right edge of every level. You store the edge with the segments, and send it back with the next bars.

In the answerMeansDo
closedSegments these bars closed, now finalStore them; they never change
right_edgeThe open segment at each level, provisionalReplace the previous right edge with it
edgeThe series' state, sealed by PatternodeStore it as it is; send it back with the next bars
edge_last_close_timeWhen the last bar closedThe next bars must open after it
outcomestarted, extended or segmentedRedraw when segmented

Rules:

  • The edge is sealed: encrypted and signed, bound to your account, the series and the profile version. It is no use to anyone else, and a changed edge is refused (400 edge_invalid); an edge sent for another series is refused (409 edge_mismatch).
  • Bars must open after the edge's last bar closed; otherwise 409 out_of_order, and nothing is applied.
  • The same edge with the same bars always gives the same answer. A timeout is safe to retry: resend the request you sent.
  • Store the closed segments, the right edge and the edge together, in one write. One writer per series: if two writers extend from the same edge, keep the first write (a version check, as the segment store does).
  • A finished series can become a forming one: ask POST /v1/segmentations for return_edge: true and carry on from that edge.
  • Many series at once: POST /v1/segmentations/extend/batch takes up to 1,000 items, each with its own edge.

Extending a series bar by bar, in any pieces, gives the same segments as sending all its bars as one finished series.

examples/python/forming_series.py
"""Pattern 2, a forming series: send the edge with each new bar, store what comes back. Preview.

PATTERNODE_API_KEY=pnk_live_... python examples/python/forming_series.py examples/data/export-kw.json

Patternode keeps nothing between calls. Each answer carries the series' edge, a sealed token;
SegmentStore keeps it with the segments and sends it back with the next bars. A retry with
the same edge and bars gives the same answer, so a timeout is safe to retry.
"""

import json
import sys
import tempfile
from pathlib import Path

from patternode_client import Patternode, PatternodeError
from segment_store import SegmentStore


def main(path: str) -> None:
bars = json.loads(Path(path).read_text())
pn = Patternode()
store = SegmentStore(Path(tempfile.mkdtemp()) / "example-utility") # in production: your store, per client
series = "exu/demo/forming/ac-power"
for bar in bars: # as each bar closes
try:
r = store.extend(pn, series, [bar], profile="standard@2026-11")
except PatternodeError as e:
if e.code == "out_of_order": # a late bar: nothing was applied, the edge is unchanged
print(f"skipped a bar at {bar[0]}: out of order")
continue
raise
for s in r["closed"]: # final: redraw, notify
print(f"bar {r['bars']}: level {s['height']} closed {s['id']} ({s['open']} -> {s['close']})")
edge = store.edge(series)
print(f"open at each level: {', '.join(s['id'] for s in store.right_edge(series))}")
print(f"trend: {store.trend(series)}; edge {len(edge.token)} bytes, next bar after {edge.last_close_time}")


if __name__ == "__main__":
main(sys.argv[1] if len(sys.argv) > 1 else "examples/data/export-kw.json")