@hoox-sh/pynets 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/runtime/ta.ts CHANGED
@@ -9,6 +9,7 @@
9
9
  export type Cell = number | null;
10
10
 
11
11
  import { PineArray } from "./array.ts";
12
+ import { cloneValue } from "./clone.ts";
12
13
 
13
14
  interface SmaState {
14
15
  period: number;
@@ -602,6 +603,33 @@ export class TaEngine {
602
603
  private readonly momentumFilterSites = new Map<string, { momentum: Cell[]; volume: Cell[] }>();
603
604
  private readonly volatilityRegimeSites = new Map<string, Cell[]>();
604
605
 
606
+ /**
607
+ * Snapshot every per-site window (Python `_snapshot_ta_state`).
608
+ * Intermediate realtime ticks push one sample per call site; without
609
+ * rollback the same bar would be counted N times.
610
+ */
611
+ snapshot(): Array<[string, Map<string, unknown>]> {
612
+ const out: Array<[string, Map<string, unknown>]> = [];
613
+ for (const [key, value] of Object.entries(this as unknown as Record<string, unknown>)) {
614
+ if (!(value instanceof Map)) continue;
615
+ const copy = new Map<string, unknown>();
616
+ for (const [site, state] of value) copy.set(site, cloneValue(state));
617
+ out.push([key, copy]);
618
+ }
619
+ return out;
620
+ }
621
+
622
+ /** Copy-on-restore (Python `_restore_ta_state`); never throws. */
623
+ restore(snap: Array<[string, Map<string, unknown>]>): void {
624
+ const self = this as unknown as Record<string, unknown>;
625
+ for (const [key, copy] of snap) {
626
+ const live = self[key];
627
+ if (!(live instanceof Map)) continue;
628
+ live.clear();
629
+ for (const [site, state] of copy) live.set(site, cloneValue(state));
630
+ }
631
+ }
632
+
605
633
  sma(site: string, source: Cell, period: number): Cell {
606
634
  const n = pinePeriod(period);
607
635
  if (n === null) return null;
@@ -7,6 +7,8 @@
7
7
  * remain the source of truth — interpret registers TypeDef / EnumDef later.
8
8
  */
9
9
 
10
+ import { cloneValue } from "./clone.ts";
11
+
10
12
  export type UdtField = { name: string; default: unknown };
11
13
 
12
14
  /** Stored method; `body` is opaque (interpret owns FunctionDef). */
@@ -83,6 +85,26 @@ export class UdtInstance {
83
85
  getMethod(name: string): UdtMethod | undefined {
84
86
  return this.type.getMethod(name);
85
87
  }
88
+
89
+ /** Deep clone (realtime tick snapshots). */
90
+ clone(): UdtInstance {
91
+ const out = new UdtInstance(this.type);
92
+ out.restoreContents(this.snapshotContents());
93
+ return out;
94
+ }
95
+
96
+ /** Deep-cloned field values for realtime tick rollback. */
97
+ snapshotContents(): Array<[string, unknown]> {
98
+ const out: Array<[string, unknown]> = [];
99
+ for (const [k, v] of this.values) out.push([k, cloneValue(v)]);
100
+ return out;
101
+ }
102
+
103
+ /** Replace fields with clones of `snap` — same instance for aliases. */
104
+ restoreContents(snap: Array<[string, unknown]>): void {
105
+ this.values.clear();
106
+ for (const [k, v] of snap) this.values.set(k, cloneValue(v));
107
+ }
86
108
  }
87
109
 
88
110
  export class EnumMember {