@livefolio/sdk 0.3.1 → 0.3.2

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/dist/index.d.ts CHANGED
@@ -114,9 +114,53 @@ declare class IndicatorHandle {
114
114
  private _sync;
115
115
  private _upsertSeries;
116
116
  private _querySeriesFromDb;
117
+ withMarket(market: MarketProvider): IndicatorHandle;
118
+ /**
119
+ * Apply leverage compounding to a raw bar series, anchored to a stored
120
+ * leveraged value. Used by both `_sync` and `computeAt` so they stay
121
+ * consistent.
122
+ *
123
+ * `anchorDate` is the date of the last *already-stored* leveraged bar
124
+ * (i.e., the bar just before `rawBars[0]`). The stored leveraged value
125
+ * at that date becomes `leveraged[0]`; raw returns are then compounded
126
+ * forward for each subsequent bar.
127
+ *
128
+ * If no stored anchor exists (first-ever sync), falls back to rawBars[0]
129
+ * as the starting raw value — identical to `_sync`'s behaviour.
130
+ */
131
+ private _applyLeverage;
132
+ /**
133
+ * Compute the indicator's value at `date` using the given market (typically
134
+ * an overlay market for pre-close preview). Pure — no writes to storage.
135
+ *
136
+ * For fetched types (yahoo/fred): fetches a small window of bars from
137
+ * `market`, applies leverage compounding anchored to the stored leveraged
138
+ * value at the bar before `date`.
139
+ * For computed types (SMA, RSI, etc.): fetches enough raw price bars to
140
+ * cover the indicator's lookback from `market`, applies leverage anchored
141
+ * to the stored value just before the fetch window, runs the computation,
142
+ * and returns the value at `date`.
143
+ * For Threshold: returns the threshold constant.
144
+ * For calendar: computes calendar value from the trading days list.
145
+ * Returns null if the value cannot be computed.
146
+ */
147
+ computeAt(market: MarketProvider, date: string): Promise<number | null>;
117
148
  series(range?: DateRange): Promise<DailyBar[]>;
118
149
  private _syntheticThresholdSeries;
119
150
  value(date?: string): Promise<number | null>;
151
+ /**
152
+ * Read-only preview of the indicator series that includes an in-memory bar
153
+ * at `date` computed via `computeAt` against a quote-overlay market. Does
154
+ * NOT write to `indicators_series`. Safe to call before market close.
155
+ *
156
+ * @param date - Target trading day whose value is computed in-memory from
157
+ * the overridden quotes. Must be in `tradingDays.getRange()`.
158
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
159
+ * Symbols omitted here fall back to yesterday's close via the overlay.
160
+ * @param range - Optional filter applied to the returned bars.
161
+ * @returns Stored historical bars plus (or with) today's in-memory value.
162
+ */
163
+ previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<DailyBar[]>;
120
164
  }
121
165
 
122
166
  interface StorageProvider {
@@ -188,6 +232,7 @@ interface StorageProvider {
188
232
  getSeries(strategyId: number, range?: DateRange): Promise<StrategySeriesEntry[]>;
189
233
  writeSeries(strategyId: number, entries: StrategySeriesEntry[]): Promise<void>;
190
234
  getLatestSeriesDate(strategyId: number): Promise<string | null>;
235
+ getLatestAllocationId(strategyId: number): Promise<number | null>;
191
236
  resolveReference(linkId: string): Promise<StrategyReferenceData>;
192
237
  };
193
238
  tradingDays: {
@@ -228,8 +273,31 @@ declare class SignalHandle {
228
273
  private _sync;
229
274
  private _upsertSeries;
230
275
  private _querySeriesFromDb;
276
+ withMarket(market: MarketProvider): SignalHandle;
277
+ /**
278
+ * Compute the signal's boolean value at `date` using the given market
279
+ * (typically an overlay market for pre-close preview). Pure — no writes.
280
+ * Returns null if either indicator cannot produce a value at `date`.
281
+ *
282
+ * @param prevBool - The signal's boolean value at the bar immediately
283
+ * preceding `date`, used for hysteresis when `tolerance > 0`. If not
284
+ * provided, falls back to `storage.signals.getLastValue` (suitable for
285
+ * standalone callers). On the preview path `_evaluate` passes this from
286
+ * the in-memory `dateMap` so we never read stale storage.
287
+ */
288
+ computeAt(market: MarketProvider, date: string, prevBool?: boolean | null): Promise<boolean | null>;
231
289
  series(range?: DateRange): Promise<DailyBar[]>;
232
290
  value(date?: string): Promise<number | null>;
291
+ /**
292
+ * Read-only preview of the signal series with an in-memory bar at `date`
293
+ * computed via `computeAt` against a quote-overlay market. Does NOT write
294
+ * to `signals_series`.
295
+ *
296
+ * @param date - Target trading day whose boolean is computed in-memory.
297
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
298
+ * @param range - Optional filter applied to the returned bars.
299
+ */
300
+ previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<DailyBar[]>;
233
301
  }
234
302
 
235
303
  declare class AllocationHandle {
@@ -339,10 +407,46 @@ declare class StrategyHandle {
339
407
  private _getLatestStrategySeriesDate;
340
408
  private _ensureFresh;
341
409
  private _sync;
410
+ /**
411
+ * Pure evaluate — runs the same pipeline as _sync but returns the computed
412
+ * evaluation instead of persisting. Used by both _sync (post-close write
413
+ * path) and previewAllocation (pre-close read-only path).
414
+ *
415
+ * The `market === this._market` identity check is what distinguishes the two
416
+ * paths: when they are the same object the method takes the write path (syncing
417
+ * signals through storage as normal); when they differ it takes the read-only
418
+ * preview path (historical bars from storage, today's value computed in-memory
419
+ * via `computeAt`). Callers that want the preview path must therefore supply a
420
+ * *different* market object — for example one produced by `createQuoteOverlay`.
421
+ */
422
+ private _evaluate;
342
423
  private _querySeriesFromDb;
343
424
  series(range?: DateRange): Promise<StrategyBar[]>;
344
425
  value(date?: string): Promise<AllocationHandle | null>;
345
426
  simulate(options: SimulateOptions): Promise<SimulationHandle>;
427
+ /**
428
+ * Preview the allocation this strategy would produce for `date` if today
429
+ * closed at the provided raw quote prices. Does NOT write to strategies_series,
430
+ * signals_series, or indicators_series. Safe to call before market close.
431
+ *
432
+ * @param date - The trading day to preview (must be in tradingDays.getRange()).
433
+ * @param quoteOverrides - Raw (unleveraged) live prices keyed by ticker symbol.
434
+ * Symbols absent from this map will fall back to yesterday's close via the
435
+ * quote overlay.
436
+ * @returns The AllocationHandle for `date`, or null if the strategy has no
437
+ * evaluable entry for that date.
438
+ */
439
+ previewAllocation(date: string, quoteOverrides: Record<string, number>): Promise<AllocationHandle | null>;
440
+ /**
441
+ * Read-only preview of the strategy's allocation series including `date`.
442
+ * Returns stored historical allocations plus an in-memory bar at `date`
443
+ * computed via the same overlay path as `previewAllocation`.
444
+ *
445
+ * @param date - Target trading day to splice in-memory via overlay market.
446
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
447
+ * @param range - Optional filter applied to the returned bars.
448
+ */
449
+ previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<StrategyBar[]>;
346
450
  private _fetchPricesForTickers;
347
451
  private _fetchRawClosePrices;
348
452
  }
package/dist/index.js CHANGED
@@ -238,7 +238,40 @@ function getComputation(type) {
238
238
  return COMPUTATIONS[type] ?? null;
239
239
  }
240
240
 
241
+ // src/providers/quote-overlay.ts
242
+ function createQuoteOverlay(base, overridesByDate, options = {}) {
243
+ return {
244
+ async fetchBars(symbol, from) {
245
+ const bars = await base.fetchBars(symbol, from);
246
+ const dates = Object.keys(overridesByDate).sort();
247
+ if (dates.length === 0) return bars;
248
+ const result = [...bars];
249
+ for (const date of dates) {
250
+ const overrideValue = overridesByDate[date][symbol];
251
+ let value = overrideValue;
252
+ if (value === void 0) {
253
+ if (!options.fallbackMissingQuotes) continue;
254
+ if (result.length === 0) continue;
255
+ value = result[result.length - 1].value;
256
+ }
257
+ const existingIdx = result.findIndex((b) => b.date === date);
258
+ if (existingIdx >= 0) {
259
+ result[existingIdx] = { date, value };
260
+ } else {
261
+ result.push({ date, value });
262
+ }
263
+ }
264
+ return result;
265
+ }
266
+ };
267
+ }
268
+
241
269
  // src/handles/indicator.ts
270
+ function _subtractCalendarDays(date, days) {
271
+ const d = new Date(date);
272
+ d.setUTCDate(d.getUTCDate() - days);
273
+ return d.toISOString().slice(0, 10);
274
+ }
242
275
  var IndicatorHandle = class _IndicatorHandle {
243
276
  type;
244
277
  ticker;
@@ -365,23 +398,8 @@ var IndicatorHandle = class _IndicatorHandle {
365
398
  case "none":
366
399
  return;
367
400
  }
368
- const leverage = this.ticker?.leverage ?? 1;
369
- const isRate = isRateTickerSymbol(this.ticker?.symbol ?? null);
370
- if (leverage !== 1 && info.provider !== "computed" && !isRate && bars.length > 0) {
371
- let anchor;
372
- if (fromDate) {
373
- const lastStored = await this._storage.indicators.getValue(this._resolvedId, fromDate);
374
- anchor = lastStored ?? bars[0].value;
375
- } else {
376
- anchor = bars[0].value;
377
- }
378
- const leveraged = [{ date: bars[0].date, value: anchor }];
379
- for (let i = 1; i < bars.length; i++) {
380
- const dailyReturn = (bars[i].value - bars[i - 1].value) / bars[i - 1].value;
381
- const prev = leveraged[i - 1].value;
382
- leveraged.push({ date: bars[i].date, value: prev * (1 + leverage * dailyReturn) });
383
- }
384
- bars = leveraged;
401
+ if (info.provider !== "computed") {
402
+ bars = await this._applyLeverage(bars, fromDate);
385
403
  }
386
404
  bars = bars.filter((b) => b.date <= latestClosed);
387
405
  if (bars.length > 0) {
@@ -396,6 +414,103 @@ var IndicatorHandle = class _IndicatorHandle {
396
414
  const { id } = await this.resolve();
397
415
  return this._storage.indicators.getSeries(id, range);
398
416
  }
417
+ withMarket(market) {
418
+ if (market === this._market) return this;
419
+ return _IndicatorHandle.fromResolved(this._storage, market, this.id, {
420
+ type: this.type,
421
+ ticker: this.ticker,
422
+ lookback: this.lookback,
423
+ delay: this.delay,
424
+ unit: this.unit,
425
+ threshold: this.threshold
426
+ });
427
+ }
428
+ /**
429
+ * Apply leverage compounding to a raw bar series, anchored to a stored
430
+ * leveraged value. Used by both `_sync` and `computeAt` so they stay
431
+ * consistent.
432
+ *
433
+ * `anchorDate` is the date of the last *already-stored* leveraged bar
434
+ * (i.e., the bar just before `rawBars[0]`). The stored leveraged value
435
+ * at that date becomes `leveraged[0]`; raw returns are then compounded
436
+ * forward for each subsequent bar.
437
+ *
438
+ * If no stored anchor exists (first-ever sync), falls back to rawBars[0]
439
+ * as the starting raw value — identical to `_sync`'s behaviour.
440
+ */
441
+ async _applyLeverage(rawBars, anchorDate) {
442
+ const leverage = this.ticker?.leverage ?? 1;
443
+ if (leverage === 1 || rawBars.length === 0) return rawBars;
444
+ if (isRateTickerSymbol(this.ticker?.symbol ?? null)) return rawBars;
445
+ let anchor;
446
+ if (anchorDate) {
447
+ const lastStored = await this._storage.indicators.getValue(this._resolvedId, anchorDate);
448
+ anchor = lastStored ?? rawBars[0].value;
449
+ } else {
450
+ anchor = rawBars[0].value;
451
+ }
452
+ const leveraged = [{ date: rawBars[0].date, value: anchor }];
453
+ for (let i = 1; i < rawBars.length; i++) {
454
+ const dailyReturn = (rawBars[i].value - rawBars[i - 1].value) / rawBars[i - 1].value;
455
+ const prev = leveraged[i - 1].value;
456
+ leveraged.push({ date: rawBars[i].date, value: prev * (1 + leverage * dailyReturn) });
457
+ }
458
+ return leveraged;
459
+ }
460
+ /**
461
+ * Compute the indicator's value at `date` using the given market (typically
462
+ * an overlay market for pre-close preview). Pure — no writes to storage.
463
+ *
464
+ * For fetched types (yahoo/fred): fetches a small window of bars from
465
+ * `market`, applies leverage compounding anchored to the stored leveraged
466
+ * value at the bar before `date`.
467
+ * For computed types (SMA, RSI, etc.): fetches enough raw price bars to
468
+ * cover the indicator's lookback from `market`, applies leverage anchored
469
+ * to the stored value just before the fetch window, runs the computation,
470
+ * and returns the value at `date`.
471
+ * For Threshold: returns the threshold constant.
472
+ * For calendar: computes calendar value from the trading days list.
473
+ * Returns null if the value cannot be computed.
474
+ */
475
+ async computeAt(market, date) {
476
+ if (this.type === "Threshold") return this.threshold;
477
+ const tickerSymbol = this.ticker?.symbol ?? null;
478
+ const info = getProviderInfo(this.type, tickerSymbol);
479
+ if (info.provider === "none") return null;
480
+ if (info.provider === "calendar") {
481
+ const allDays = await this._storage.tradingDays.getRange();
482
+ const dayBars = allDays.map((d) => ({ date: d, value: 0 }));
483
+ const computed = computeCalendar(dayBars, this.type);
484
+ return computed.find((b) => b.date === date)?.value ?? null;
485
+ }
486
+ if (info.provider === "computed") {
487
+ const from2 = _subtractCalendarDays(date, this.lookback + 10);
488
+ const rawBars2 = await market.fetchBars(info.symbol, from2);
489
+ const anchorDate = rawBars2.length > 0 ? rawBars2[0].date : void 0;
490
+ const priceBars = await this._applyLeverage(rawBars2, anchorDate);
491
+ const computeFn = getComputation(this.type);
492
+ if (!computeFn) throw new Error(`No computation found for type "${this.type}"`);
493
+ const computed = computeFn(priceBars, this.lookback);
494
+ return computed.find((b) => b.date === date)?.value ?? null;
495
+ }
496
+ const symbol = info.provider === "yahoo" ? info.symbol : info.seriesId;
497
+ const from = _subtractCalendarDays(date, 5);
498
+ const rawBars = await market.fetchBars(symbol, from);
499
+ const leverage = this.ticker?.leverage ?? 1;
500
+ if (leverage === 1) {
501
+ return rawBars.find((b) => b.date === date)?.value ?? null;
502
+ }
503
+ const dateIdx = rawBars.findIndex((b) => b.date === date);
504
+ if (dateIdx < 0) return null;
505
+ const prevBar = rawBars[dateIdx - 1];
506
+ if (!prevBar) {
507
+ return rawBars[dateIdx].value;
508
+ }
509
+ const storedPrev = await this._storage.indicators.getValue(this._resolvedId, prevBar.date);
510
+ const leveragedPrev = storedPrev ?? prevBar.value;
511
+ const rawReturn = (rawBars[dateIdx].value - prevBar.value) / prevBar.value;
512
+ return leveragedPrev * (1 + leverage * rawReturn);
513
+ }
399
514
  // ── Public data access ─────────────────────────────────────────────
400
515
  async series(range) {
401
516
  if (this.type === "Threshold") {
@@ -417,6 +532,46 @@ var IndicatorHandle = class _IndicatorHandle {
417
532
  const { id } = await this.resolve();
418
533
  return this._storage.indicators.getValue(id, date);
419
534
  }
535
+ /**
536
+ * Read-only preview of the indicator series that includes an in-memory bar
537
+ * at `date` computed via `computeAt` against a quote-overlay market. Does
538
+ * NOT write to `indicators_series`. Safe to call before market close.
539
+ *
540
+ * @param date - Target trading day whose value is computed in-memory from
541
+ * the overridden quotes. Must be in `tradingDays.getRange()`.
542
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
543
+ * Symbols omitted here fall back to yesterday's close via the overlay.
544
+ * @param range - Optional filter applied to the returned bars.
545
+ * @returns Stored historical bars plus (or with) today's in-memory value.
546
+ */
547
+ async previewSeries(date, quoteOverrides, range) {
548
+ const tradingDays = await this._storage.tradingDays.getRange();
549
+ if (!tradingDays.includes(date)) {
550
+ throw new Error(`previewSeries: ${date} is not a trading day`);
551
+ }
552
+ const overlay = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });
553
+ let bars;
554
+ if (this.type === "Threshold") {
555
+ bars = await this._syntheticThresholdSeries();
556
+ } else {
557
+ bars = await this._querySeriesFromDb();
558
+ }
559
+ const todayValue = await this.computeAt(overlay, date);
560
+ if (todayValue !== null) {
561
+ const idx = bars.findIndex((b) => b.date === date);
562
+ if (idx >= 0) {
563
+ bars[idx] = { date, value: todayValue };
564
+ } else {
565
+ bars = [...bars, { date, value: todayValue }].sort((a, b) => a.date.localeCompare(b.date));
566
+ }
567
+ }
568
+ if (range) {
569
+ bars = bars.filter(
570
+ (b) => (range.from === void 0 || b.date >= range.from) && (range.to === void 0 || b.date <= range.to)
571
+ );
572
+ }
573
+ return bars;
574
+ }
420
575
  };
421
576
 
422
577
  // src/computations/signal.ts
@@ -589,6 +744,61 @@ var SignalHandle = class _SignalHandle {
589
744
  const { id } = await this.resolve();
590
745
  return this._storage.signals.getSeries(id, range);
591
746
  }
747
+ withMarket(market) {
748
+ if (market === this._market) return this;
749
+ return _SignalHandle.fromResolved(this._storage, market, this.id, {
750
+ indicator1: this.indicator1.withMarket(market),
751
+ indicator2: this.indicator2.withMarket(market),
752
+ comparison: this.comparison,
753
+ tolerance: this.tolerance
754
+ });
755
+ }
756
+ /**
757
+ * Compute the signal's boolean value at `date` using the given market
758
+ * (typically an overlay market for pre-close preview). Pure — no writes.
759
+ * Returns null if either indicator cannot produce a value at `date`.
760
+ *
761
+ * @param prevBool - The signal's boolean value at the bar immediately
762
+ * preceding `date`, used for hysteresis when `tolerance > 0`. If not
763
+ * provided, falls back to `storage.signals.getLastValue` (suitable for
764
+ * standalone callers). On the preview path `_evaluate` passes this from
765
+ * the in-memory `dateMap` so we never read stale storage.
766
+ */
767
+ async computeAt(market, date, prevBool) {
768
+ const [v1, v2] = await Promise.all([
769
+ this.indicator1.computeAt(market, date),
770
+ this.indicator2.computeAt(market, date)
771
+ ]);
772
+ if (v1 === null || v2 === null) return null;
773
+ const absolute = ABSOLUTE_TOLERANCE_TYPES.has(this.indicator1.type);
774
+ if (this.tolerance === 0) {
775
+ switch (this.comparison) {
776
+ case ">":
777
+ return v1 > v2;
778
+ case "<":
779
+ return v1 < v2;
780
+ case "=":
781
+ return v1 === v2;
782
+ }
783
+ }
784
+ const tolerance = this.tolerance;
785
+ const upper = absolute ? v2 + tolerance : v2 * (1 + tolerance / 100);
786
+ const lower = absolute ? v2 - tolerance : v2 * (1 - tolerance / 100);
787
+ if (this.comparison === "=") {
788
+ return v1 >= lower && v1 <= upper;
789
+ }
790
+ let resolvedPrevBool;
791
+ if (prevBool !== void 0 && prevBool !== null) {
792
+ resolvedPrevBool = prevBool;
793
+ } else {
794
+ const prev = await this._storage.signals.getLastValue(this.id);
795
+ resolvedPrevBool = prev === 1;
796
+ }
797
+ if (this.comparison === ">") {
798
+ return resolvedPrevBool ? v1 >= lower : v1 > upper;
799
+ }
800
+ return resolvedPrevBool ? v1 <= upper : v1 < lower;
801
+ }
592
802
  // ── Public data access ─────────────────────────────────────────────
593
803
  async series(range) {
594
804
  await this._ensureFresh();
@@ -606,6 +816,44 @@ var SignalHandle = class _SignalHandle {
606
816
  const { id } = await this.resolve();
607
817
  return this._storage.signals.getLastValue(id);
608
818
  }
819
+ /**
820
+ * Read-only preview of the signal series with an in-memory bar at `date`
821
+ * computed via `computeAt` against a quote-overlay market. Does NOT write
822
+ * to `signals_series`.
823
+ *
824
+ * @param date - Target trading day whose boolean is computed in-memory.
825
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
826
+ * @param range - Optional filter applied to the returned bars.
827
+ */
828
+ async previewSeries(date, quoteOverrides, range) {
829
+ const tradingDays = await this._storage.tradingDays.getRange();
830
+ if (!tradingDays.includes(date)) {
831
+ throw new Error(`previewSeries: ${date} is not a trading day`);
832
+ }
833
+ const overlay = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });
834
+ let bars = await this._querySeriesFromDb();
835
+ const dateMap = /* @__PURE__ */ new Map();
836
+ for (const bar of bars) dateMap.set(bar.date, bar.value === 1);
837
+ const limitIdx = tradingDays.indexOf(date);
838
+ const prevDate = limitIdx > 0 ? tradingDays[limitIdx - 1] : void 0;
839
+ const prevBool = prevDate !== void 0 ? dateMap.get(prevDate) ?? null : null;
840
+ const todayBool = await this.computeAt(overlay, date, prevBool);
841
+ if (todayBool !== null) {
842
+ const numeric = todayBool ? 1 : 0;
843
+ const idx = bars.findIndex((b) => b.date === date);
844
+ if (idx >= 0) {
845
+ bars[idx] = { date, value: numeric };
846
+ } else {
847
+ bars = [...bars, { date, value: numeric }].sort((a, b) => a.date.localeCompare(b.date));
848
+ }
849
+ }
850
+ if (range) {
851
+ bars = bars.filter(
852
+ (b) => (range.from === void 0 || b.date >= range.from) && (range.to === void 0 || b.date <= range.to)
853
+ );
854
+ }
855
+ return bars;
856
+ }
609
857
  };
610
858
 
611
859
  // src/handles/allocation.ts
@@ -1218,20 +1466,56 @@ var StrategyHandle = class {
1218
1466
  }
1219
1467
  async _sync(latestClosed) {
1220
1468
  const { id } = await this.resolve();
1221
- const signalSeries = /* @__PURE__ */ new Map();
1469
+ const { entries } = await this._evaluate(this._market, latestClosed);
1470
+ if (entries.length > 0) {
1471
+ await this._storage.strategies.writeSeries(id, entries);
1472
+ }
1473
+ }
1474
+ /**
1475
+ * Pure evaluate — runs the same pipeline as _sync but returns the computed
1476
+ * evaluation instead of persisting. Used by both _sync (post-close write
1477
+ * path) and previewAllocation (pre-close read-only path).
1478
+ *
1479
+ * The `market === this._market` identity check is what distinguishes the two
1480
+ * paths: when they are the same object the method takes the write path (syncing
1481
+ * signals through storage as normal); when they differ it takes the read-only
1482
+ * preview path (historical bars from storage, today's value computed in-memory
1483
+ * via `computeAt`). Callers that want the preview path must therefore supply a
1484
+ * *different* market object — for example one produced by `createQuoteOverlay`.
1485
+ */
1486
+ async _evaluate(market, limitDate) {
1222
1487
  const allSignals = /* @__PURE__ */ new Set();
1223
1488
  for (const rule of this._rules) {
1224
1489
  if (rule.when) rule.when.forEach((s) => allSignals.add(s));
1225
1490
  }
1226
- await Promise.all(
1227
- Array.from(allSignals).map(async (signal) => {
1228
- const bars = await signal.series();
1229
- const dateMap = /* @__PURE__ */ new Map();
1230
- for (const bar of bars) dateMap.set(bar.date, bar.value === 1);
1231
- signalSeries.set(signal.id, dateMap);
1232
- })
1233
- );
1491
+ const signalSeries = /* @__PURE__ */ new Map();
1234
1492
  const tradingDays = await this._storage.tradingDays.getRange();
1493
+ if (market === this._market) {
1494
+ await Promise.all(
1495
+ Array.from(allSignals).map(async (signal) => {
1496
+ const bars = await signal.withMarket(market).series();
1497
+ const dateMap = /* @__PURE__ */ new Map();
1498
+ for (const bar of bars) dateMap.set(bar.date, bar.value === 1);
1499
+ signalSeries.set(signal.id, dateMap);
1500
+ })
1501
+ );
1502
+ } else {
1503
+ const limitIdx = tradingDays.indexOf(limitDate);
1504
+ const prevDate = limitIdx > 0 ? tradingDays[limitIdx - 1] : void 0;
1505
+ await Promise.all(
1506
+ Array.from(allSignals).map(async (signal) => {
1507
+ const historicalBars = await this._storage.signals.getSeries(signal.id);
1508
+ const dateMap = /* @__PURE__ */ new Map();
1509
+ for (const bar of historicalBars) dateMap.set(bar.date, bar.value === 1);
1510
+ const prevBool = prevDate !== void 0 ? dateMap.get(prevDate) ?? null : null;
1511
+ const todayValue = await signal.computeAt(market, limitDate, prevBool);
1512
+ if (todayValue !== null) {
1513
+ dateMap.set(limitDate, todayValue);
1514
+ }
1515
+ signalSeries.set(signal.id, dateMap);
1516
+ })
1517
+ );
1518
+ }
1235
1519
  const rebalanceDates = computeRebalanceDates(tradingDays, this._freq, this._offset);
1236
1520
  const allocations = [];
1237
1521
  const allocIndexMap = /* @__PURE__ */ new Map();
@@ -1248,13 +1532,8 @@ var StrategyHandle = class {
1248
1532
  };
1249
1533
  });
1250
1534
  const evalResult = evaluateStrategy(signalSeries, rulesInput, rebalanceDates, tradingDays);
1251
- const entries = Array.from(evalResult.entries()).filter(([date]) => date <= latestClosed).map(([date, allocIdx]) => ({
1252
- date,
1253
- allocationId: allocations[allocIdx].id
1254
- }));
1255
- if (entries.length > 0) {
1256
- await this._storage.strategies.writeSeries(id, entries);
1257
- }
1535
+ const entries = Array.from(evalResult.entries()).filter(([date]) => date <= limitDate).map(([date, allocIdx]) => ({ date, allocationId: allocations[allocIdx].id }));
1536
+ return { allocations, entries };
1258
1537
  }
1259
1538
  async _querySeriesFromDb(range) {
1260
1539
  const { id } = await this.resolve();
@@ -1307,6 +1586,62 @@ var StrategyHandle = class {
1307
1586
  };
1308
1587
  return new SimulationHandle(result.series, result.trades, options.portfolio, finalState);
1309
1588
  }
1589
+ /**
1590
+ * Preview the allocation this strategy would produce for `date` if today
1591
+ * closed at the provided raw quote prices. Does NOT write to strategies_series,
1592
+ * signals_series, or indicators_series. Safe to call before market close.
1593
+ *
1594
+ * @param date - The trading day to preview (must be in tradingDays.getRange()).
1595
+ * @param quoteOverrides - Raw (unleveraged) live prices keyed by ticker symbol.
1596
+ * Symbols absent from this map will fall back to yesterday's close via the
1597
+ * quote overlay.
1598
+ * @returns The AllocationHandle for `date`, or null if the strategy has no
1599
+ * evaluable entry for that date.
1600
+ */
1601
+ async previewAllocation(date, quoteOverrides) {
1602
+ await this.resolve();
1603
+ const tradingDays = await this._storage.tradingDays.getRange();
1604
+ if (!tradingDays.includes(date)) {
1605
+ throw new Error(`previewAllocation: ${date} is not a trading day`);
1606
+ }
1607
+ const overlayMarket = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });
1608
+ const { allocations, entries } = await this._evaluate(overlayMarket, date);
1609
+ const target = entries.find((e) => e.date === date);
1610
+ if (!target) return null;
1611
+ const alloc = allocations.find((a) => a.id === target.allocationId);
1612
+ return alloc ?? this._allocationMap.get(target.allocationId) ?? null;
1613
+ }
1614
+ /**
1615
+ * Read-only preview of the strategy's allocation series including `date`.
1616
+ * Returns stored historical allocations plus an in-memory bar at `date`
1617
+ * computed via the same overlay path as `previewAllocation`.
1618
+ *
1619
+ * @param date - Target trading day to splice in-memory via overlay market.
1620
+ * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.
1621
+ * @param range - Optional filter applied to the returned bars.
1622
+ */
1623
+ async previewSeries(date, quoteOverrides, range) {
1624
+ await this.resolve();
1625
+ const tradingDays = await this._storage.tradingDays.getRange();
1626
+ if (!tradingDays.includes(date)) {
1627
+ throw new Error(`previewSeries: ${date} is not a trading day`);
1628
+ }
1629
+ const overlayMarket = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });
1630
+ const { allocations, entries } = await this._evaluate(overlayMarket, date);
1631
+ const allocById = /* @__PURE__ */ new Map();
1632
+ for (const a of allocations) allocById.set(a.id, a);
1633
+ for (const [id, a] of this._allocationMap) if (!allocById.has(id)) allocById.set(id, a);
1634
+ let bars = entries.map((e) => ({
1635
+ date: e.date,
1636
+ allocation: allocById.get(e.allocationId)
1637
+ }));
1638
+ if (range) {
1639
+ bars = bars.filter(
1640
+ (b) => (range.from === void 0 || b.date >= range.from) && (range.to === void 0 || b.date <= range.to)
1641
+ );
1642
+ }
1643
+ return bars;
1644
+ }
1310
1645
  async _fetchPricesForTickers(bars, from, to) {
1311
1646
  const tickerMap = /* @__PURE__ */ new Map();
1312
1647
  for (const bar of bars) {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/handles/ticker.ts","../src/providers/mappings.ts","../src/computations/sma.ts","../src/computations/ema.ts","../src/computations/rsi.ts","../src/computations/returns.ts","../src/computations/volatility.ts","../src/computations/drawdown.ts","../src/computations/calendar.ts","../src/computations/index.ts","../src/handles/indicator.ts","../src/computations/signal.ts","../src/handles/signal.ts","../src/handles/allocation.ts","../src/handles/strategy.ts","../src/computations/strategy.ts","../src/handles/portfolio.ts","../src/backtest/simulate.ts","../src/backtest/types.ts","../src/client.ts"],"sourcesContent":["import type { StorageProvider } from '../providers/storage';\n\nexport class TickerHandle {\n readonly symbol: string;\n readonly leverage: number;\n\n private _storage: StorageProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n constructor(storage: StorageProvider, symbol: string, leverage: number = 1) {\n this._storage = storage;\n this.symbol = symbol.toUpperCase();\n this.leverage = leverage;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('TickerHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(storage: StorageProvider, id: number, symbol: string, leverage: number): TickerHandle {\n const handle = new TickerHandle(storage, symbol, leverage);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const result = await this._storage.tickers.findOrCreate(this.symbol, this.leverage);\n this._resolvedId = result.id;\n return result;\n }\n}\n","import type { IndicatorType } from './types';\n\nexport type ProviderInfo =\n | { provider: 'yahoo'; symbol: string; rateSeries?: true }\n | { provider: 'fred'; seriesId: string; rateSeries?: true }\n | { provider: 'computed'; dependsOn: 'Price'; symbol: string; rateSeries?: true }\n | { provider: 'calendar' }\n | { provider: 'none' };\n\nconst FRED_SERIES: Record<string, string> = {\n T3M: 'DGS3MO',\n T6M: 'DGS6MO',\n T1Y: 'DGS1',\n T2Y: 'DGS2',\n T3Y: 'DGS3',\n T5Y: 'DGS5',\n T7Y: 'DGS7',\n T10Y: 'DGS10',\n T20Y: 'DGS20',\n T30Y: 'DGS30',\n};\n\n// Ticker symbols whose \"price\" values are rates/yields (expressed in percent),\n// not prices. For these, percent-change returns are both broken (divide by\n// zero / sign flips) and semantically wrong — callers should use absolute\n// differences instead.\nconst RATE_TICKER_SYMBOLS = new Set<string>([\n 'DTB3',\n 'DTB6',\n 'DFF',\n 'DGS3MO',\n 'DGS6MO',\n 'DGS1',\n 'DGS2',\n 'DGS3',\n 'DGS5',\n 'DGS7',\n 'DGS10',\n 'DGS20',\n 'DGS30',\n]);\n\nconst COMPUTED_TYPES = new Set<string>(['SMA', 'EMA', 'RSI', 'Return', 'Volatility', 'Drawdown']);\nconst CALENDAR_TYPES = new Set<string>(['Month', 'Day of Week', 'Day of Month', 'Day of Year']);\n\nexport function isRateTickerSymbol(symbol: string | null): boolean {\n return symbol != null && RATE_TICKER_SYMBOLS.has(symbol);\n}\n\nexport function getProviderInfo(type: IndicatorType, tickerSymbol: string | null): ProviderInfo {\n if (type === 'Price') {\n const info: ProviderInfo = { provider: 'yahoo', symbol: tickerSymbol! };\n if (isRateTickerSymbol(tickerSymbol)) info.rateSeries = true;\n return info;\n }\n if (type === 'VIX') return { provider: 'yahoo', symbol: '^VIX' };\n if (type === 'VIX3M') return { provider: 'yahoo', symbol: '^VIX3M' };\n\n if (type in FRED_SERIES) return { provider: 'fred', seriesId: FRED_SERIES[type]!, rateSeries: true };\n\n if (COMPUTED_TYPES.has(type)) {\n const info: ProviderInfo = { provider: 'computed', dependsOn: 'Price', symbol: tickerSymbol! };\n if (isRateTickerSymbol(tickerSymbol)) info.rateSeries = true;\n return info;\n }\n\n if (CALENDAR_TYPES.has(type)) return { provider: 'calendar' };\n\n return { provider: 'none' };\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeSma(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const result: DailyBar[] = [];\n let sum = 0;\n for (let i = 0; i < lookback; i++) sum += bars[i].value;\n result.push({ date: bars[lookback - 1].date, value: sum / lookback });\n for (let i = lookback; i < bars.length; i++) {\n sum += bars[i].value - bars[i - lookback].value;\n result.push({ date: bars[i].date, value: sum / lookback });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeEma(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const multiplier = 2 / (lookback + 1);\n const result: DailyBar[] = [];\n let sum = 0;\n for (let i = 0; i < lookback; i++) sum += bars[i].value;\n let ema = sum / lookback;\n result.push({ date: bars[lookback - 1].date, value: ema });\n for (let i = lookback; i < bars.length; i++) {\n ema = bars[i].value * multiplier + ema * (1 - multiplier);\n result.push({ date: bars[i].date, value: ema });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeRsi(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback + 1) return [];\n const changes: number[] = [];\n for (let i = 1; i < bars.length; i++) {\n changes.push(bars[i].value - bars[i - 1].value);\n }\n let avgGain = 0;\n let avgLoss = 0;\n for (let i = 0; i < lookback; i++) {\n if (changes[i] > 0) avgGain += changes[i];\n else avgLoss += Math.abs(changes[i]);\n }\n avgGain /= lookback;\n avgLoss /= lookback;\n const result: DailyBar[] = [];\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n result.push({\n date: bars[lookback].date,\n value: avgLoss === 0 ? 100 : 100 - 100 / (1 + rs),\n });\n for (let i = lookback; i < changes.length; i++) {\n const gain = changes[i] > 0 ? changes[i] : 0;\n const loss = changes[i] < 0 ? Math.abs(changes[i]) : 0;\n avgGain = (avgGain * (lookback - 1) + gain) / lookback;\n avgLoss = (avgLoss * (lookback - 1) + loss) / lookback;\n const smoothRs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n result.push({\n date: bars[i + 1].date,\n value: avgLoss === 0 ? 100 : 100 - 100 / (1 + smoothRs),\n });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport type ReturnMode = 'pct' | 'abs';\n\nexport function computeReturns(bars: DailyBar[], lookback: number, mode: ReturnMode = 'pct'): DailyBar[] {\n if (bars.length <= lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback; i < bars.length; i++) {\n const curr = bars[i]!.value;\n const prev = bars[i - lookback]!.value;\n const value = mode === 'abs' ? curr - prev : (curr - prev) / prev;\n result.push({ date: bars[i]!.date, value });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeVolatility(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback + 1) return [];\n const dailyReturns: { date: string; value: number }[] = [];\n for (let i = 1; i < bars.length; i++) {\n dailyReturns.push({\n date: bars[i].date,\n value: bars[i].value / bars[i - 1].value - 1,\n });\n }\n if (dailyReturns.length < lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback - 1; i < dailyReturns.length; i++) {\n const window = dailyReturns.slice(i - lookback + 1, i + 1);\n const mean = window.reduce((s, r) => s + r.value, 0) / lookback;\n const variance = window.reduce((s, r) => s + (r.value - mean) ** 2, 0) / lookback;\n result.push({ date: dailyReturns[i].date, value: Math.sqrt(variance) });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeDrawdown(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback - 1; i < bars.length; i++) {\n let max = -Infinity;\n for (let j = i - lookback + 1; j <= i; j++) {\n if (bars[j].value > max) max = bars[j].value;\n }\n result.push({ date: bars[i].date, value: (bars[i].value - max) / max });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\ntype CalendarPeriod = 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year';\n\nfunction dayOfYear(d: Date): number {\n const start = new Date(d.getFullYear(), 0, 0);\n const diff = d.getTime() - start.getTime();\n return Math.floor(diff / (1000 * 60 * 60 * 24));\n}\n\nexport function computeCalendar(bars: DailyBar[], period: CalendarPeriod): DailyBar[] {\n return bars.map((bar) => {\n const [y, m, d] = bar.date.split('-').map(Number);\n const date = new Date(y, m - 1, d);\n let value: number;\n switch (period) {\n case 'Month':\n value = date.getMonth() + 1;\n break;\n case 'Day of Week':\n value = date.getDay();\n break;\n case 'Day of Month':\n value = date.getDate();\n break;\n case 'Day of Year':\n value = dayOfYear(date);\n break;\n }\n return { date: bar.date, value };\n });\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { IndicatorType } from '../providers/types';\nimport { computeSma } from './sma';\nimport { computeEma } from './ema';\nimport { computeRsi } from './rsi';\nimport { computeReturns } from './returns';\nimport { computeVolatility } from './volatility';\nimport { computeDrawdown } from './drawdown';\n\nexport { computeSma } from './sma';\nexport { computeEma } from './ema';\nexport { computeRsi } from './rsi';\nexport { computeReturns } from './returns';\nexport { computeVolatility } from './volatility';\nexport { computeDrawdown } from './drawdown';\nexport { computeCalendar } from './calendar';\ntype ComputeFn = (bars: DailyBar[], lookback: number) => DailyBar[];\n\nconst COMPUTATIONS: Partial<Record<IndicatorType, ComputeFn>> = {\n SMA: computeSma,\n EMA: computeEma,\n RSI: computeRsi,\n Return: computeReturns,\n Volatility: computeVolatility,\n Drawdown: computeDrawdown,\n};\n\nexport function getComputation(type: IndicatorType): ComputeFn | null {\n return COMPUTATIONS[type] ?? null;\n}\n","import type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { IndicatorType, Unit } from '../providers/types';\nimport { TickerHandle } from './ticker';\nimport { getProviderInfo, isRateTickerSymbol } from '../providers/mappings';\nimport { getComputation } from '../computations/index';\nimport { computeReturns } from '../computations/returns';\nimport { computeCalendar } from '../computations/calendar';\n\nexport interface DailyBar {\n date: string;\n value: number;\n}\n\nexport interface IndicatorIdentity {\n type: IndicatorType;\n ticker: TickerHandle | null;\n lookback: number;\n delay: number;\n unit: Unit | null;\n threshold: number | null;\n}\n\nexport interface DateRange {\n from?: string;\n to?: string;\n}\n\nexport class IndicatorHandle {\n readonly type: IndicatorType;\n readonly ticker: TickerHandle | null;\n readonly lookback: number;\n readonly delay: number;\n readonly unit: Unit | null;\n readonly threshold: number | null;\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n private _cachedSeries: DailyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, identity: IndicatorIdentity) {\n this._storage = storage;\n this._market = market;\n this.type = identity.type;\n this.ticker = identity.ticker;\n this.lookback = identity.lookback;\n this.delay = identity.delay;\n this.unit = identity.unit;\n this.threshold = identity.threshold;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('IndicatorHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(\n storage: StorageProvider,\n market: MarketProvider,\n id: number,\n identity: IndicatorIdentity,\n ): IndicatorHandle {\n const handle = new IndicatorHandle(storage, market, identity);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const tickerId = this.ticker ? (await this.ticker.resolve()).id : null;\n const result = await this._storage.indicators.findOrCreate({\n type: this.type,\n tickerId,\n lookback: this.lookback,\n delay: this.delay,\n unit: this.unit,\n threshold: this.threshold,\n });\n this._resolvedId = result.id;\n return result;\n }\n\n // ── Freshness & Sync ───────────────────────────────────────────────\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestSeriesDate(indicatorId: number): Promise<string | null> {\n return this._storage.indicators.getLatestSeriesDate(indicatorId);\n }\n\n private async _ensureFresh(): Promise<void> {\n const { id } = await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n // In-memory cache still valid\n if (this._cachedAsOf === latestClosed) return;\n\n const latestSeries = await this._getLatestSeriesDate(id);\n\n if (latestSeries === latestClosed) {\n // DB is fresh — invalidate in-memory cache so next read picks up DB data\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n // Need to sync — deduplicate concurrent calls\n if (!this._syncing) {\n this._syncing = this._sync(latestSeries ?? undefined, latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(fromDate: string | undefined, latestClosed: string): Promise<void> {\n const tickerSymbol = this.ticker?.symbol ?? null;\n const info = getProviderInfo(this.type, tickerSymbol);\n\n let bars: DailyBar[];\n\n switch (info.provider) {\n case 'yahoo':\n bars = await this._market.fetchBars(info.symbol, fromDate);\n break;\n\n case 'fred':\n bars = await this._market.fetchBars(info.seriesId, fromDate);\n break;\n\n case 'computed': {\n // Create an internal Price handle for the same ticker\n const priceHandle = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker: this.ticker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n\n // Recursively ensure Price data is fresh\n await priceHandle._ensureFresh();\n\n // Read Price series from DB\n const priceBars = await priceHandle._querySeriesFromDb();\n\n if (this.type === 'Return') {\n // For rate/yield series (e.g. DTB3, DFF), percentage change is broken\n // near zero and semantically wrong; use absolute differences instead.\n bars = computeReturns(priceBars, this.lookback, info.rateSeries ? 'abs' : 'pct');\n } else {\n const computeFn = getComputation(this.type);\n if (!computeFn) throw new Error(`No computation found for type \"${this.type}\"`);\n bars = computeFn(priceBars, this.lookback);\n }\n\n // If incremental, filter to only new bars\n if (fromDate) {\n bars = bars.filter((b) => b.date > fromDate);\n }\n break;\n }\n\n case 'calendar': {\n // Fetch all trading days to compute calendar values\n const allDays = await this._storage.tradingDays.getRange();\n const dayBars: DailyBar[] = allDays.map((date) => ({ date, value: 0 }));\n bars = computeCalendar(dayBars, this.type as 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year');\n\n if (fromDate) {\n bars = bars.filter((b) => b.date > fromDate);\n }\n break;\n }\n\n case 'none':\n // Threshold indicators have no series to sync\n return;\n }\n\n // Apply leverage to daily returns only for fetched (non-computed) indicators.\n // Computed indicators (RSI, SMA, etc.) already read from the leveraged price series.\n // Rate tickers (DTB3, DFF, etc.) skip leverage compounding: the stored series\n // stays raw; the simulator applies the leverage multiplier at accrual time.\n const leverage = this.ticker?.leverage ?? 1;\n const isRate = isRateTickerSymbol(this.ticker?.symbol ?? null);\n if (leverage !== 1 && info.provider !== 'computed' && !isRate && bars.length > 0) {\n // For incremental syncs, anchor the leverage chain to the last stored\n // leveraged price so we continue from where we left off rather than\n // restarting from the raw Yahoo price.\n let anchor: number;\n if (fromDate) {\n const lastStored = await this._storage.indicators.getValue(this._resolvedId!, fromDate);\n anchor = lastStored ?? bars[0]!.value;\n } else {\n anchor = bars[0]!.value;\n }\n const leveraged: DailyBar[] = [{ date: bars[0]!.date, value: anchor }];\n for (let i = 1; i < bars.length; i++) {\n const dailyReturn = (bars[i]!.value - bars[i - 1]!.value) / bars[i - 1]!.value;\n const prev = leveraged[i - 1]!.value;\n leveraged.push({ date: bars[i]!.date, value: prev * (1 + leverage * dailyReturn) });\n }\n bars = leveraged;\n }\n\n // Filter bars up to latestClosed\n bars = bars.filter((b) => b.date <= latestClosed);\n\n if (bars.length > 0) {\n await this._upsertSeries(bars);\n }\n }\n\n private async _upsertSeries(bars: DailyBar[]): Promise<void> {\n const { id } = await this.resolve();\n await this._storage.indicators.writeSeries(id, bars);\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<DailyBar[]> {\n const { id } = await this.resolve();\n return this._storage.indicators.getSeries(id, range);\n }\n\n // ── Public data access ─────────────────────────────────────────────\n\n async series(range?: DateRange): Promise<DailyBar[]> {\n if (this.type === 'Threshold') {\n return this._syntheticThresholdSeries(range);\n }\n await this._ensureFresh();\n if (this._cachedSeries && !range) return this._cachedSeries;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cachedSeries = bars;\n return bars;\n }\n\n private async _syntheticThresholdSeries(range?: DateRange): Promise<DailyBar[]> {\n const v = this.threshold!;\n const dates = await this._storage.tradingDays.getRange(range);\n return dates.map((date) => ({ date, value: v }));\n }\n\n async value(date?: string): Promise<number | null> {\n await this._ensureFresh();\n const { id } = await this.resolve();\n return this._storage.indicators.getValue(id, date);\n }\n}\n","import type { DailyBar } from '../handles/indicator';\n\ntype Comparison = '>' | '<' | '=';\n\nfunction computeBuffers(v2: number, tolerance: number, absolute: boolean): { upper: number; lower: number } {\n if (tolerance === 0) return { upper: v2, lower: v2 };\n if (absolute) return { upper: v2 + tolerance, lower: v2 - tolerance };\n return { upper: v2 * (1 + tolerance / 100), lower: v2 * (1 - tolerance / 100) };\n}\n\nfunction rawCompare(v1: number, v2: number, comparison: Comparison): number {\n switch (comparison) {\n case '>':\n return v1 > v2 ? 1 : 0;\n case '<':\n return v1 < v2 ? 1 : 0;\n case '=':\n return v1 === v2 ? 1 : 0;\n }\n}\n\nexport function evaluateSignal(\n series1: DailyBar[],\n series2: DailyBar[],\n comparison: Comparison,\n tolerance: number,\n absolute: boolean,\n previousValue?: number,\n): DailyBar[] {\n const s2Map = new Map<string, number>();\n for (const bar of series2) {\n s2Map.set(bar.date, bar.value);\n }\n\n const result: DailyBar[] = [];\n let prev = previousValue;\n\n for (const bar1 of series1) {\n const v2 = s2Map.get(bar1.date);\n if (v2 === undefined) continue;\n\n const v1 = bar1.value;\n const { upper, lower } = computeBuffers(v2, tolerance, absolute);\n\n let value: number;\n\n if (tolerance === 0) {\n value = rawCompare(v1, v2, comparison);\n } else if (comparison === '=') {\n value = v1 >= lower && v1 <= upper ? 1 : 0;\n } else if (prev === undefined) {\n value = rawCompare(v1, v2, comparison);\n } else if (comparison === '>') {\n if (prev === 1) {\n value = v1 < lower ? 0 : 1;\n } else {\n value = v1 > upper ? 1 : 0;\n }\n } else {\n // comparison === '<'\n if (prev === 1) {\n value = v1 > upper ? 0 : 1;\n } else {\n value = v1 < lower ? 1 : 0;\n }\n }\n\n result.push({ date: bar1.date, value });\n prev = value;\n }\n\n return result;\n}\n","// src/handles/signal.ts\nimport type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { Comparison } from '../providers/types';\nimport type { IndicatorHandle, DailyBar, DateRange } from './indicator';\nimport { evaluateSignal } from '../computations/signal';\n\nconst ABSOLUTE_TOLERANCE_TYPES = new Set([\n 'Return',\n 'Volatility',\n 'Drawdown',\n 'VIX',\n 'VIX3M',\n 'T3M',\n 'T6M',\n 'T1Y',\n 'T2Y',\n 'T3Y',\n 'T5Y',\n 'T7Y',\n 'T10Y',\n 'T20Y',\n 'T30Y',\n]);\n\nexport interface SignalIdentity {\n indicator1: IndicatorHandle;\n indicator2: IndicatorHandle;\n comparison: Comparison;\n tolerance: number;\n}\n\nexport class SignalHandle {\n readonly indicator1: IndicatorHandle;\n readonly indicator2: IndicatorHandle;\n readonly comparison: Comparison;\n readonly tolerance: number;\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n private _cachedSeries: DailyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, identity: SignalIdentity) {\n this._storage = storage;\n this._market = market;\n this.indicator1 = identity.indicator1;\n this.indicator2 = identity.indicator2;\n this.comparison = identity.comparison;\n this.tolerance = identity.tolerance;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('SignalHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(\n storage: StorageProvider,\n market: MarketProvider,\n id: number,\n identity: SignalIdentity,\n ): SignalHandle {\n const handle = new SignalHandle(storage, market, identity);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const [ind1, ind2] = await Promise.all([this.indicator1.resolve(), this.indicator2.resolve()]);\n const result = await this._storage.signals.findOrCreate({\n indicatorId1: ind1.id,\n indicatorId2: ind2.id,\n comparison: this.comparison,\n tolerance: this.tolerance,\n });\n this._resolvedId = result.id;\n return result;\n }\n\n // ── Freshness & Sync ───────────────────────────────────────────────\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestSignalSeriesDate(signalId: number): Promise<string | null> {\n return this._storage.signals.getLatestSeriesDate(signalId);\n }\n\n private async _getLastSignalValue(signalId: number): Promise<number | null> {\n return this._storage.signals.getLastValue(signalId);\n }\n\n private async _ensureFresh(): Promise<void> {\n const { id } = await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n if (this._cachedAsOf === latestClosed) return;\n\n // Ensure both indicators are fresh first\n await Promise.all([this.indicator1.series(), this.indicator2.series()]);\n\n const latestSeries = await this._getLatestSignalSeriesDate(id);\n\n if (latestSeries === latestClosed) {\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n if (!this._syncing) {\n this._syncing = this._sync(latestSeries ?? undefined, latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(fromDate: string | undefined, latestClosed: string): Promise<void> {\n const { id } = await this.resolve();\n\n const range = fromDate ? { from: fromDate } : undefined;\n const [series1, series2] = await Promise.all([this.indicator1.series(range), this.indicator2.series(range)]);\n\n const previousValue = fromDate ? ((await this._getLastSignalValue(id)) ?? undefined) : undefined;\n\n const absolute = ABSOLUTE_TOLERANCE_TYPES.has(this.indicator1.type);\n const signalBars = evaluateSignal(series1, series2, this.comparison, this.tolerance, absolute, previousValue);\n\n const bars = signalBars.filter((b) => b.date <= latestClosed);\n\n if (bars.length > 0) {\n await this._upsertSeries(bars);\n }\n }\n\n private async _upsertSeries(bars: DailyBar[]): Promise<void> {\n const { id } = await this.resolve();\n await this._storage.signals.writeSeries(id, bars);\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<DailyBar[]> {\n const { id } = await this.resolve();\n return this._storage.signals.getSeries(id, range);\n }\n\n // ── Public data access ─────────────────────────────────────────────\n\n async series(range?: DateRange): Promise<DailyBar[]> {\n await this._ensureFresh();\n if (this._cachedSeries && !range) return this._cachedSeries;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cachedSeries = bars;\n return bars;\n }\n\n async value(date?: string): Promise<number | null> {\n await this._ensureFresh();\n if (date) {\n const series = await this._querySeriesFromDb({ from: date, to: date });\n return series.length > 0 ? series[0]!.value : null;\n }\n const { id } = await this.resolve();\n return this._storage.signals.getLastValue(id);\n }\n}\n","import type { StorageProvider } from '../providers/storage';\nimport { TickerHandle } from './ticker';\n\nexport class AllocationHandle {\n readonly holdings: [TickerHandle, number][];\n\n private _storage: StorageProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n constructor(storage: StorageProvider, holdings: [TickerHandle, number][]) {\n const total = holdings.reduce((sum, [, weight]) => sum + weight, 0);\n if (Math.abs(total - 1) > 1e-9) {\n throw new Error(`Allocation weights must sum to 1, got ${total}`);\n }\n this._storage = storage;\n this.holdings = holdings;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('AllocationHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(storage: StorageProvider, id: number, holdings: [TickerHandle, number][]): AllocationHandle {\n const handle = new AllocationHandle(storage, holdings);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n await Promise.all(this.holdings.map(([ticker]) => ticker.resolve()));\n\n const holdingsJson: Record<string, number> = {};\n for (const [ticker, weight] of this.holdings) {\n const key = ticker.leverage !== 1 ? `${ticker.symbol}?L=${ticker.leverage}` : ticker.symbol;\n holdingsJson[key] = weight;\n }\n\n const result = await this._storage.allocations.findOrCreate(holdingsJson);\n this._resolvedId = result.id;\n return result;\n }\n}\n","import { customAlphabet } from 'nanoid';\nimport type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { TradingFreq, StrategySeriesEntry } from '../providers/types';\nimport { SignalHandle } from './signal';\nimport { AllocationHandle } from './allocation';\nimport { TickerHandle } from './ticker';\nimport { IndicatorHandle } from './indicator';\nimport type { DateRange } from './indicator';\nimport { evaluateStrategy, computeRebalanceDates } from '../computations/strategy';\nimport { runSimulation } from '../backtest/simulate';\nimport { SimulationHandle } from '../backtest/types';\nimport type { SimulateOptions, FinalState } from '../backtest/types';\n\nconst nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 21);\n\nexport interface StrategyRule {\n when?: SignalHandle[];\n hold: AllocationHandle;\n}\n\nexport interface StrategyBar {\n date: string;\n allocation: AllocationHandle;\n}\n\nexport interface StrategyOptions {\n name: string;\n freq?: TradingFreq;\n offset?: number;\n rules: StrategyRule[];\n}\n\nexport class StrategyHandle {\n private _linkId: string | null;\n private _name: string | null;\n private _freq: TradingFreq;\n private _offset: number;\n private _rules: StrategyRule[];\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolvedLinkId: string | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n private _allocationMap: Map<number, AllocationHandle> = new Map();\n\n private _cache: StrategyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, optionsOrLinkId: StrategyOptions | string) {\n this._storage = storage;\n this._market = market;\n\n if (typeof optionsOrLinkId === 'string') {\n this._linkId = optionsOrLinkId;\n this._name = null;\n this._freq = 'Daily';\n this._offset = 0;\n this._rules = [];\n } else {\n const opts = optionsOrLinkId;\n if (opts.rules.length === 0) {\n throw new Error('Strategy must have at least one rule');\n }\n const lastRule = opts.rules[opts.rules.length - 1]!;\n if (lastRule.when && lastRule.when.length > 0) {\n throw new Error('Last rule must be a fallback (no when clause)');\n }\n for (let i = 0; i < opts.rules.length - 1; i++) {\n const rule = opts.rules[i]!;\n if (rule.when !== undefined && rule.when.length === 0) {\n throw new Error(\n `Rule ${i} has an empty when clause and will match unconditionally, making subsequent rules unreachable`,\n );\n }\n }\n this._linkId = null;\n this._name = opts.name;\n this._freq = opts.freq ?? 'Daily';\n this._offset = opts.offset ?? 0;\n this._rules = opts.rules;\n }\n }\n\n get id(): number {\n if (this._resolvedId == null) throw new Error('StrategyHandle not yet resolved. Call resolve() first.');\n return this._resolvedId;\n }\n\n get link(): string {\n if (this._resolvedLinkId == null) throw new Error('StrategyHandle not yet resolved. Call resolve() first.');\n return this._resolvedLinkId;\n }\n\n get name(): string | null {\n return this._name;\n }\n\n get freq(): TradingFreq {\n return this._freq;\n }\n\n get offset(): number {\n return this._offset;\n }\n\n get rules(): StrategyRule[] {\n return this._rules;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) {\n this._resolving =\n this._linkId !== null && this._name === null ? this._doResolveReference() : this._doResolveCreate();\n }\n return this._resolving;\n }\n\n private async _doResolveCreate(): Promise<{ id: number }> {\n const allSignals = new Set<SignalHandle>();\n const allAllocations = new Set<AllocationHandle>();\n for (const rule of this._rules) {\n if (rule.when) rule.when.forEach((s) => allSignals.add(s));\n allAllocations.add(rule.hold);\n }\n\n await Promise.all([\n ...Array.from(allSignals).map((s) => s.resolve()),\n ...Array.from(allAllocations).map((a) => a.resolve()),\n ]);\n\n const linkId = nanoid();\n const result = await this._storage.strategies.create({\n linkId,\n name: this._name!,\n freq: this._freq,\n offset: this._offset,\n rules: this._rules.map((rule) => ({\n signalIds: (rule.when ?? []).map((s) => s.id),\n allocationId: rule.hold.id,\n })),\n });\n\n this._resolvedId = result.id;\n this._resolvedLinkId = linkId;\n\n for (const rule of this._rules) {\n this._allocationMap.set(rule.hold.id, rule.hold);\n }\n\n return result;\n }\n\n private async _doResolveReference(): Promise<{ id: number }> {\n const ref = await this._storage.strategies.resolveReference(this._linkId!);\n this._resolvedId = ref.id;\n this._resolvedLinkId = this._linkId!;\n this._name = ref.name;\n this._freq = ref.freq;\n this._offset = ref.offset;\n\n // Build handles bottom-up from reference data\n const tickerMap = new Map<number, TickerHandle>();\n for (const t of ref.rules.tickers) {\n tickerMap.set(t.id, TickerHandle.fromResolved(this._storage, t.id, t.symbol, t.leverage));\n }\n\n const indicatorMap = new Map<number, IndicatorHandle>();\n for (const ind of ref.rules.indicators) {\n const ticker = ind.tickerId ? (tickerMap.get(ind.tickerId) ?? null) : null;\n indicatorMap.set(\n ind.id,\n IndicatorHandle.fromResolved(this._storage, this._market, ind.id, {\n type: ind.type,\n ticker,\n lookback: ind.lookback,\n delay: ind.delay,\n unit: ind.unit,\n threshold: ind.threshold,\n }),\n );\n }\n\n const signalMap = new Map<number, SignalHandle>();\n for (const sig of ref.rules.signals) {\n signalMap.set(\n sig.id,\n SignalHandle.fromResolved(this._storage, this._market, sig.id, {\n indicator1: indicatorMap.get(sig.indicatorId1)!,\n indicator2: indicatorMap.get(sig.indicatorId2)!,\n comparison: sig.comparison,\n tolerance: sig.tolerance,\n }),\n );\n }\n\n const allocationHandleMap = new Map<number, AllocationHandle>();\n for (const alloc of ref.rules.allocations) {\n const holdings: [TickerHandle, number][] = Object.entries(alloc.holdings).map(([key, weight]) => {\n const match = key.match(/^(.+)\\?L=(.+)$/);\n const symbol = match ? match[1]! : key;\n const leverage = match ? Number(match[2]) : 1;\n return [new TickerHandle(this._storage, symbol, leverage), weight];\n });\n const handle = AllocationHandle.fromResolved(this._storage, alloc.id, holdings);\n allocationHandleMap.set(alloc.id, handle);\n this._allocationMap.set(alloc.id, handle);\n }\n\n // Reconstruct rules\n this._rules = ref.rules.definition.map((rule) => ({\n when: rule.signalIds && rule.signalIds.length > 0 ? rule.signalIds.map((id) => signalMap.get(id)!) : undefined,\n hold: allocationHandleMap.get(rule.allocationId)!,\n }));\n\n return { id: ref.id };\n }\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestStrategySeriesDate(): Promise<string | null> {\n const { id } = await this.resolve();\n return this._storage.strategies.getLatestSeriesDate(id);\n }\n\n private async _ensureFresh(): Promise<void> {\n await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n if (this._cachedAsOf === latestClosed) return;\n\n const latestSeries = await this._getLatestStrategySeriesDate();\n\n if (latestSeries === latestClosed) {\n this._cache = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n if (!this._syncing) {\n this._syncing = this._sync(latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cache = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(latestClosed: string): Promise<void> {\n const { id } = await this.resolve();\n\n // Sync all signals and collect their series\n const signalSeries = new Map<number, Map<string, boolean>>();\n const allSignals = new Set<SignalHandle>();\n for (const rule of this._rules) {\n if (rule.when) rule.when.forEach((s) => allSignals.add(s));\n }\n\n await Promise.all(\n Array.from(allSignals).map(async (signal) => {\n const bars = await signal.series();\n const dateMap = new Map<string, boolean>();\n for (const bar of bars) dateMap.set(bar.date, bar.value === 1);\n signalSeries.set(signal.id, dateMap);\n }),\n );\n\n // Get all trading days\n const tradingDays = await this._storage.tradingDays.getRange();\n\n const rebalanceDates = computeRebalanceDates(tradingDays, this._freq, this._offset);\n\n // Build allocation index mapping\n const allocations: AllocationHandle[] = [];\n const allocIndexMap = new Map<number, number>();\n const rulesInput = this._rules.map((rule) => {\n let allocIdx = allocIndexMap.get(rule.hold.id);\n if (allocIdx === undefined) {\n allocIdx = allocations.length;\n allocations.push(rule.hold);\n allocIndexMap.set(rule.hold.id, allocIdx);\n }\n return {\n signalIds: (rule.when ?? []).map((s) => s.id),\n allocationIndex: allocIdx,\n };\n });\n\n // Evaluate\n const evalResult = evaluateStrategy(signalSeries, rulesInput, rebalanceDates, tradingDays);\n\n // Write strategy series\n const entries: StrategySeriesEntry[] = Array.from(evalResult.entries())\n .filter(([date]) => date <= latestClosed)\n .map(([date, allocIdx]) => ({\n date,\n allocationId: allocations[allocIdx]!.id,\n }));\n\n if (entries.length > 0) {\n await this._storage.strategies.writeSeries(id, entries);\n }\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<StrategyBar[]> {\n const { id } = await this.resolve();\n const entries = await this._storage.strategies.getSeries(id, range);\n return entries.map((e) => ({\n date: e.date,\n allocation: this._allocationMap.get(e.allocationId)!,\n }));\n }\n\n async series(range?: DateRange): Promise<StrategyBar[]> {\n await this._ensureFresh();\n if (this._cache && !range) return this._cache;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cache = bars;\n return bars;\n }\n\n async value(date?: string): Promise<AllocationHandle | null> {\n await this._ensureFresh();\n const bars = date ? await this._querySeriesFromDb({ from: date, to: date }) : await this._querySeriesFromDb();\n if (bars.length === 0) return null;\n return date ? bars[0]!.allocation : bars[bars.length - 1]!.allocation;\n }\n\n async simulate(options: SimulateOptions): Promise<SimulationHandle> {\n const bars = await this.series({ from: options.from, to: options.to });\n if (bars.length === 0) {\n return new SimulationHandle([], [], options.portfolio);\n }\n\n const prices = await this._fetchPricesForTickers(bars, options.from, options.to);\n const tradingDays = bars.map((b) => b.date);\n const rebalanceDates = computeRebalanceDates(tradingDays, this._freq, this._offset);\n\n // Force day 1 rebalance so existing positions align to strategy\n rebalanceDates.add(bars[0]!.date);\n\n const result = runSimulation(bars, prices, rebalanceDates, options.portfolio);\n\n // Build finalState for live push support\n const lastBar = bars[bars.length - 1]!;\n const lastDate = lastBar.date;\n const lastAllocation = lastBar.allocation;\n\n // leveragedPrices: keyed as \"symbol:leverage\", values are the leveraged prices from _fetchPricesForTickers\n const leveragedPrices: Record<string, number> = {};\n for (const [ticker, _weight] of lastAllocation.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const key = `${ticker.symbol}:${ticker.leverage}`;\n const price = prices[key]?.[lastDate];\n if (price != null) leveragedPrices[key] = price;\n }\n\n // closePrices: raw (unleveraged) close prices for computing real returns\n const closePrices: Record<string, number> = {};\n await this._fetchRawClosePrices(bars, lastDate, closePrices);\n\n const finalState: FinalState = {\n portfolio: result.finalPortfolio,\n allocation: lastAllocation,\n closePrices,\n leveragedPrices,\n };\n\n return new SimulationHandle(result.series, result.trades, options.portfolio, finalState);\n }\n\n private async _fetchPricesForTickers(\n bars: StrategyBar[],\n from: string,\n to: string,\n ): Promise<Record<string, Record<string, number>>> {\n const tickerMap = new Map<string, TickerHandle>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n const key = `${ticker.symbol}:${ticker.leverage}`;\n if (!tickerMap.has(key)) {\n tickerMap.set(key, ticker);\n }\n }\n }\n\n const entries = await Promise.all(\n Array.from(tickerMap.entries()).map(async ([key, ticker]) => {\n const priceIndicator = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n const priceBars = await priceIndicator.series({ from, to });\n const dateMap: Record<string, number> = {};\n for (const bar of priceBars) {\n dateMap[bar.date] = bar.value;\n }\n return [key, dateMap] as const;\n }),\n );\n\n return Object.fromEntries(entries);\n }\n\n private async _fetchRawClosePrices(\n bars: StrategyBar[],\n lastDate: string,\n closePrices: Record<string, number>,\n ): Promise<void> {\n const symbols = new Set<string>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n if (ticker.symbol !== 'CASHX') symbols.add(ticker.symbol);\n }\n }\n\n await Promise.all(\n Array.from(symbols).map(async (symbol) => {\n const rawTicker = new TickerHandle(this._storage, symbol, 1);\n const priceIndicator = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker: rawTicker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n const priceBars = await priceIndicator.series({ from: lastDate, to: lastDate });\n if (priceBars.length > 0) {\n closePrices[symbol] = priceBars[0]!.value;\n }\n }),\n );\n }\n}\n","import type { TradingFreq } from '../providers/types';\n\nfunction getPeriodKey(dateStr: string, freq: TradingFreq): string {\n const d = new Date(dateStr + 'T00:00:00Z');\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth();\n\n switch (freq) {\n case 'Weekly': {\n const thu = new Date(d);\n thu.setUTCDate(thu.getUTCDate() + 3 - ((thu.getUTCDay() + 6) % 7));\n const yearStart = new Date(Date.UTC(thu.getUTCFullYear(), 0, 1));\n const weekNo = Math.ceil(((thu.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\n return `${thu.getUTCFullYear()}-W${weekNo}`;\n }\n case 'Monthly':\n return `${y}-${m}`;\n case 'Bi-monthly':\n return `${y}-${Math.floor(m / 2)}`;\n case 'Quarterly':\n return `${y}-Q${Math.floor(m / 3)}`;\n case 'Every 4 Months':\n return `${y}-${Math.floor(m / 4)}`;\n case 'Semiannually':\n return `${y}-H${Math.floor(m / 6)}`;\n case 'Yearly':\n return `${y}`;\n default:\n return `${y}-${m}`;\n }\n}\n\nexport function computeRebalanceDates(tradingDays: string[], freq: TradingFreq, offset: number): Set<string> {\n if (freq === 'Daily') return new Set(tradingDays);\n\n const groups = new Map<string, number[]>();\n for (let i = 0; i < tradingDays.length; i++) {\n const key = getPeriodKey(tradingDays[i], freq);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(i);\n }\n\n const result = new Set<string>();\n for (const indices of groups.values()) {\n const lastIdx = indices[indices.length - 1];\n const targetIdx = lastIdx - offset;\n if (targetIdx >= 0 && targetIdx < tradingDays.length) {\n result.add(tradingDays[targetIdx]);\n }\n }\n\n return result;\n}\n\nexport interface StrategyRuleInput {\n signalIds: number[];\n allocationIndex: number;\n}\n\nexport function evaluateStrategy(\n signalSeries: Map<number, Map<string, boolean>>,\n rules: StrategyRuleInput[],\n rebalanceDates: Set<string>,\n tradingDays: string[],\n): Map<string, number> {\n const result = new Map<string, number>();\n let current: number | undefined;\n\n for (const date of tradingDays) {\n if (rebalanceDates.has(date)) {\n for (const rule of rules) {\n if (rule.signalIds.length === 0) {\n current = rule.allocationIndex;\n break;\n }\n const allTrue = rule.signalIds.every((id) => signalSeries.get(id)?.get(date) ?? false);\n if (allTrue) {\n current = rule.allocationIndex;\n break;\n }\n }\n }\n if (current !== undefined) {\n result.set(date, current);\n }\n }\n\n return result;\n}\n","import { TickerHandle } from './ticker';\nimport type { Trade } from '../backtest/types';\nimport { AllocationHandle } from './allocation';\nimport { isRateTickerSymbol } from '../providers/mappings';\n\nexport class PortfolioHandle {\n readonly holdings: [TickerHandle, number][];\n\n constructor(holdings: [TickerHandle, number][]) {\n // Check for duplicates\n const seen = new Set<string>();\n for (const [ticker] of holdings) {\n const key = `${ticker.symbol}:${ticker.leverage}`;\n if (seen.has(key)) {\n throw new Error(`Duplicate ticker: ${ticker.symbol}`);\n }\n seen.add(key);\n }\n\n this.holdings = holdings;\n }\n\n private _priceMap(prices: [TickerHandle, number][]): Map<string, number> {\n const map = new Map<string, number>();\n for (const [ticker, price] of prices) {\n map.set(`${ticker.symbol}:${ticker.leverage}`, price);\n }\n return map;\n }\n\n private _priceFor(ticker: TickerHandle, priceMap: Map<string, number>): number {\n if (ticker.symbol === 'CASHX') return 1;\n if (isRateTickerSymbol(ticker.symbol)) return 1;\n const key = `${ticker.symbol}:${ticker.leverage}`;\n const price = priceMap.get(key);\n if (price == null) {\n throw new Error(`Missing price for ${ticker.symbol}`);\n }\n return price;\n }\n\n value(prices: [TickerHandle, number][]): number {\n const priceMap = this._priceMap(prices);\n let total = 0;\n for (const [ticker, quantity] of this.holdings) {\n total += quantity * this._priceFor(ticker, priceMap);\n }\n return total;\n }\n\n weights(prices: [TickerHandle, number][]): [TickerHandle, number][] {\n const total = this.value(prices);\n if (total === 0) return [];\n\n const priceMap = this._priceMap(prices);\n const result: [TickerHandle, number][] = [];\n for (const [ticker, quantity] of this.holdings) {\n const dollarValue = quantity * this._priceFor(ticker, priceMap);\n if (dollarValue === 0) continue;\n result.push([ticker, dollarValue / total]);\n }\n return result;\n }\n\n trades(target: AllocationHandle, prices: [TickerHandle, number][], date: string): Trade[] {\n const priceMap = this._priceMap(prices);\n const totalValue = this.value(prices);\n\n // Build current dollar amounts by symbol\n const currentDollars = new Map<string, number>();\n for (const [ticker, quantity] of this.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const price = this._priceFor(ticker, priceMap);\n currentDollars.set(ticker.symbol, quantity * price);\n }\n\n // Build target dollar amounts by symbol\n const targetDollars = new Map<string, number>();\n for (const [ticker, weight] of target.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n targetDollars.set(ticker.symbol, totalValue * weight);\n }\n\n // Build a symbol → TickerHandle lookup for price resolution\n const tickerBySymbol = new Map<string, TickerHandle>();\n for (const [ticker] of this.holdings) {\n if (ticker.symbol !== 'CASHX') tickerBySymbol.set(ticker.symbol, ticker);\n }\n for (const [ticker] of target.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const existing = tickerBySymbol.get(ticker.symbol);\n if (existing && existing.leverage !== ticker.leverage) {\n throw new Error(`Conflicting leverage for ${ticker.symbol}`);\n }\n tickerBySymbol.set(ticker.symbol, ticker);\n }\n\n // Collect all non-CASHX symbols from both sides\n const allSymbols = new Set([...currentDollars.keys(), ...targetDollars.keys()]);\n\n const sells: Trade[] = [];\n const buys: Trade[] = [];\n\n for (const symbol of allSymbols) {\n const current = currentDollars.get(symbol) ?? 0;\n const target$ = targetDollars.get(symbol) ?? 0;\n const delta = target$ - current;\n\n const ticker = tickerBySymbol.get(symbol)!;\n const price = this._priceFor(ticker, priceMap);\n\n const quantity = Math.abs(delta) / price;\n if (quantity < 1e-10) continue;\n\n const trade: Trade = { date, symbol, quantity, price, action: delta > 0 ? 'buy' : 'sell' };\n\n if (trade.action === 'sell') {\n sells.push(trade);\n } else {\n buys.push(trade);\n }\n }\n\n return [...sells, ...buys];\n }\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { StrategyBar } from '../handles/strategy';\nimport type { TickerHandle } from '../handles/ticker';\nimport type { Trade } from './types';\nimport { PortfolioHandle } from '../handles/portfolio';\nimport { isRateTickerSymbol } from '../providers/mappings';\n\nconst EPSILON = 1e-8;\n\nfunction tkey(symbol: string, leverage: number): string {\n return `${symbol}:${leverage}`;\n}\n\nfunction symbolFromKey(key: string): string {\n const idx = key.lastIndexOf(':');\n return idx === -1 ? key : key.slice(0, idx);\n}\n\nfunction isRateKey(key: string): boolean {\n return isRateTickerSymbol(symbolFromKey(key));\n}\n\nfunction navPriceForKey(\n key: string,\n date: string,\n prices: Record<string, Record<string, number>>,\n lastPrice: Record<string, number>,\n): number | undefined {\n if (isRateKey(key)) return 1;\n const live = prices[key]?.[date];\n if (live != null) {\n lastPrice[key] = live;\n return live;\n }\n return lastPrice[key];\n}\n\nfunction daysBetween(prevIsoDate: string, currIsoDate: string): number {\n // Both inputs are 'YYYY-MM-DD'. UTC midnight → diff in ms → days.\n const ms =\n Date.UTC(Number(currIsoDate.slice(0, 4)), Number(currIsoDate.slice(5, 7)) - 1, Number(currIsoDate.slice(8, 10))) -\n Date.UTC(Number(prevIsoDate.slice(0, 4)), Number(prevIsoDate.slice(5, 7)) - 1, Number(prevIsoDate.slice(8, 10)));\n return Math.round(ms / (1000 * 60 * 60 * 24));\n}\n\nexport function runSimulation(\n bars: StrategyBar[],\n prices: Record<string, Record<string, number>>,\n rebalanceDates: Set<string>,\n portfolio: PortfolioHandle,\n): { series: DailyBar[]; trades: Trade[]; finalPortfolio: PortfolioHandle } {\n const positions: Record<string, number> = {};\n const lastPrice: Record<string, number> = {};\n let cash = 0;\n for (const [ticker, quantity] of portfolio.holdings) {\n if (ticker.symbol === 'CASHX') {\n cash = quantity;\n } else {\n positions[tkey(ticker.symbol, ticker.leverage)] = quantity;\n }\n }\n const series: DailyBar[] = [];\n const trades: Trade[] = [];\n\n // Carry forward the last known close when today's price is missing so\n // a held position isn't silently valued at $0 (e.g. mutual fund NAV that\n // posts after the trading-day cutoff).\n function valuationPrice(key: string, date: string): number | undefined {\n return navPriceForKey(key, date, prices, lastPrice);\n }\n\n let prevDate: string | null = null;\n\n for (const bar of bars) {\n const date = bar.date;\n\n // Accrue interest on rate-ticker positions between the previous bar and today.\n if (prevDate != null) {\n const days = daysBetween(prevDate, date);\n if (days > 0) {\n for (const [key, shares] of Object.entries(positions)) {\n if (!isRateKey(key)) continue;\n const ratePct = prices[key]?.[prevDate];\n if (ratePct == null) continue;\n const leverage = Number(key.slice(key.lastIndexOf(':') + 1)) || 1;\n const factor = 1 + leverage * (ratePct / 100) * (days / 360);\n positions[key] = shares * factor;\n }\n }\n }\n\n if (rebalanceDates.has(date)) {\n // Compute current portfolio value before rebalancing\n let portfolioValue = cash;\n for (const [key, shares] of Object.entries(positions)) {\n const price = valuationPrice(key, date);\n if (price != null) portfolioValue += shares * price;\n }\n\n // Determine target holdings\n const targetWeights: Record<string, number> = {};\n for (const [ticker, weight] of bar.allocation.holdings) {\n targetWeights[tkey(ticker.symbol, ticker.leverage)] = weight;\n }\n\n // Compute target shares and execute trades\n const allKeys = new Set([...Object.keys(positions), ...Object.keys(targetWeights)]);\n for (const key of allKeys) {\n let price: number;\n if (isRateKey(key)) {\n price = 1;\n } else {\n const live = prices[key]?.[date];\n if (live == null || live <= 0) continue;\n price = live;\n }\n\n const currentShares = positions[key] ?? 0;\n const targetValue = portfolioValue * (targetWeights[key] ?? 0);\n const targetShares = targetValue / price;\n const delta = targetShares - currentShares;\n\n if (Math.abs(delta) <= EPSILON) continue;\n\n if (Math.abs(targetShares) <= EPSILON) {\n delete positions[key];\n } else {\n positions[key] = targetShares;\n }\n cash -= delta * price;\n\n trades.push({\n date,\n symbol: key.split(':')[0]!,\n quantity: Math.abs(delta),\n price,\n action: delta > 0 ? 'buy' : 'sell',\n });\n }\n\n if (Math.abs(cash) <= EPSILON) cash = 0;\n }\n\n // Compute end-of-day portfolio value\n let value = cash;\n for (const [key, shares] of Object.entries(positions)) {\n const price = valuationPrice(key, date);\n if (price != null) value += shares * price;\n }\n series.push({ date, value });\n prevDate = date;\n }\n\n // Build finalPortfolio from ending positions + cash\n const finalHoldings: [TickerHandle, number][] = [];\n\n // Map ticker keys back to TickerHandles from allocations and starting portfolio\n const tickerByKey = new Map<string, TickerHandle>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n const key = tkey(ticker.symbol, ticker.leverage);\n if (!tickerByKey.has(key)) {\n tickerByKey.set(key, ticker);\n }\n }\n }\n for (const [ticker] of portfolio.holdings) {\n const key = tkey(ticker.symbol, ticker.leverage);\n if (!tickerByKey.has(key)) {\n tickerByKey.set(key, ticker);\n }\n }\n\n for (const [key, shares] of Object.entries(positions)) {\n const ticker = tickerByKey.get(key);\n if (ticker && Math.abs(shares) > EPSILON) {\n finalHoldings.push([ticker, shares]);\n }\n }\n\n // Add CASHX\n const cashKey = tkey('CASHX', 1);\n const cashTicker = tickerByKey.get(cashKey) ?? portfolio.holdings.find(([t]) => t.symbol === 'CASHX')?.[0];\n if (cashTicker && Math.abs(cash) > EPSILON) {\n finalHoldings.push([cashTicker, cash]);\n }\n\n const finalPortfolio = new PortfolioHandle(finalHoldings);\n\n return { series, trades, finalPortfolio };\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { AllocationHandle } from '../handles/allocation';\nimport { PortfolioHandle } from '../handles/portfolio';\nimport type { TickerHandle } from '../handles/ticker';\n\nexport interface SimulateOptions {\n from: string;\n to: string;\n portfolio: PortfolioHandle;\n}\n\nexport interface Trade {\n date: string;\n symbol: string;\n quantity: number;\n price: number;\n action: 'buy' | 'sell';\n}\n\nexport interface PortfolioSnapshot {\n value: number;\n holdings: [TickerHandle, number][];\n weights: [TickerHandle, number][];\n pendingTrades: Trade[];\n}\n\nexport interface FinalState {\n portfolio: PortfolioHandle;\n allocation: AllocationHandle;\n closePrices: Record<string, number>;\n leveragedPrices: Record<string, number>;\n}\n\nexport class SimulationHandle {\n readonly series: DailyBar[];\n readonly trades: Trade[];\n readonly startingPortfolio: PortfolioHandle;\n\n private _portfolio: PortfolioHandle | null;\n private _currentAllocation: AllocationHandle | null;\n private _lastClosePrices: Record<string, number>;\n private _lastLeveragedPrices: Map<string, number>;\n private _currentLeveragedPrices: Map<string, number>;\n private _lastDate: string;\n\n constructor(series: DailyBar[], trades: Trade[], startingPortfolio: PortfolioHandle, finalState?: FinalState) {\n this.series = series;\n this.trades = trades;\n this.startingPortfolio = startingPortfolio;\n\n if (finalState) {\n this._portfolio = finalState.portfolio;\n this._currentAllocation = finalState.allocation;\n this._lastClosePrices = finalState.closePrices;\n this._lastLeveragedPrices = new Map(Object.entries(finalState.leveragedPrices));\n this._currentLeveragedPrices = new Map(Object.entries(finalState.leveragedPrices));\n this._lastDate = series.at(-1)?.date ?? '';\n } else {\n this._portfolio = null;\n this._currentAllocation = null;\n this._lastClosePrices = {};\n this._lastLeveragedPrices = new Map();\n this._currentLeveragedPrices = new Map();\n this._lastDate = '';\n }\n }\n\n push(...prices: [TickerHandle, number][]): PortfolioSnapshot {\n if (!this._portfolio || !this._currentAllocation) {\n return { value: 0, holdings: [], weights: [], pendingTrades: [] };\n }\n\n // Update leveraged prices from raw market prices\n for (const [ticker, realPrice] of prices) {\n if (ticker.symbol === 'CASHX') continue;\n const lastClose = this._lastClosePrices[ticker.symbol];\n if (lastClose == null) continue;\n\n const realReturn = (realPrice - lastClose) / lastClose;\n\n // Apply leverage to all portfolio tickers sharing this symbol\n for (const [held] of this._portfolio.holdings) {\n if (held.symbol !== ticker.symbol) continue;\n if (held.symbol === 'CASHX') continue;\n const key = `${held.symbol}:${held.leverage}`;\n const baseLeveragedPrice = this._lastLeveragedPrices.get(key);\n if (baseLeveragedPrice == null) continue;\n const leveragedReturn = held.leverage * realReturn;\n this._currentLeveragedPrices.set(key, baseLeveragedPrice * (1 + leveragedReturn));\n }\n }\n\n // Build price array for PortfolioHandle methods\n const priceArray: [TickerHandle, number][] = [];\n for (const [held] of this._portfolio.holdings) {\n if (held.symbol === 'CASHX') continue;\n const key = `${held.symbol}:${held.leverage}`;\n const price = this._currentLeveragedPrices.get(key);\n if (price != null) priceArray.push([held, price]);\n }\n\n return {\n value: this._portfolio.value(priceArray),\n holdings: this._portfolio.holdings,\n weights: this._portfolio.weights(priceArray),\n pendingTrades: this._portfolio.trades(this._currentAllocation, priceArray, this._lastDate),\n };\n }\n}\n","import type { StorageProvider } from './providers/storage';\nimport type { MarketProvider } from './providers/market';\nimport type { IndicatorType, Unit } from './providers/types';\nimport { TickerHandle } from './handles/ticker';\nimport { IndicatorHandle } from './handles/indicator';\nimport { SignalHandle } from './handles/signal';\nimport { AllocationHandle } from './handles/allocation';\nimport { StrategyHandle } from './handles/strategy';\nimport { PortfolioHandle } from './handles/portfolio';\nimport type { StrategyOptions } from './handles/strategy';\n\ntype TreasuryTenor = Extract<\n IndicatorType,\n 'T3M' | 'T6M' | 'T1Y' | 'T2Y' | 'T3Y' | 'T5Y' | 'T7Y' | 'T10Y' | 'T20Y' | 'T30Y'\n>;\ntype CalendarPeriod = Extract<IndicatorType, 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year'>;\n\ninterface IndicatorOpts {\n delay?: number;\n}\n\nexport interface LivefolioClient {\n ticker(symbol: string, leverage?: number): TickerHandle;\n\n // Ticker-bound\n sma(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n ema(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n price(ticker: TickerHandle, opts?: IndicatorOpts): IndicatorHandle;\n returns(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n volatility(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n drawdown(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n rsi(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n\n // Standalone\n vix(opts?: IndicatorOpts): IndicatorHandle;\n vix3m(opts?: IndicatorOpts): IndicatorHandle;\n treasury(tenor: TreasuryTenor, opts?: IndicatorOpts): IndicatorHandle;\n calendar(period: CalendarPeriod, opts?: IndicatorOpts): IndicatorHandle;\n\n // Threshold\n threshold(value: number, unit?: Unit): IndicatorHandle;\n\n // Signals\n gt(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n lt(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n eq(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n\n // Allocations\n allocation(...holdings: [TickerHandle, number][]): AllocationHandle;\n\n // Portfolios\n portfolio(...holdings: [TickerHandle, number][]): PortfolioHandle;\n\n // Strategies\n strategy(linkId: string): StrategyHandle;\n strategy(options: StrategyOptions): StrategyHandle;\n strategy(optionsOrLinkId: string | StrategyOptions): StrategyHandle;\n}\n\nexport interface LivefolioClientOptions {\n storage: StorageProvider;\n market: MarketProvider;\n}\n\nfunction tickerBound(\n storage: StorageProvider,\n market: MarketProvider,\n type: IndicatorType,\n ticker: TickerHandle,\n lookback: number,\n opts?: IndicatorOpts,\n): IndicatorHandle {\n return new IndicatorHandle(storage, market, {\n type,\n ticker,\n lookback,\n delay: opts?.delay ?? 0,\n unit: null,\n threshold: null,\n });\n}\n\nfunction standalone(\n storage: StorageProvider,\n market: MarketProvider,\n type: IndicatorType,\n opts?: IndicatorOpts,\n): IndicatorHandle {\n return new IndicatorHandle(storage, market, {\n type,\n ticker: null,\n lookback: 0,\n delay: opts?.delay ?? 0,\n unit: null,\n threshold: null,\n });\n}\n\nexport function createClient(options: LivefolioClientOptions): LivefolioClient {\n const { storage, market } = options;\n\n return {\n ticker: (symbol, leverage) => new TickerHandle(storage, symbol, leverage),\n\n sma: (ticker, lookback, opts?) => tickerBound(storage, market, 'SMA', ticker, lookback, opts),\n ema: (ticker, lookback, opts?) => tickerBound(storage, market, 'EMA', ticker, lookback, opts),\n price: (ticker, opts?) => tickerBound(storage, market, 'Price', ticker, 0, opts),\n returns: (ticker, lookback, opts?) => tickerBound(storage, market, 'Return', ticker, lookback, opts),\n volatility: (ticker, lookback, opts?) => tickerBound(storage, market, 'Volatility', ticker, lookback, opts),\n drawdown: (ticker, lookback, opts?) => tickerBound(storage, market, 'Drawdown', ticker, lookback, opts),\n rsi: (ticker, lookback, opts?) => tickerBound(storage, market, 'RSI', ticker, lookback, opts),\n\n vix: (opts?) => standalone(storage, market, 'VIX', opts),\n vix3m: (opts?) => standalone(storage, market, 'VIX3M', opts),\n treasury: (tenor, opts?) => standalone(storage, market, tenor, opts),\n calendar: (period, opts?) => standalone(storage, market, period, opts),\n\n threshold: (value, unit?) =>\n new IndicatorHandle(storage, market, {\n type: 'Threshold',\n ticker: null,\n lookback: 0,\n delay: 0,\n unit: unit ?? null,\n threshold: value,\n }),\n\n gt: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '>',\n tolerance: tolerance ?? 0,\n }),\n lt: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '<',\n tolerance: tolerance ?? 0,\n }),\n eq: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '=',\n tolerance: tolerance ?? 0,\n }),\n\n allocation: (...holdings) => new AllocationHandle(storage, holdings),\n\n portfolio: (...holdings) => new PortfolioHandle(holdings),\n\n strategy: (optionsOrLinkId: StrategyOptions | string) => new StrategyHandle(storage, market, optionsOrLinkId),\n };\n}\n"],"mappings":";AAEO,IAAM,eAAN,MAAM,cAAa;AAAA,EACf;AAAA,EACA;AAAA,EAED;AAAA,EACA,cAA6B;AAAA,EAC7B,aAA6C;AAAA,EAErD,YAAY,SAA0B,QAAgB,WAAmB,GAAG;AAC1E,SAAK,WAAW;AAChB,SAAK,SAAS,OAAO,YAAY;AACjC,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,KAAa;AACf,QAAI,KAAK,eAAe;AACtB,YAAM,IAAI,MAAM,+EAA+E;AACjG,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAmC;AACvC,QAAI,KAAK,eAAe,KAAM,QAAO,EAAE,IAAI,KAAK,YAAY;AAC5D,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,KAAK,WAAW;AACxD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,aAAa,SAA0B,IAAY,QAAgB,UAAgC;AACxG,UAAM,SAAS,IAAI,cAAa,SAAS,QAAQ,QAAQ;AACzD,WAAO,cAAc;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAsC;AAClD,UAAM,SAAS,MAAM,KAAK,SAAS,QAAQ,aAAa,KAAK,QAAQ,KAAK,QAAQ;AAClF,SAAK,cAAc,OAAO;AAC1B,WAAO;AAAA,EACT;AACF;;;AC9BA,IAAM,cAAsC;AAAA,EAC1C,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AACR;AAMA,IAAM,sBAAsB,oBAAI,IAAY;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAED,IAAM,iBAAiB,oBAAI,IAAY,CAAC,OAAO,OAAO,OAAO,UAAU,cAAc,UAAU,CAAC;AAChG,IAAM,iBAAiB,oBAAI,IAAY,CAAC,SAAS,eAAe,gBAAgB,aAAa,CAAC;AAEvF,SAAS,mBAAmB,QAAgC;AACjE,SAAO,UAAU,QAAQ,oBAAoB,IAAI,MAAM;AACzD;AAEO,SAAS,gBAAgB,MAAqB,cAA2C;AAC9F,MAAI,SAAS,SAAS;AACpB,UAAM,OAAqB,EAAE,UAAU,SAAS,QAAQ,aAAc;AACtE,QAAI,mBAAmB,YAAY,EAAG,MAAK,aAAa;AACxD,WAAO;AAAA,EACT;AACA,MAAI,SAAS,MAAO,QAAO,EAAE,UAAU,SAAS,QAAQ,OAAO;AAC/D,MAAI,SAAS,QAAS,QAAO,EAAE,UAAU,SAAS,QAAQ,SAAS;AAEnE,MAAI,QAAQ,YAAa,QAAO,EAAE,UAAU,QAAQ,UAAU,YAAY,IAAI,GAAI,YAAY,KAAK;AAEnG,MAAI,eAAe,IAAI,IAAI,GAAG;AAC5B,UAAM,OAAqB,EAAE,UAAU,YAAY,WAAW,SAAS,QAAQ,aAAc;AAC7F,QAAI,mBAAmB,YAAY,EAAG,MAAK,aAAa;AACxD,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,IAAI,IAAI,EAAG,QAAO,EAAE,UAAU,WAAW;AAE5D,SAAO,EAAE,UAAU,OAAO;AAC5B;;;ACnEO,SAAS,WAAW,MAAkB,UAA8B;AACzE,MAAI,KAAK,SAAS,SAAU,QAAO,CAAC;AACpC,QAAM,SAAqB,CAAC;AAC5B,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,UAAU,IAAK,QAAO,KAAK,CAAC,EAAE;AAClD,SAAO,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC,EAAE,MAAM,OAAO,MAAM,SAAS,CAAC;AACpE,WAAS,IAAI,UAAU,IAAI,KAAK,QAAQ,KAAK;AAC3C,WAAO,KAAK,CAAC,EAAE,QAAQ,KAAK,IAAI,QAAQ,EAAE;AAC1C,WAAO,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,MAAM,OAAO,MAAM,SAAS,CAAC;AAAA,EAC3D;AACA,SAAO;AACT;;;ACXO,SAAS,WAAW,MAAkB,UAA8B;AACzE,MAAI,KAAK,SAAS,SAAU,QAAO,CAAC;AACpC,QAAM,aAAa,KAAK,WAAW;AACnC,QAAM,SAAqB,CAAC;AAC5B,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,UAAU,IAAK,QAAO,KAAK,CAAC,EAAE;AAClD,MAAI,MAAM,MAAM;AAChB,SAAO,KAAK,EAAE,MAAM,KAAK,WAAW,CAAC,EAAE,MAAM,OAAO,IAAI,CAAC;AACzD,WAAS,IAAI,UAAU,IAAI,KAAK,QAAQ,KAAK;AAC3C,UAAM,KAAK,CAAC,EAAE,QAAQ,aAAa,OAAO,IAAI;AAC9C,WAAO,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,MAAM,OAAO,IAAI,CAAC;AAAA,EAChD;AACA,SAAO;AACT;;;ACbO,SAAS,WAAW,MAAkB,UAA8B;AACzE,MAAI,KAAK,SAAS,WAAW,EAAG,QAAO,CAAC;AACxC,QAAM,UAAoB,CAAC;AAC3B,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,YAAQ,KAAK,KAAK,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC,EAAE,KAAK;AAAA,EAChD;AACA,MAAI,UAAU;AACd,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AACjC,QAAI,QAAQ,CAAC,IAAI,EAAG,YAAW,QAAQ,CAAC;AAAA,QACnC,YAAW,KAAK,IAAI,QAAQ,CAAC,CAAC;AAAA,EACrC;AACA,aAAW;AACX,aAAW;AACX,QAAM,SAAqB,CAAC;AAC5B,QAAM,KAAK,YAAY,IAAI,MAAM,UAAU;AAC3C,SAAO,KAAK;AAAA,IACV,MAAM,KAAK,QAAQ,EAAE;AAAA,IACrB,OAAO,YAAY,IAAI,MAAM,MAAM,OAAO,IAAI;AAAA,EAChD,CAAC;AACD,WAAS,IAAI,UAAU,IAAI,QAAQ,QAAQ,KAAK;AAC9C,UAAM,OAAO,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI;AAC3C,UAAM,OAAO,QAAQ,CAAC,IAAI,IAAI,KAAK,IAAI,QAAQ,CAAC,CAAC,IAAI;AACrD,eAAW,WAAW,WAAW,KAAK,QAAQ;AAC9C,eAAW,WAAW,WAAW,KAAK,QAAQ;AAC9C,UAAM,WAAW,YAAY,IAAI,MAAM,UAAU;AACjD,WAAO,KAAK;AAAA,MACV,MAAM,KAAK,IAAI,CAAC,EAAE;AAAA,MAClB,OAAO,YAAY,IAAI,MAAM,MAAM,OAAO,IAAI;AAAA,IAChD,CAAC;AAAA,EACH;AACA,SAAO;AACT;;;AC9BO,SAAS,eAAe,MAAkB,UAAkB,OAAmB,OAAmB;AACvG,MAAI,KAAK,UAAU,SAAU,QAAO,CAAC;AACrC,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,UAAU,IAAI,KAAK,QAAQ,KAAK;AAC3C,UAAM,OAAO,KAAK,CAAC,EAAG;AACtB,UAAM,OAAO,KAAK,IAAI,QAAQ,EAAG;AACjC,UAAM,QAAQ,SAAS,QAAQ,OAAO,QAAQ,OAAO,QAAQ;AAC7D,WAAO,KAAK,EAAE,MAAM,KAAK,CAAC,EAAG,MAAM,MAAM,CAAC;AAAA,EAC5C;AACA,SAAO;AACT;;;ACZO,SAAS,kBAAkB,MAAkB,UAA8B;AAChF,MAAI,KAAK,SAAS,WAAW,EAAG,QAAO,CAAC;AACxC,QAAM,eAAkD,CAAC;AACzD,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,iBAAa,KAAK;AAAA,MAChB,MAAM,KAAK,CAAC,EAAE;AAAA,MACd,OAAO,KAAK,CAAC,EAAE,QAAQ,KAAK,IAAI,CAAC,EAAE,QAAQ;AAAA,IAC7C,CAAC;AAAA,EACH;AACA,MAAI,aAAa,SAAS,SAAU,QAAO,CAAC;AAC5C,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,WAAW,GAAG,IAAI,aAAa,QAAQ,KAAK;AACvD,UAAM,SAAS,aAAa,MAAM,IAAI,WAAW,GAAG,IAAI,CAAC;AACzD,UAAM,OAAO,OAAO,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,CAAC,IAAI;AACvD,UAAM,WAAW,OAAO,OAAO,CAAC,GAAG,MAAM,KAAK,EAAE,QAAQ,SAAS,GAAG,CAAC,IAAI;AACzE,WAAO,KAAK,EAAE,MAAM,aAAa,CAAC,EAAE,MAAM,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;AAAA,EACxE;AACA,SAAO;AACT;;;AClBO,SAAS,gBAAgB,MAAkB,UAA8B;AAC9E,MAAI,KAAK,SAAS,SAAU,QAAO,CAAC;AACpC,QAAM,SAAqB,CAAC;AAC5B,WAAS,IAAI,WAAW,GAAG,IAAI,KAAK,QAAQ,KAAK;AAC/C,QAAI,MAAM;AACV,aAAS,IAAI,IAAI,WAAW,GAAG,KAAK,GAAG,KAAK;AAC1C,UAAI,KAAK,CAAC,EAAE,QAAQ,IAAK,OAAM,KAAK,CAAC,EAAE;AAAA,IACzC;AACA,WAAO,KAAK,EAAE,MAAM,KAAK,CAAC,EAAE,MAAM,QAAQ,KAAK,CAAC,EAAE,QAAQ,OAAO,IAAI,CAAC;AAAA,EACxE;AACA,SAAO;AACT;;;ACTA,SAAS,UAAU,GAAiB;AAClC,QAAM,QAAQ,IAAI,KAAK,EAAE,YAAY,GAAG,GAAG,CAAC;AAC5C,QAAM,OAAO,EAAE,QAAQ,IAAI,MAAM,QAAQ;AACzC,SAAO,KAAK,MAAM,QAAQ,MAAO,KAAK,KAAK,GAAG;AAChD;AAEO,SAAS,gBAAgB,MAAkB,QAAoC;AACpF,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAM,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AAChD,UAAM,OAAO,IAAI,KAAK,GAAG,IAAI,GAAG,CAAC;AACjC,QAAI;AACJ,YAAQ,QAAQ;AAAA,MACd,KAAK;AACH,gBAAQ,KAAK,SAAS,IAAI;AAC1B;AAAA,MACF,KAAK;AACH,gBAAQ,KAAK,OAAO;AACpB;AAAA,MACF,KAAK;AACH,gBAAQ,KAAK,QAAQ;AACrB;AAAA,MACF,KAAK;AACH,gBAAQ,UAAU,IAAI;AACtB;AAAA,IACJ;AACA,WAAO,EAAE,MAAM,IAAI,MAAM,MAAM;AAAA,EACjC,CAAC;AACH;;;ACbA,IAAM,eAA0D;AAAA,EAC9D,KAAK;AAAA,EACL,KAAK;AAAA,EACL,KAAK;AAAA,EACL,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,UAAU;AACZ;AAEO,SAAS,eAAe,MAAuC;AACpE,SAAO,aAAa,IAAI,KAAK;AAC/B;;;ACDO,IAAM,kBAAN,MAAM,iBAAgB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED;AAAA,EACA;AAAA,EACA,cAA6B;AAAA,EAC7B,aAA6C;AAAA,EAE7C,gBAAmC;AAAA,EACnC,cAA6B;AAAA,EAC7B,WAAiC;AAAA,EAEzC,YAAY,SAA0B,QAAwB,UAA6B;AACzF,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,OAAO,SAAS;AACrB,SAAK,SAAS,SAAS;AACvB,SAAK,WAAW,SAAS;AACzB,SAAK,QAAQ,SAAS;AACtB,SAAK,OAAO,SAAS;AACrB,SAAK,YAAY,SAAS;AAAA,EAC5B;AAAA,EAEA,IAAI,KAAa;AACf,QAAI,KAAK,eAAe;AACtB,YAAM,IAAI,MAAM,kFAAkF;AACpG,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAmC;AACvC,QAAI,KAAK,eAAe,KAAM,QAAO,EAAE,IAAI,KAAK,YAAY;AAC5D,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,KAAK,WAAW;AACxD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,aACL,SACA,QACA,IACA,UACiB;AACjB,UAAM,SAAS,IAAI,iBAAgB,SAAS,QAAQ,QAAQ;AAC5D,WAAO,cAAc;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAsC;AAClD,UAAM,WAAW,KAAK,UAAU,MAAM,KAAK,OAAO,QAAQ,GAAG,KAAK;AAClE,UAAM,SAAS,MAAM,KAAK,SAAS,WAAW,aAAa;AAAA,MACzD,MAAM,KAAK;AAAA,MACX;AAAA,MACA,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,MAAM,KAAK;AAAA,MACX,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,cAAc,OAAO;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,MAAc,6BAA8C;AAC1D,UAAM,OAAO,MAAM,KAAK,SAAS,YAAY,gBAAgB;AAC7D,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,8BAA8B;AACzD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,qBAAqB,aAA6C;AAC9E,WAAO,KAAK,SAAS,WAAW,oBAAoB,WAAW;AAAA,EACjE;AAAA,EAEA,MAAc,eAA8B;AAC1C,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,UAAM,eAAe,MAAM,KAAK,2BAA2B;AAG3D,QAAI,KAAK,gBAAgB,aAAc;AAEvC,UAAM,eAAe,MAAM,KAAK,qBAAqB,EAAE;AAEvD,QAAI,iBAAiB,cAAc;AAEjC,WAAK,gBAAgB;AACrB,WAAK,cAAc;AACnB;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,MAAM,gBAAgB,QAAW,YAAY,EAAE,QAAQ,MAAM;AAChF,aAAK,WAAW;AAAA,MAClB,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAEX,SAAK,gBAAgB;AACrB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAc,MAAM,UAA8B,cAAqC;AACrF,UAAM,eAAe,KAAK,QAAQ,UAAU;AAC5C,UAAM,OAAO,gBAAgB,KAAK,MAAM,YAAY;AAEpD,QAAI;AAEJ,YAAQ,KAAK,UAAU;AAAA,MACrB,KAAK;AACH,eAAO,MAAM,KAAK,QAAQ,UAAU,KAAK,QAAQ,QAAQ;AACzD;AAAA,MAEF,KAAK;AACH,eAAO,MAAM,KAAK,QAAQ,UAAU,KAAK,UAAU,QAAQ;AAC3D;AAAA,MAEF,KAAK,YAAY;AAEf,cAAM,cAAc,IAAI,iBAAgB,KAAK,UAAU,KAAK,SAAS;AAAA,UACnE,MAAM;AAAA,UACN,QAAQ,KAAK;AAAA,UACb,UAAU;AAAA,UACV,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW;AAAA,QACb,CAAC;AAGD,cAAM,YAAY,aAAa;AAG/B,cAAM,YAAY,MAAM,YAAY,mBAAmB;AAEvD,YAAI,KAAK,SAAS,UAAU;AAG1B,iBAAO,eAAe,WAAW,KAAK,UAAU,KAAK,aAAa,QAAQ,KAAK;AAAA,QACjF,OAAO;AACL,gBAAM,YAAY,eAAe,KAAK,IAAI;AAC1C,cAAI,CAAC,UAAW,OAAM,IAAI,MAAM,kCAAkC,KAAK,IAAI,GAAG;AAC9E,iBAAO,UAAU,WAAW,KAAK,QAAQ;AAAA,QAC3C;AAGA,YAAI,UAAU;AACZ,iBAAO,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,QAC7C;AACA;AAAA,MACF;AAAA,MAEA,KAAK,YAAY;AAEf,cAAM,UAAU,MAAM,KAAK,SAAS,YAAY,SAAS;AACzD,cAAM,UAAsB,QAAQ,IAAI,CAAC,UAAU,EAAE,MAAM,OAAO,EAAE,EAAE;AACtE,eAAO,gBAAgB,SAAS,KAAK,IAAgE;AAErG,YAAI,UAAU;AACZ,iBAAO,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,QAAQ;AAAA,QAC7C;AACA;AAAA,MACF;AAAA,MAEA,KAAK;AAEH;AAAA,IACJ;AAMA,UAAM,WAAW,KAAK,QAAQ,YAAY;AAC1C,UAAM,SAAS,mBAAmB,KAAK,QAAQ,UAAU,IAAI;AAC7D,QAAI,aAAa,KAAK,KAAK,aAAa,cAAc,CAAC,UAAU,KAAK,SAAS,GAAG;AAIhF,UAAI;AACJ,UAAI,UAAU;AACZ,cAAM,aAAa,MAAM,KAAK,SAAS,WAAW,SAAS,KAAK,aAAc,QAAQ;AACtF,iBAAS,cAAc,KAAK,CAAC,EAAG;AAAA,MAClC,OAAO;AACL,iBAAS,KAAK,CAAC,EAAG;AAAA,MACpB;AACA,YAAM,YAAwB,CAAC,EAAE,MAAM,KAAK,CAAC,EAAG,MAAM,OAAO,OAAO,CAAC;AACrE,eAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,cAAM,eAAe,KAAK,CAAC,EAAG,QAAQ,KAAK,IAAI,CAAC,EAAG,SAAS,KAAK,IAAI,CAAC,EAAG;AACzE,cAAM,OAAO,UAAU,IAAI,CAAC,EAAG;AAC/B,kBAAU,KAAK,EAAE,MAAM,KAAK,CAAC,EAAG,MAAM,OAAO,QAAQ,IAAI,WAAW,aAAa,CAAC;AAAA,MACpF;AACA,aAAO;AAAA,IACT;AAGA,WAAO,KAAK,OAAO,CAAC,MAAM,EAAE,QAAQ,YAAY;AAEhD,QAAI,KAAK,SAAS,GAAG;AACnB,YAAM,KAAK,cAAc,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,MAAiC;AAC3D,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,UAAM,KAAK,SAAS,WAAW,YAAY,IAAI,IAAI;AAAA,EACrD;AAAA,EAEA,MAAc,mBAAmB,OAAwC;AACvE,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,WAAO,KAAK,SAAS,WAAW,UAAU,IAAI,KAAK;AAAA,EACrD;AAAA;AAAA,EAIA,MAAM,OAAO,OAAwC;AACnD,QAAI,KAAK,SAAS,aAAa;AAC7B,aAAO,KAAK,0BAA0B,KAAK;AAAA,IAC7C;AACA,UAAM,KAAK,aAAa;AACxB,QAAI,KAAK,iBAAiB,CAAC,MAAO,QAAO,KAAK;AAC9C,UAAM,OAAO,MAAM,KAAK,mBAAmB,KAAK;AAChD,QAAI,CAAC,MAAO,MAAK,gBAAgB;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,0BAA0B,OAAwC;AAC9E,UAAM,IAAI,KAAK;AACf,UAAM,QAAQ,MAAM,KAAK,SAAS,YAAY,SAAS,KAAK;AAC5D,WAAO,MAAM,IAAI,CAAC,UAAU,EAAE,MAAM,OAAO,EAAE,EAAE;AAAA,EACjD;AAAA,EAEA,MAAM,MAAM,MAAuC;AACjD,UAAM,KAAK,aAAa;AACxB,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,WAAO,KAAK,SAAS,WAAW,SAAS,IAAI,IAAI;AAAA,EACnD;AACF;;;ACvQA,SAAS,eAAe,IAAY,WAAmB,UAAqD;AAC1G,MAAI,cAAc,EAAG,QAAO,EAAE,OAAO,IAAI,OAAO,GAAG;AACnD,MAAI,SAAU,QAAO,EAAE,OAAO,KAAK,WAAW,OAAO,KAAK,UAAU;AACpE,SAAO,EAAE,OAAO,MAAM,IAAI,YAAY,MAAM,OAAO,MAAM,IAAI,YAAY,KAAK;AAChF;AAEA,SAAS,WAAW,IAAY,IAAY,YAAgC;AAC1E,UAAQ,YAAY;AAAA,IAClB,KAAK;AACH,aAAO,KAAK,KAAK,IAAI;AAAA,IACvB,KAAK;AACH,aAAO,KAAK,KAAK,IAAI;AAAA,IACvB,KAAK;AACH,aAAO,OAAO,KAAK,IAAI;AAAA,EAC3B;AACF;AAEO,SAAS,eACd,SACA,SACA,YACA,WACA,UACA,eACY;AACZ,QAAM,QAAQ,oBAAI,IAAoB;AACtC,aAAW,OAAO,SAAS;AACzB,UAAM,IAAI,IAAI,MAAM,IAAI,KAAK;AAAA,EAC/B;AAEA,QAAM,SAAqB,CAAC;AAC5B,MAAI,OAAO;AAEX,aAAW,QAAQ,SAAS;AAC1B,UAAM,KAAK,MAAM,IAAI,KAAK,IAAI;AAC9B,QAAI,OAAO,OAAW;AAEtB,UAAM,KAAK,KAAK;AAChB,UAAM,EAAE,OAAO,MAAM,IAAI,eAAe,IAAI,WAAW,QAAQ;AAE/D,QAAI;AAEJ,QAAI,cAAc,GAAG;AACnB,cAAQ,WAAW,IAAI,IAAI,UAAU;AAAA,IACvC,WAAW,eAAe,KAAK;AAC7B,cAAQ,MAAM,SAAS,MAAM,QAAQ,IAAI;AAAA,IAC3C,WAAW,SAAS,QAAW;AAC7B,cAAQ,WAAW,IAAI,IAAI,UAAU;AAAA,IACvC,WAAW,eAAe,KAAK;AAC7B,UAAI,SAAS,GAAG;AACd,gBAAQ,KAAK,QAAQ,IAAI;AAAA,MAC3B,OAAO;AACL,gBAAQ,KAAK,QAAQ,IAAI;AAAA,MAC3B;AAAA,IACF,OAAO;AAEL,UAAI,SAAS,GAAG;AACd,gBAAQ,KAAK,QAAQ,IAAI;AAAA,MAC3B,OAAO;AACL,gBAAQ,KAAK,QAAQ,IAAI;AAAA,MAC3B;AAAA,IACF;AAEA,WAAO,KAAK,EAAE,MAAM,KAAK,MAAM,MAAM,CAAC;AACtC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ACjEA,IAAM,2BAA2B,oBAAI,IAAI;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AASM,IAAM,eAAN,MAAM,cAAa;AAAA,EACf;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAED;AAAA,EACA;AAAA,EACA,cAA6B;AAAA,EAC7B,aAA6C;AAAA,EAE7C,gBAAmC;AAAA,EACnC,cAA6B;AAAA,EAC7B,WAAiC;AAAA,EAEzC,YAAY,SAA0B,QAAwB,UAA0B;AACtF,SAAK,WAAW;AAChB,SAAK,UAAU;AACf,SAAK,aAAa,SAAS;AAC3B,SAAK,aAAa,SAAS;AAC3B,SAAK,aAAa,SAAS;AAC3B,SAAK,YAAY,SAAS;AAAA,EAC5B;AAAA,EAEA,IAAI,KAAa;AACf,QAAI,KAAK,eAAe;AACtB,YAAM,IAAI,MAAM,+EAA+E;AACjG,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAmC;AACvC,QAAI,KAAK,eAAe,KAAM,QAAO,EAAE,IAAI,KAAK,YAAY;AAC5D,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,KAAK,WAAW;AACxD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,aACL,SACA,QACA,IACA,UACc;AACd,UAAM,SAAS,IAAI,cAAa,SAAS,QAAQ,QAAQ;AACzD,WAAO,cAAc;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAsC;AAClD,UAAM,CAAC,MAAM,IAAI,IAAI,MAAM,QAAQ,IAAI,CAAC,KAAK,WAAW,QAAQ,GAAG,KAAK,WAAW,QAAQ,CAAC,CAAC;AAC7F,UAAM,SAAS,MAAM,KAAK,SAAS,QAAQ,aAAa;AAAA,MACtD,cAAc,KAAK;AAAA,MACnB,cAAc,KAAK;AAAA,MACnB,YAAY,KAAK;AAAA,MACjB,WAAW,KAAK;AAAA,IAClB,CAAC;AACD,SAAK,cAAc,OAAO;AAC1B,WAAO;AAAA,EACT;AAAA;AAAA,EAIA,MAAc,6BAA8C;AAC1D,UAAM,OAAO,MAAM,KAAK,SAAS,YAAY,gBAAgB;AAC7D,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,8BAA8B;AACzD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,2BAA2B,UAA0C;AACjF,WAAO,KAAK,SAAS,QAAQ,oBAAoB,QAAQ;AAAA,EAC3D;AAAA,EAEA,MAAc,oBAAoB,UAA0C;AAC1E,WAAO,KAAK,SAAS,QAAQ,aAAa,QAAQ;AAAA,EACpD;AAAA,EAEA,MAAc,eAA8B;AAC1C,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,UAAM,eAAe,MAAM,KAAK,2BAA2B;AAE3D,QAAI,KAAK,gBAAgB,aAAc;AAGvC,UAAM,QAAQ,IAAI,CAAC,KAAK,WAAW,OAAO,GAAG,KAAK,WAAW,OAAO,CAAC,CAAC;AAEtE,UAAM,eAAe,MAAM,KAAK,2BAA2B,EAAE;AAE7D,QAAI,iBAAiB,cAAc;AACjC,WAAK,gBAAgB;AACrB,WAAK,cAAc;AACnB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,MAAM,gBAAgB,QAAW,YAAY,EAAE,QAAQ,MAAM;AAChF,aAAK,WAAW;AAAA,MAClB,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAEX,SAAK,gBAAgB;AACrB,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAc,MAAM,UAA8B,cAAqC;AACrF,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAElC,UAAM,QAAQ,WAAW,EAAE,MAAM,SAAS,IAAI;AAC9C,UAAM,CAAC,SAAS,OAAO,IAAI,MAAM,QAAQ,IAAI,CAAC,KAAK,WAAW,OAAO,KAAK,GAAG,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC;AAE3G,UAAM,gBAAgB,WAAa,MAAM,KAAK,oBAAoB,EAAE,KAAM,SAAa;AAEvF,UAAM,WAAW,yBAAyB,IAAI,KAAK,WAAW,IAAI;AAClE,UAAM,aAAa,eAAe,SAAS,SAAS,KAAK,YAAY,KAAK,WAAW,UAAU,aAAa;AAE5G,UAAM,OAAO,WAAW,OAAO,CAAC,MAAM,EAAE,QAAQ,YAAY;AAE5D,QAAI,KAAK,SAAS,GAAG;AACnB,YAAM,KAAK,cAAc,IAAI;AAAA,IAC/B;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,MAAiC;AAC3D,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,UAAM,KAAK,SAAS,QAAQ,YAAY,IAAI,IAAI;AAAA,EAClD;AAAA,EAEA,MAAc,mBAAmB,OAAwC;AACvE,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,WAAO,KAAK,SAAS,QAAQ,UAAU,IAAI,KAAK;AAAA,EAClD;AAAA;AAAA,EAIA,MAAM,OAAO,OAAwC;AACnD,UAAM,KAAK,aAAa;AACxB,QAAI,KAAK,iBAAiB,CAAC,MAAO,QAAO,KAAK;AAC9C,UAAM,OAAO,MAAM,KAAK,mBAAmB,KAAK;AAChD,QAAI,CAAC,MAAO,MAAK,gBAAgB;AACjC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,MAAuC;AACjD,UAAM,KAAK,aAAa;AACxB,QAAI,MAAM;AACR,YAAM,SAAS,MAAM,KAAK,mBAAmB,EAAE,MAAM,MAAM,IAAI,KAAK,CAAC;AACrE,aAAO,OAAO,SAAS,IAAI,OAAO,CAAC,EAAG,QAAQ;AAAA,IAChD;AACA,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,WAAO,KAAK,SAAS,QAAQ,aAAa,EAAE;AAAA,EAC9C;AACF;;;ACnLO,IAAM,mBAAN,MAAM,kBAAiB;AAAA,EACnB;AAAA,EAED;AAAA,EACA,cAA6B;AAAA,EAC7B,aAA6C;AAAA,EAErD,YAAY,SAA0B,UAAoC;AACxE,UAAM,QAAQ,SAAS,OAAO,CAAC,KAAK,CAAC,EAAE,MAAM,MAAM,MAAM,QAAQ,CAAC;AAClE,QAAI,KAAK,IAAI,QAAQ,CAAC,IAAI,MAAM;AAC9B,YAAM,IAAI,MAAM,yCAAyC,KAAK,EAAE;AAAA,IAClE;AACA,SAAK,WAAW;AAChB,SAAK,WAAW;AAAA,EAClB;AAAA,EAEA,IAAI,KAAa;AACf,QAAI,KAAK,eAAe;AACtB,YAAM,IAAI,MAAM,mFAAmF;AACrG,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAmC;AACvC,QAAI,KAAK,eAAe,KAAM,QAAO,EAAE,IAAI,KAAK,YAAY;AAC5D,QAAI,CAAC,KAAK,WAAY,MAAK,aAAa,KAAK,WAAW;AACxD,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,aAAa,SAA0B,IAAY,UAAsD;AAC9G,UAAM,SAAS,IAAI,kBAAiB,SAAS,QAAQ;AACrD,WAAO,cAAc;AACrB,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAsC;AAClD,UAAM,QAAQ,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,MAAM,OAAO,QAAQ,CAAC,CAAC;AAEnE,UAAM,eAAuC,CAAC;AAC9C,eAAW,CAAC,QAAQ,MAAM,KAAK,KAAK,UAAU;AAC5C,YAAM,MAAM,OAAO,aAAa,IAAI,GAAG,OAAO,MAAM,MAAM,OAAO,QAAQ,KAAK,OAAO;AACrF,mBAAa,GAAG,IAAI;AAAA,IACtB;AAEA,UAAM,SAAS,MAAM,KAAK,SAAS,YAAY,aAAa,YAAY;AACxE,SAAK,cAAc,OAAO;AAC1B,WAAO;AAAA,EACT;AACF;;;AClDA,SAAS,sBAAsB;;;ACE/B,SAAS,aAAa,SAAiB,MAA2B;AAChE,QAAM,IAAI,oBAAI,KAAK,UAAU,YAAY;AACzC,QAAM,IAAI,EAAE,eAAe;AAC3B,QAAM,IAAI,EAAE,YAAY;AAExB,UAAQ,MAAM;AAAA,IACZ,KAAK,UAAU;AACb,YAAM,MAAM,IAAI,KAAK,CAAC;AACtB,UAAI,WAAW,IAAI,WAAW,IAAI,KAAM,IAAI,UAAU,IAAI,KAAK,CAAE;AACjE,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,eAAe,GAAG,GAAG,CAAC,CAAC;AAC/D,YAAM,SAAS,KAAK,OAAO,IAAI,QAAQ,IAAI,UAAU,QAAQ,KAAK,QAAW,KAAK,CAAC;AACnF,aAAO,GAAG,IAAI,eAAe,CAAC,KAAK,MAAM;AAAA,IAC3C;AAAA,IACA,KAAK;AACH,aAAO,GAAG,CAAC,IAAI,CAAC;AAAA,IAClB,KAAK;AACH,aAAO,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,IAClC,KAAK;AACH,aAAO,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,IACnC,KAAK;AACH,aAAO,GAAG,CAAC,IAAI,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,IAClC,KAAK;AACH,aAAO,GAAG,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,CAAC;AAAA,IACnC,KAAK;AACH,aAAO,GAAG,CAAC;AAAA,IACb;AACE,aAAO,GAAG,CAAC,IAAI,CAAC;AAAA,EACpB;AACF;AAEO,SAAS,sBAAsB,aAAuB,MAAmB,QAA6B;AAC3G,MAAI,SAAS,QAAS,QAAO,IAAI,IAAI,WAAW;AAEhD,QAAM,SAAS,oBAAI,IAAsB;AACzC,WAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,UAAM,MAAM,aAAa,YAAY,CAAC,GAAG,IAAI;AAC7C,QAAI,CAAC,OAAO,IAAI,GAAG,EAAG,QAAO,IAAI,KAAK,CAAC,CAAC;AACxC,WAAO,IAAI,GAAG,EAAG,KAAK,CAAC;AAAA,EACzB;AAEA,QAAM,SAAS,oBAAI,IAAY;AAC/B,aAAW,WAAW,OAAO,OAAO,GAAG;AACrC,UAAM,UAAU,QAAQ,QAAQ,SAAS,CAAC;AAC1C,UAAM,YAAY,UAAU;AAC5B,QAAI,aAAa,KAAK,YAAY,YAAY,QAAQ;AACpD,aAAO,IAAI,YAAY,SAAS,CAAC;AAAA,IACnC;AAAA,EACF;AAEA,SAAO;AACT;AAOO,SAAS,iBACd,cACA,OACA,gBACA,aACqB;AACrB,QAAM,SAAS,oBAAI,IAAoB;AACvC,MAAI;AAEJ,aAAW,QAAQ,aAAa;AAC9B,QAAI,eAAe,IAAI,IAAI,GAAG;AAC5B,iBAAW,QAAQ,OAAO;AACxB,YAAI,KAAK,UAAU,WAAW,GAAG;AAC/B,oBAAU,KAAK;AACf;AAAA,QACF;AACA,cAAM,UAAU,KAAK,UAAU,MAAM,CAAC,OAAO,aAAa,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,KAAK;AACrF,YAAI,SAAS;AACX,oBAAU,KAAK;AACf;AAAA,QACF;AAAA,MACF;AAAA,IACF;AACA,QAAI,YAAY,QAAW;AACzB,aAAO,IAAI,MAAM,OAAO;AAAA,IAC1B;AAAA,EACF;AAEA,SAAO;AACT;;;ACnFO,IAAM,kBAAN,MAAsB;AAAA,EAClB;AAAA,EAET,YAAY,UAAoC;AAE9C,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,CAAC,MAAM,KAAK,UAAU;AAC/B,YAAM,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ;AAC/C,UAAI,KAAK,IAAI,GAAG,GAAG;AACjB,cAAM,IAAI,MAAM,qBAAqB,OAAO,MAAM,EAAE;AAAA,MACtD;AACA,WAAK,IAAI,GAAG;AAAA,IACd;AAEA,SAAK,WAAW;AAAA,EAClB;AAAA,EAEQ,UAAU,QAAuD;AACvE,UAAM,MAAM,oBAAI,IAAoB;AACpC,eAAW,CAAC,QAAQ,KAAK,KAAK,QAAQ;AACpC,UAAI,IAAI,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ,IAAI,KAAK;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,QAAsB,UAAuC;AAC7E,QAAI,OAAO,WAAW,QAAS,QAAO;AACtC,QAAI,mBAAmB,OAAO,MAAM,EAAG,QAAO;AAC9C,UAAM,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ;AAC/C,UAAM,QAAQ,SAAS,IAAI,GAAG;AAC9B,QAAI,SAAS,MAAM;AACjB,YAAM,IAAI,MAAM,qBAAqB,OAAO,MAAM,EAAE;AAAA,IACtD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,QAA0C;AAC9C,UAAM,WAAW,KAAK,UAAU,MAAM;AACtC,QAAI,QAAQ;AACZ,eAAW,CAAC,QAAQ,QAAQ,KAAK,KAAK,UAAU;AAC9C,eAAS,WAAW,KAAK,UAAU,QAAQ,QAAQ;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA,EAEA,QAAQ,QAA4D;AAClE,UAAM,QAAQ,KAAK,MAAM,MAAM;AAC/B,QAAI,UAAU,EAAG,QAAO,CAAC;AAEzB,UAAM,WAAW,KAAK,UAAU,MAAM;AACtC,UAAM,SAAmC,CAAC;AAC1C,eAAW,CAAC,QAAQ,QAAQ,KAAK,KAAK,UAAU;AAC9C,YAAM,cAAc,WAAW,KAAK,UAAU,QAAQ,QAAQ;AAC9D,UAAI,gBAAgB,EAAG;AACvB,aAAO,KAAK,CAAC,QAAQ,cAAc,KAAK,CAAC;AAAA,IAC3C;AACA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,QAA0B,QAAkC,MAAuB;AACxF,UAAM,WAAW,KAAK,UAAU,MAAM;AACtC,UAAM,aAAa,KAAK,MAAM,MAAM;AAGpC,UAAM,iBAAiB,oBAAI,IAAoB;AAC/C,eAAW,CAAC,QAAQ,QAAQ,KAAK,KAAK,UAAU;AAC9C,UAAI,OAAO,WAAW,QAAS;AAC/B,YAAM,QAAQ,KAAK,UAAU,QAAQ,QAAQ;AAC7C,qBAAe,IAAI,OAAO,QAAQ,WAAW,KAAK;AAAA,IACpD;AAGA,UAAM,gBAAgB,oBAAI,IAAoB;AAC9C,eAAW,CAAC,QAAQ,MAAM,KAAK,OAAO,UAAU;AAC9C,UAAI,OAAO,WAAW,QAAS;AAC/B,oBAAc,IAAI,OAAO,QAAQ,aAAa,MAAM;AAAA,IACtD;AAGA,UAAM,iBAAiB,oBAAI,IAA0B;AACrD,eAAW,CAAC,MAAM,KAAK,KAAK,UAAU;AACpC,UAAI,OAAO,WAAW,QAAS,gBAAe,IAAI,OAAO,QAAQ,MAAM;AAAA,IACzE;AACA,eAAW,CAAC,MAAM,KAAK,OAAO,UAAU;AACtC,UAAI,OAAO,WAAW,QAAS;AAC/B,YAAM,WAAW,eAAe,IAAI,OAAO,MAAM;AACjD,UAAI,YAAY,SAAS,aAAa,OAAO,UAAU;AACrD,cAAM,IAAI,MAAM,4BAA4B,OAAO,MAAM,EAAE;AAAA,MAC7D;AACA,qBAAe,IAAI,OAAO,QAAQ,MAAM;AAAA,IAC1C;AAGA,UAAM,aAAa,oBAAI,IAAI,CAAC,GAAG,eAAe,KAAK,GAAG,GAAG,cAAc,KAAK,CAAC,CAAC;AAE9E,UAAM,QAAiB,CAAC;AACxB,UAAM,OAAgB,CAAC;AAEvB,eAAW,UAAU,YAAY;AAC/B,YAAM,UAAU,eAAe,IAAI,MAAM,KAAK;AAC9C,YAAM,UAAU,cAAc,IAAI,MAAM,KAAK;AAC7C,YAAM,QAAQ,UAAU;AAExB,YAAM,SAAS,eAAe,IAAI,MAAM;AACxC,YAAM,QAAQ,KAAK,UAAU,QAAQ,QAAQ;AAE7C,YAAM,WAAW,KAAK,IAAI,KAAK,IAAI;AACnC,UAAI,WAAW,MAAO;AAEtB,YAAM,QAAe,EAAE,MAAM,QAAQ,UAAU,OAAO,QAAQ,QAAQ,IAAI,QAAQ,OAAO;AAEzF,UAAI,MAAM,WAAW,QAAQ;AAC3B,cAAM,KAAK,KAAK;AAAA,MAClB,OAAO;AACL,aAAK,KAAK,KAAK;AAAA,MACjB;AAAA,IACF;AAEA,WAAO,CAAC,GAAG,OAAO,GAAG,IAAI;AAAA,EAC3B;AACF;;;ACtHA,IAAM,UAAU;AAEhB,SAAS,KAAK,QAAgB,UAA0B;AACtD,SAAO,GAAG,MAAM,IAAI,QAAQ;AAC9B;AAEA,SAAS,cAAc,KAAqB;AAC1C,QAAM,MAAM,IAAI,YAAY,GAAG;AAC/B,SAAO,QAAQ,KAAK,MAAM,IAAI,MAAM,GAAG,GAAG;AAC5C;AAEA,SAAS,UAAU,KAAsB;AACvC,SAAO,mBAAmB,cAAc,GAAG,CAAC;AAC9C;AAEA,SAAS,eACP,KACA,MACA,QACA,WACoB;AACpB,MAAI,UAAU,GAAG,EAAG,QAAO;AAC3B,QAAM,OAAO,OAAO,GAAG,IAAI,IAAI;AAC/B,MAAI,QAAQ,MAAM;AAChB,cAAU,GAAG,IAAI;AACjB,WAAO;AAAA,EACT;AACA,SAAO,UAAU,GAAG;AACtB;AAEA,SAAS,YAAY,aAAqB,aAA6B;AAErE,QAAM,KACJ,KAAK,IAAI,OAAO,YAAY,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,YAAY,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,OAAO,YAAY,MAAM,GAAG,EAAE,CAAC,CAAC,IAC/G,KAAK,IAAI,OAAO,YAAY,MAAM,GAAG,CAAC,CAAC,GAAG,OAAO,YAAY,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,OAAO,YAAY,MAAM,GAAG,EAAE,CAAC,CAAC;AACjH,SAAO,KAAK,MAAM,MAAM,MAAO,KAAK,KAAK,GAAG;AAC9C;AAEO,SAAS,cACd,MACA,QACA,gBACA,WAC0E;AAC1E,QAAM,YAAoC,CAAC;AAC3C,QAAM,YAAoC,CAAC;AAC3C,MAAI,OAAO;AACX,aAAW,CAAC,QAAQ,QAAQ,KAAK,UAAU,UAAU;AACnD,QAAI,OAAO,WAAW,SAAS;AAC7B,aAAO;AAAA,IACT,OAAO;AACL,gBAAU,KAAK,OAAO,QAAQ,OAAO,QAAQ,CAAC,IAAI;AAAA,IACpD;AAAA,EACF;AACA,QAAM,SAAqB,CAAC;AAC5B,QAAM,SAAkB,CAAC;AAKzB,WAAS,eAAe,KAAa,MAAkC;AACrE,WAAO,eAAe,KAAK,MAAM,QAAQ,SAAS;AAAA,EACpD;AAEA,MAAI,WAA0B;AAE9B,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,IAAI;AAGjB,QAAI,YAAY,MAAM;AACpB,YAAM,OAAO,YAAY,UAAU,IAAI;AACvC,UAAI,OAAO,GAAG;AACZ,mBAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,cAAI,CAAC,UAAU,GAAG,EAAG;AACrB,gBAAM,UAAU,OAAO,GAAG,IAAI,QAAQ;AACtC,cAAI,WAAW,KAAM;AACrB,gBAAM,WAAW,OAAO,IAAI,MAAM,IAAI,YAAY,GAAG,IAAI,CAAC,CAAC,KAAK;AAChE,gBAAM,SAAS,IAAI,YAAY,UAAU,QAAQ,OAAO;AACxD,oBAAU,GAAG,IAAI,SAAS;AAAA,QAC5B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,eAAe,IAAI,IAAI,GAAG;AAE5B,UAAI,iBAAiB;AACrB,iBAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,cAAM,QAAQ,eAAe,KAAK,IAAI;AACtC,YAAI,SAAS,KAAM,mBAAkB,SAAS;AAAA,MAChD;AAGA,YAAM,gBAAwC,CAAC;AAC/C,iBAAW,CAAC,QAAQ,MAAM,KAAK,IAAI,WAAW,UAAU;AACtD,sBAAc,KAAK,OAAO,QAAQ,OAAO,QAAQ,CAAC,IAAI;AAAA,MACxD;AAGA,YAAM,UAAU,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,SAAS,GAAG,GAAG,OAAO,KAAK,aAAa,CAAC,CAAC;AAClF,iBAAW,OAAO,SAAS;AACzB,YAAI;AACJ,YAAI,UAAU,GAAG,GAAG;AAClB,kBAAQ;AAAA,QACV,OAAO;AACL,gBAAM,OAAO,OAAO,GAAG,IAAI,IAAI;AAC/B,cAAI,QAAQ,QAAQ,QAAQ,EAAG;AAC/B,kBAAQ;AAAA,QACV;AAEA,cAAM,gBAAgB,UAAU,GAAG,KAAK;AACxC,cAAM,cAAc,kBAAkB,cAAc,GAAG,KAAK;AAC5D,cAAM,eAAe,cAAc;AACnC,cAAM,QAAQ,eAAe;AAE7B,YAAI,KAAK,IAAI,KAAK,KAAK,QAAS;AAEhC,YAAI,KAAK,IAAI,YAAY,KAAK,SAAS;AACrC,iBAAO,UAAU,GAAG;AAAA,QACtB,OAAO;AACL,oBAAU,GAAG,IAAI;AAAA,QACnB;AACA,gBAAQ,QAAQ;AAEhB,eAAO,KAAK;AAAA,UACV;AAAA,UACA,QAAQ,IAAI,MAAM,GAAG,EAAE,CAAC;AAAA,UACxB,UAAU,KAAK,IAAI,KAAK;AAAA,UACxB;AAAA,UACA,QAAQ,QAAQ,IAAI,QAAQ;AAAA,QAC9B,CAAC;AAAA,MACH;AAEA,UAAI,KAAK,IAAI,IAAI,KAAK,QAAS,QAAO;AAAA,IACxC;AAGA,QAAI,QAAQ;AACZ,eAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,YAAM,QAAQ,eAAe,KAAK,IAAI;AACtC,UAAI,SAAS,KAAM,UAAS,SAAS;AAAA,IACvC;AACA,WAAO,KAAK,EAAE,MAAM,MAAM,CAAC;AAC3B,eAAW;AAAA,EACb;AAGA,QAAM,gBAA0C,CAAC;AAGjD,QAAM,cAAc,oBAAI,IAA0B;AAClD,aAAW,OAAO,MAAM;AACtB,eAAW,CAAC,MAAM,KAAK,IAAI,WAAW,UAAU;AAC9C,YAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,QAAQ;AAC/C,UAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AACzB,oBAAY,IAAI,KAAK,MAAM;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AACA,aAAW,CAAC,MAAM,KAAK,UAAU,UAAU;AACzC,UAAM,MAAM,KAAK,OAAO,QAAQ,OAAO,QAAQ;AAC/C,QAAI,CAAC,YAAY,IAAI,GAAG,GAAG;AACzB,kBAAY,IAAI,KAAK,MAAM;AAAA,IAC7B;AAAA,EACF;AAEA,aAAW,CAAC,KAAK,MAAM,KAAK,OAAO,QAAQ,SAAS,GAAG;AACrD,UAAM,SAAS,YAAY,IAAI,GAAG;AAClC,QAAI,UAAU,KAAK,IAAI,MAAM,IAAI,SAAS;AACxC,oBAAc,KAAK,CAAC,QAAQ,MAAM,CAAC;AAAA,IACrC;AAAA,EACF;AAGA,QAAM,UAAU,KAAK,SAAS,CAAC;AAC/B,QAAM,aAAa,YAAY,IAAI,OAAO,KAAK,UAAU,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,WAAW,OAAO,IAAI,CAAC;AACzG,MAAI,cAAc,KAAK,IAAI,IAAI,IAAI,SAAS;AAC1C,kBAAc,KAAK,CAAC,YAAY,IAAI,CAAC;AAAA,EACvC;AAEA,QAAM,iBAAiB,IAAI,gBAAgB,aAAa;AAExD,SAAO,EAAE,QAAQ,QAAQ,eAAe;AAC1C;;;AC7JO,IAAM,mBAAN,MAAuB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAED;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAY,QAAoB,QAAiB,mBAAoC,YAAyB;AAC5G,SAAK,SAAS;AACd,SAAK,SAAS;AACd,SAAK,oBAAoB;AAEzB,QAAI,YAAY;AACd,WAAK,aAAa,WAAW;AAC7B,WAAK,qBAAqB,WAAW;AACrC,WAAK,mBAAmB,WAAW;AACnC,WAAK,uBAAuB,IAAI,IAAI,OAAO,QAAQ,WAAW,eAAe,CAAC;AAC9E,WAAK,0BAA0B,IAAI,IAAI,OAAO,QAAQ,WAAW,eAAe,CAAC;AACjF,WAAK,YAAY,OAAO,GAAG,EAAE,GAAG,QAAQ;AAAA,IAC1C,OAAO;AACL,WAAK,aAAa;AAClB,WAAK,qBAAqB;AAC1B,WAAK,mBAAmB,CAAC;AACzB,WAAK,uBAAuB,oBAAI,IAAI;AACpC,WAAK,0BAA0B,oBAAI,IAAI;AACvC,WAAK,YAAY;AAAA,IACnB;AAAA,EACF;AAAA,EAEA,QAAQ,QAAqD;AAC3D,QAAI,CAAC,KAAK,cAAc,CAAC,KAAK,oBAAoB;AAChD,aAAO,EAAE,OAAO,GAAG,UAAU,CAAC,GAAG,SAAS,CAAC,GAAG,eAAe,CAAC,EAAE;AAAA,IAClE;AAGA,eAAW,CAAC,QAAQ,SAAS,KAAK,QAAQ;AACxC,UAAI,OAAO,WAAW,QAAS;AAC/B,YAAM,YAAY,KAAK,iBAAiB,OAAO,MAAM;AACrD,UAAI,aAAa,KAAM;AAEvB,YAAM,cAAc,YAAY,aAAa;AAG7C,iBAAW,CAAC,IAAI,KAAK,KAAK,WAAW,UAAU;AAC7C,YAAI,KAAK,WAAW,OAAO,OAAQ;AACnC,YAAI,KAAK,WAAW,QAAS;AAC7B,cAAM,MAAM,GAAG,KAAK,MAAM,IAAI,KAAK,QAAQ;AAC3C,cAAM,qBAAqB,KAAK,qBAAqB,IAAI,GAAG;AAC5D,YAAI,sBAAsB,KAAM;AAChC,cAAM,kBAAkB,KAAK,WAAW;AACxC,aAAK,wBAAwB,IAAI,KAAK,sBAAsB,IAAI,gBAAgB;AAAA,MAClF;AAAA,IACF;AAGA,UAAM,aAAuC,CAAC;AAC9C,eAAW,CAAC,IAAI,KAAK,KAAK,WAAW,UAAU;AAC7C,UAAI,KAAK,WAAW,QAAS;AAC7B,YAAM,MAAM,GAAG,KAAK,MAAM,IAAI,KAAK,QAAQ;AAC3C,YAAM,QAAQ,KAAK,wBAAwB,IAAI,GAAG;AAClD,UAAI,SAAS,KAAM,YAAW,KAAK,CAAC,MAAM,KAAK,CAAC;AAAA,IAClD;AAEA,WAAO;AAAA,MACL,OAAO,KAAK,WAAW,MAAM,UAAU;AAAA,MACvC,UAAU,KAAK,WAAW;AAAA,MAC1B,SAAS,KAAK,WAAW,QAAQ,UAAU;AAAA,MAC3C,eAAe,KAAK,WAAW,OAAO,KAAK,oBAAoB,YAAY,KAAK,SAAS;AAAA,IAC3F;AAAA,EACF;AACF;;;AJ9FA,IAAM,SAAS,eAAe,kEAAkE,EAAE;AAmB3F,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEA;AAAA,EACA;AAAA,EACA,cAA6B;AAAA,EAC7B,kBAAiC;AAAA,EACjC,aAA6C;AAAA,EAC7C,iBAAgD,oBAAI,IAAI;AAAA,EAExD,SAA+B;AAAA,EAC/B,cAA6B;AAAA,EAC7B,WAAiC;AAAA,EAEzC,YAAY,SAA0B,QAAwB,iBAA2C;AACvG,SAAK,WAAW;AAChB,SAAK,UAAU;AAEf,QAAI,OAAO,oBAAoB,UAAU;AACvC,WAAK,UAAU;AACf,WAAK,QAAQ;AACb,WAAK,QAAQ;AACb,WAAK,UAAU;AACf,WAAK,SAAS,CAAC;AAAA,IACjB,OAAO;AACL,YAAM,OAAO;AACb,UAAI,KAAK,MAAM,WAAW,GAAG;AAC3B,cAAM,IAAI,MAAM,sCAAsC;AAAA,MACxD;AACA,YAAM,WAAW,KAAK,MAAM,KAAK,MAAM,SAAS,CAAC;AACjD,UAAI,SAAS,QAAQ,SAAS,KAAK,SAAS,GAAG;AAC7C,cAAM,IAAI,MAAM,+CAA+C;AAAA,MACjE;AACA,eAAS,IAAI,GAAG,IAAI,KAAK,MAAM,SAAS,GAAG,KAAK;AAC9C,cAAM,OAAO,KAAK,MAAM,CAAC;AACzB,YAAI,KAAK,SAAS,UAAa,KAAK,KAAK,WAAW,GAAG;AACrD,gBAAM,IAAI;AAAA,YACR,QAAQ,CAAC;AAAA,UACX;AAAA,QACF;AAAA,MACF;AACA,WAAK,UAAU;AACf,WAAK,QAAQ,KAAK;AAClB,WAAK,QAAQ,KAAK,QAAQ;AAC1B,WAAK,UAAU,KAAK,UAAU;AAC9B,WAAK,SAAS,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,IAAI,KAAa;AACf,QAAI,KAAK,eAAe,KAAM,OAAM,IAAI,MAAM,wDAAwD;AACtG,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAe;AACjB,QAAI,KAAK,mBAAmB,KAAM,OAAM,IAAI,MAAM,wDAAwD;AAC1G,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAoB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAiB;AACnB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,QAAwB;AAC1B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,UAAmC;AACvC,QAAI,KAAK,eAAe,KAAM,QAAO,EAAE,IAAI,KAAK,YAAY;AAC5D,QAAI,CAAC,KAAK,YAAY;AACpB,WAAK,aACH,KAAK,YAAY,QAAQ,KAAK,UAAU,OAAO,KAAK,oBAAoB,IAAI,KAAK,iBAAiB;AAAA,IACtG;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,mBAA4C;AACxD,UAAM,aAAa,oBAAI,IAAkB;AACzC,UAAM,iBAAiB,oBAAI,IAAsB;AACjD,eAAW,QAAQ,KAAK,QAAQ;AAC9B,UAAI,KAAK,KAAM,MAAK,KAAK,QAAQ,CAAC,MAAM,WAAW,IAAI,CAAC,CAAC;AACzD,qBAAe,IAAI,KAAK,IAAI;AAAA,IAC9B;AAEA,UAAM,QAAQ,IAAI;AAAA,MAChB,GAAG,MAAM,KAAK,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,MAChD,GAAG,MAAM,KAAK,cAAc,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC;AAAA,IACtD,CAAC;AAED,UAAM,SAAS,OAAO;AACtB,UAAM,SAAS,MAAM,KAAK,SAAS,WAAW,OAAO;AAAA,MACnD;AAAA,MACA,MAAM,KAAK;AAAA,MACX,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,OAAO,KAAK,OAAO,IAAI,CAAC,UAAU;AAAA,QAChC,YAAY,KAAK,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,QAC5C,cAAc,KAAK,KAAK;AAAA,MAC1B,EAAE;AAAA,IACJ,CAAC;AAED,SAAK,cAAc,OAAO;AAC1B,SAAK,kBAAkB;AAEvB,eAAW,QAAQ,KAAK,QAAQ;AAC9B,WAAK,eAAe,IAAI,KAAK,KAAK,IAAI,KAAK,IAAI;AAAA,IACjD;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,sBAA+C;AAC3D,UAAM,MAAM,MAAM,KAAK,SAAS,WAAW,iBAAiB,KAAK,OAAQ;AACzE,SAAK,cAAc,IAAI;AACvB,SAAK,kBAAkB,KAAK;AAC5B,SAAK,QAAQ,IAAI;AACjB,SAAK,QAAQ,IAAI;AACjB,SAAK,UAAU,IAAI;AAGnB,UAAM,YAAY,oBAAI,IAA0B;AAChD,eAAW,KAAK,IAAI,MAAM,SAAS;AACjC,gBAAU,IAAI,EAAE,IAAI,aAAa,aAAa,KAAK,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC;AAAA,IAC1F;AAEA,UAAM,eAAe,oBAAI,IAA6B;AACtD,eAAW,OAAO,IAAI,MAAM,YAAY;AACtC,YAAM,SAAS,IAAI,WAAY,UAAU,IAAI,IAAI,QAAQ,KAAK,OAAQ;AACtE,mBAAa;AAAA,QACX,IAAI;AAAA,QACJ,gBAAgB,aAAa,KAAK,UAAU,KAAK,SAAS,IAAI,IAAI;AAAA,UAChE,MAAM,IAAI;AAAA,UACV;AAAA,UACA,UAAU,IAAI;AAAA,UACd,OAAO,IAAI;AAAA,UACX,MAAM,IAAI;AAAA,UACV,WAAW,IAAI;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,YAAY,oBAAI,IAA0B;AAChD,eAAW,OAAO,IAAI,MAAM,SAAS;AACnC,gBAAU;AAAA,QACR,IAAI;AAAA,QACJ,aAAa,aAAa,KAAK,UAAU,KAAK,SAAS,IAAI,IAAI;AAAA,UAC7D,YAAY,aAAa,IAAI,IAAI,YAAY;AAAA,UAC7C,YAAY,aAAa,IAAI,IAAI,YAAY;AAAA,UAC7C,YAAY,IAAI;AAAA,UAChB,WAAW,IAAI;AAAA,QACjB,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,sBAAsB,oBAAI,IAA8B;AAC9D,eAAW,SAAS,IAAI,MAAM,aAAa;AACzC,YAAM,WAAqC,OAAO,QAAQ,MAAM,QAAQ,EAAE,IAAI,CAAC,CAAC,KAAK,MAAM,MAAM;AAC/F,cAAM,QAAQ,IAAI,MAAM,gBAAgB;AACxC,cAAM,SAAS,QAAQ,MAAM,CAAC,IAAK;AACnC,cAAM,WAAW,QAAQ,OAAO,MAAM,CAAC,CAAC,IAAI;AAC5C,eAAO,CAAC,IAAI,aAAa,KAAK,UAAU,QAAQ,QAAQ,GAAG,MAAM;AAAA,MACnE,CAAC;AACD,YAAM,SAAS,iBAAiB,aAAa,KAAK,UAAU,MAAM,IAAI,QAAQ;AAC9E,0BAAoB,IAAI,MAAM,IAAI,MAAM;AACxC,WAAK,eAAe,IAAI,MAAM,IAAI,MAAM;AAAA,IAC1C;AAGA,SAAK,SAAS,IAAI,MAAM,WAAW,IAAI,CAAC,UAAU;AAAA,MAChD,MAAM,KAAK,aAAa,KAAK,UAAU,SAAS,IAAI,KAAK,UAAU,IAAI,CAAC,OAAO,UAAU,IAAI,EAAE,CAAE,IAAI;AAAA,MACrG,MAAM,oBAAoB,IAAI,KAAK,YAAY;AAAA,IACjD,EAAE;AAEF,WAAO,EAAE,IAAI,IAAI,GAAG;AAAA,EACtB;AAAA,EAEA,MAAc,6BAA8C;AAC1D,UAAM,OAAO,MAAM,KAAK,SAAS,YAAY,gBAAgB;AAC7D,QAAI,CAAC,KAAM,OAAM,IAAI,MAAM,8BAA8B;AACzD,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,+BAAuD;AACnE,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,WAAO,KAAK,SAAS,WAAW,oBAAoB,EAAE;AAAA,EACxD;AAAA,EAEA,MAAc,eAA8B;AAC1C,UAAM,KAAK,QAAQ;AACnB,UAAM,eAAe,MAAM,KAAK,2BAA2B;AAE3D,QAAI,KAAK,gBAAgB,aAAc;AAEvC,UAAM,eAAe,MAAM,KAAK,6BAA6B;AAE7D,QAAI,iBAAiB,cAAc;AACjC,WAAK,SAAS;AACd,WAAK,cAAc;AACnB;AAAA,IACF;AAEA,QAAI,CAAC,KAAK,UAAU;AAClB,WAAK,WAAW,KAAK,MAAM,YAAY,EAAE,QAAQ,MAAM;AACrD,aAAK,WAAW;AAAA,MAClB,CAAC;AAAA,IACH;AACA,UAAM,KAAK;AAEX,SAAK,SAAS;AACd,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAc,MAAM,cAAqC;AACvD,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAGlC,UAAM,eAAe,oBAAI,IAAkC;AAC3D,UAAM,aAAa,oBAAI,IAAkB;AACzC,eAAW,QAAQ,KAAK,QAAQ;AAC9B,UAAI,KAAK,KAAM,MAAK,KAAK,QAAQ,CAAC,MAAM,WAAW,IAAI,CAAC,CAAC;AAAA,IAC3D;AAEA,UAAM,QAAQ;AAAA,MACZ,MAAM,KAAK,UAAU,EAAE,IAAI,OAAO,WAAW;AAC3C,cAAM,OAAO,MAAM,OAAO,OAAO;AACjC,cAAM,UAAU,oBAAI,IAAqB;AACzC,mBAAW,OAAO,KAAM,SAAQ,IAAI,IAAI,MAAM,IAAI,UAAU,CAAC;AAC7D,qBAAa,IAAI,OAAO,IAAI,OAAO;AAAA,MACrC,CAAC;AAAA,IACH;AAGA,UAAM,cAAc,MAAM,KAAK,SAAS,YAAY,SAAS;AAE7D,UAAM,iBAAiB,sBAAsB,aAAa,KAAK,OAAO,KAAK,OAAO;AAGlF,UAAM,cAAkC,CAAC;AACzC,UAAM,gBAAgB,oBAAI,IAAoB;AAC9C,UAAM,aAAa,KAAK,OAAO,IAAI,CAAC,SAAS;AAC3C,UAAI,WAAW,cAAc,IAAI,KAAK,KAAK,EAAE;AAC7C,UAAI,aAAa,QAAW;AAC1B,mBAAW,YAAY;AACvB,oBAAY,KAAK,KAAK,IAAI;AAC1B,sBAAc,IAAI,KAAK,KAAK,IAAI,QAAQ;AAAA,MAC1C;AACA,aAAO;AAAA,QACL,YAAY,KAAK,QAAQ,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE;AAAA,QAC5C,iBAAiB;AAAA,MACnB;AAAA,IACF,CAAC;AAGD,UAAM,aAAa,iBAAiB,cAAc,YAAY,gBAAgB,WAAW;AAGzF,UAAM,UAAiC,MAAM,KAAK,WAAW,QAAQ,CAAC,EACnE,OAAO,CAAC,CAAC,IAAI,MAAM,QAAQ,YAAY,EACvC,IAAI,CAAC,CAAC,MAAM,QAAQ,OAAO;AAAA,MAC1B;AAAA,MACA,cAAc,YAAY,QAAQ,EAAG;AAAA,IACvC,EAAE;AAEJ,QAAI,QAAQ,SAAS,GAAG;AACtB,YAAM,KAAK,SAAS,WAAW,YAAY,IAAI,OAAO;AAAA,IACxD;AAAA,EACF;AAAA,EAEA,MAAc,mBAAmB,OAA2C;AAC1E,UAAM,EAAE,GAAG,IAAI,MAAM,KAAK,QAAQ;AAClC,UAAM,UAAU,MAAM,KAAK,SAAS,WAAW,UAAU,IAAI,KAAK;AAClE,WAAO,QAAQ,IAAI,CAAC,OAAO;AAAA,MACzB,MAAM,EAAE;AAAA,MACR,YAAY,KAAK,eAAe,IAAI,EAAE,YAAY;AAAA,IACpD,EAAE;AAAA,EACJ;AAAA,EAEA,MAAM,OAAO,OAA2C;AACtD,UAAM,KAAK,aAAa;AACxB,QAAI,KAAK,UAAU,CAAC,MAAO,QAAO,KAAK;AACvC,UAAM,OAAO,MAAM,KAAK,mBAAmB,KAAK;AAChD,QAAI,CAAC,MAAO,MAAK,SAAS;AAC1B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,MAAM,MAAiD;AAC3D,UAAM,KAAK,aAAa;AACxB,UAAM,OAAO,OAAO,MAAM,KAAK,mBAAmB,EAAE,MAAM,MAAM,IAAI,KAAK,CAAC,IAAI,MAAM,KAAK,mBAAmB;AAC5G,QAAI,KAAK,WAAW,EAAG,QAAO;AAC9B,WAAO,OAAO,KAAK,CAAC,EAAG,aAAa,KAAK,KAAK,SAAS,CAAC,EAAG;AAAA,EAC7D;AAAA,EAEA,MAAM,SAAS,SAAqD;AAClE,UAAM,OAAO,MAAM,KAAK,OAAO,EAAE,MAAM,QAAQ,MAAM,IAAI,QAAQ,GAAG,CAAC;AACrE,QAAI,KAAK,WAAW,GAAG;AACrB,aAAO,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,QAAQ,SAAS;AAAA,IACvD;AAEA,UAAM,SAAS,MAAM,KAAK,uBAAuB,MAAM,QAAQ,MAAM,QAAQ,EAAE;AAC/E,UAAM,cAAc,KAAK,IAAI,CAAC,MAAM,EAAE,IAAI;AAC1C,UAAM,iBAAiB,sBAAsB,aAAa,KAAK,OAAO,KAAK,OAAO;AAGlF,mBAAe,IAAI,KAAK,CAAC,EAAG,IAAI;AAEhC,UAAM,SAAS,cAAc,MAAM,QAAQ,gBAAgB,QAAQ,SAAS;AAG5E,UAAM,UAAU,KAAK,KAAK,SAAS,CAAC;AACpC,UAAM,WAAW,QAAQ;AACzB,UAAM,iBAAiB,QAAQ;AAG/B,UAAM,kBAA0C,CAAC;AACjD,eAAW,CAAC,QAAQ,OAAO,KAAK,eAAe,UAAU;AACvD,UAAI,OAAO,WAAW,QAAS;AAC/B,YAAM,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ;AAC/C,YAAM,QAAQ,OAAO,GAAG,IAAI,QAAQ;AACpC,UAAI,SAAS,KAAM,iBAAgB,GAAG,IAAI;AAAA,IAC5C;AAGA,UAAM,cAAsC,CAAC;AAC7C,UAAM,KAAK,qBAAqB,MAAM,UAAU,WAAW;AAE3D,UAAM,aAAyB;AAAA,MAC7B,WAAW,OAAO;AAAA,MAClB,YAAY;AAAA,MACZ;AAAA,MACA;AAAA,IACF;AAEA,WAAO,IAAI,iBAAiB,OAAO,QAAQ,OAAO,QAAQ,QAAQ,WAAW,UAAU;AAAA,EACzF;AAAA,EAEA,MAAc,uBACZ,MACA,MACA,IACiD;AACjD,UAAM,YAAY,oBAAI,IAA0B;AAChD,eAAW,OAAO,MAAM;AACtB,iBAAW,CAAC,MAAM,KAAK,IAAI,WAAW,UAAU;AAC9C,cAAM,MAAM,GAAG,OAAO,MAAM,IAAI,OAAO,QAAQ;AAC/C,YAAI,CAAC,UAAU,IAAI,GAAG,GAAG;AACvB,oBAAU,IAAI,KAAK,MAAM;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,QAAQ;AAAA,MAC5B,MAAM,KAAK,UAAU,QAAQ,CAAC,EAAE,IAAI,OAAO,CAAC,KAAK,MAAM,MAAM;AAC3D,cAAM,iBAAiB,IAAI,gBAAgB,KAAK,UAAU,KAAK,SAAS;AAAA,UACtE,MAAM;AAAA,UACN;AAAA,UACA,UAAU;AAAA,UACV,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW;AAAA,QACb,CAAC;AACD,cAAM,YAAY,MAAM,eAAe,OAAO,EAAE,MAAM,GAAG,CAAC;AAC1D,cAAM,UAAkC,CAAC;AACzC,mBAAW,OAAO,WAAW;AAC3B,kBAAQ,IAAI,IAAI,IAAI,IAAI;AAAA,QAC1B;AACA,eAAO,CAAC,KAAK,OAAO;AAAA,MACtB,CAAC;AAAA,IACH;AAEA,WAAO,OAAO,YAAY,OAAO;AAAA,EACnC;AAAA,EAEA,MAAc,qBACZ,MACA,UACA,aACe;AACf,UAAM,UAAU,oBAAI,IAAY;AAChC,eAAW,OAAO,MAAM;AACtB,iBAAW,CAAC,MAAM,KAAK,IAAI,WAAW,UAAU;AAC9C,YAAI,OAAO,WAAW,QAAS,SAAQ,IAAI,OAAO,MAAM;AAAA,MAC1D;AAAA,IACF;AAEA,UAAM,QAAQ;AAAA,MACZ,MAAM,KAAK,OAAO,EAAE,IAAI,OAAO,WAAW;AACxC,cAAM,YAAY,IAAI,aAAa,KAAK,UAAU,QAAQ,CAAC;AAC3D,cAAM,iBAAiB,IAAI,gBAAgB,KAAK,UAAU,KAAK,SAAS;AAAA,UACtE,MAAM;AAAA,UACN,QAAQ;AAAA,UACR,UAAU;AAAA,UACV,OAAO;AAAA,UACP,MAAM;AAAA,UACN,WAAW;AAAA,QACb,CAAC;AACD,cAAM,YAAY,MAAM,eAAe,OAAO,EAAE,MAAM,UAAU,IAAI,SAAS,CAAC;AAC9E,YAAI,UAAU,SAAS,GAAG;AACxB,sBAAY,MAAM,IAAI,UAAU,CAAC,EAAG;AAAA,QACtC;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;;;AK/XA,SAAS,YACP,SACA,QACA,MACA,QACA,UACA,MACiB;AACjB,SAAO,IAAI,gBAAgB,SAAS,QAAQ;AAAA,IAC1C;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO,MAAM,SAAS;AAAA,IACtB,MAAM;AAAA,IACN,WAAW;AAAA,EACb,CAAC;AACH;AAEA,SAAS,WACP,SACA,QACA,MACA,MACiB;AACjB,SAAO,IAAI,gBAAgB,SAAS,QAAQ;AAAA,IAC1C;AAAA,IACA,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,OAAO,MAAM,SAAS;AAAA,IACtB,MAAM;AAAA,IACN,WAAW;AAAA,EACb,CAAC;AACH;AAEO,SAAS,aAAa,SAAkD;AAC7E,QAAM,EAAE,SAAS,OAAO,IAAI;AAE5B,SAAO;AAAA,IACL,QAAQ,CAAC,QAAQ,aAAa,IAAI,aAAa,SAAS,QAAQ,QAAQ;AAAA,IAExE,KAAK,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,OAAO,QAAQ,UAAU,IAAI;AAAA,IAC5F,KAAK,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,OAAO,QAAQ,UAAU,IAAI;AAAA,IAC5F,OAAO,CAAC,QAAQ,SAAU,YAAY,SAAS,QAAQ,SAAS,QAAQ,GAAG,IAAI;AAAA,IAC/E,SAAS,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,UAAU,QAAQ,UAAU,IAAI;AAAA,IACnG,YAAY,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,cAAc,QAAQ,UAAU,IAAI;AAAA,IAC1G,UAAU,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,YAAY,QAAQ,UAAU,IAAI;AAAA,IACtG,KAAK,CAAC,QAAQ,UAAU,SAAU,YAAY,SAAS,QAAQ,OAAO,QAAQ,UAAU,IAAI;AAAA,IAE5F,KAAK,CAAC,SAAU,WAAW,SAAS,QAAQ,OAAO,IAAI;AAAA,IACvD,OAAO,CAAC,SAAU,WAAW,SAAS,QAAQ,SAAS,IAAI;AAAA,IAC3D,UAAU,CAAC,OAAO,SAAU,WAAW,SAAS,QAAQ,OAAO,IAAI;AAAA,IACnE,UAAU,CAAC,QAAQ,SAAU,WAAW,SAAS,QAAQ,QAAQ,IAAI;AAAA,IAErE,WAAW,CAAC,OAAO,SACjB,IAAI,gBAAgB,SAAS,QAAQ;AAAA,MACnC,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,OAAO;AAAA,MACP,MAAM,QAAQ;AAAA,MACd,WAAW;AAAA,IACb,CAAC;AAAA,IAEH,IAAI,CAAC,MAAM,MAAM,cACf,IAAI,aAAa,SAAS,QAAQ;AAAA,MAChC,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW,aAAa;AAAA,IAC1B,CAAC;AAAA,IACH,IAAI,CAAC,MAAM,MAAM,cACf,IAAI,aAAa,SAAS,QAAQ;AAAA,MAChC,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW,aAAa;AAAA,IAC1B,CAAC;AAAA,IACH,IAAI,CAAC,MAAM,MAAM,cACf,IAAI,aAAa,SAAS,QAAQ;AAAA,MAChC,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,WAAW,aAAa;AAAA,IAC1B,CAAC;AAAA,IAEH,YAAY,IAAI,aAAa,IAAI,iBAAiB,SAAS,QAAQ;AAAA,IAEnE,WAAW,IAAI,aAAa,IAAI,gBAAgB,QAAQ;AAAA,IAExD,UAAU,CAAC,oBAA8C,IAAI,eAAe,SAAS,QAAQ,eAAe;AAAA,EAC9G;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/handles/ticker.ts","../src/providers/mappings.ts","../src/computations/sma.ts","../src/computations/ema.ts","../src/computations/rsi.ts","../src/computations/returns.ts","../src/computations/volatility.ts","../src/computations/drawdown.ts","../src/computations/calendar.ts","../src/computations/index.ts","../src/providers/quote-overlay.ts","../src/handles/indicator.ts","../src/computations/signal.ts","../src/handles/signal.ts","../src/handles/allocation.ts","../src/handles/strategy.ts","../src/computations/strategy.ts","../src/handles/portfolio.ts","../src/backtest/simulate.ts","../src/backtest/types.ts","../src/client.ts"],"sourcesContent":["import type { StorageProvider } from '../providers/storage';\n\nexport class TickerHandle {\n readonly symbol: string;\n readonly leverage: number;\n\n private _storage: StorageProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n constructor(storage: StorageProvider, symbol: string, leverage: number = 1) {\n this._storage = storage;\n this.symbol = symbol.toUpperCase();\n this.leverage = leverage;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('TickerHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(storage: StorageProvider, id: number, symbol: string, leverage: number): TickerHandle {\n const handle = new TickerHandle(storage, symbol, leverage);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const result = await this._storage.tickers.findOrCreate(this.symbol, this.leverage);\n this._resolvedId = result.id;\n return result;\n }\n}\n","import type { IndicatorType } from './types';\n\nexport type ProviderInfo =\n | { provider: 'yahoo'; symbol: string; rateSeries?: true }\n | { provider: 'fred'; seriesId: string; rateSeries?: true }\n | { provider: 'computed'; dependsOn: 'Price'; symbol: string; rateSeries?: true }\n | { provider: 'calendar' }\n | { provider: 'none' };\n\nconst FRED_SERIES: Record<string, string> = {\n T3M: 'DGS3MO',\n T6M: 'DGS6MO',\n T1Y: 'DGS1',\n T2Y: 'DGS2',\n T3Y: 'DGS3',\n T5Y: 'DGS5',\n T7Y: 'DGS7',\n T10Y: 'DGS10',\n T20Y: 'DGS20',\n T30Y: 'DGS30',\n};\n\n// Ticker symbols whose \"price\" values are rates/yields (expressed in percent),\n// not prices. For these, percent-change returns are both broken (divide by\n// zero / sign flips) and semantically wrong — callers should use absolute\n// differences instead.\nconst RATE_TICKER_SYMBOLS = new Set<string>([\n 'DTB3',\n 'DTB6',\n 'DFF',\n 'DGS3MO',\n 'DGS6MO',\n 'DGS1',\n 'DGS2',\n 'DGS3',\n 'DGS5',\n 'DGS7',\n 'DGS10',\n 'DGS20',\n 'DGS30',\n]);\n\nconst COMPUTED_TYPES = new Set<string>(['SMA', 'EMA', 'RSI', 'Return', 'Volatility', 'Drawdown']);\nconst CALENDAR_TYPES = new Set<string>(['Month', 'Day of Week', 'Day of Month', 'Day of Year']);\n\nexport function isRateTickerSymbol(symbol: string | null): boolean {\n return symbol != null && RATE_TICKER_SYMBOLS.has(symbol);\n}\n\nexport function getProviderInfo(type: IndicatorType, tickerSymbol: string | null): ProviderInfo {\n if (type === 'Price') {\n const info: ProviderInfo = { provider: 'yahoo', symbol: tickerSymbol! };\n if (isRateTickerSymbol(tickerSymbol)) info.rateSeries = true;\n return info;\n }\n if (type === 'VIX') return { provider: 'yahoo', symbol: '^VIX' };\n if (type === 'VIX3M') return { provider: 'yahoo', symbol: '^VIX3M' };\n\n if (type in FRED_SERIES) return { provider: 'fred', seriesId: FRED_SERIES[type]!, rateSeries: true };\n\n if (COMPUTED_TYPES.has(type)) {\n const info: ProviderInfo = { provider: 'computed', dependsOn: 'Price', symbol: tickerSymbol! };\n if (isRateTickerSymbol(tickerSymbol)) info.rateSeries = true;\n return info;\n }\n\n if (CALENDAR_TYPES.has(type)) return { provider: 'calendar' };\n\n return { provider: 'none' };\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeSma(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const result: DailyBar[] = [];\n let sum = 0;\n for (let i = 0; i < lookback; i++) sum += bars[i].value;\n result.push({ date: bars[lookback - 1].date, value: sum / lookback });\n for (let i = lookback; i < bars.length; i++) {\n sum += bars[i].value - bars[i - lookback].value;\n result.push({ date: bars[i].date, value: sum / lookback });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeEma(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const multiplier = 2 / (lookback + 1);\n const result: DailyBar[] = [];\n let sum = 0;\n for (let i = 0; i < lookback; i++) sum += bars[i].value;\n let ema = sum / lookback;\n result.push({ date: bars[lookback - 1].date, value: ema });\n for (let i = lookback; i < bars.length; i++) {\n ema = bars[i].value * multiplier + ema * (1 - multiplier);\n result.push({ date: bars[i].date, value: ema });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeRsi(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback + 1) return [];\n const changes: number[] = [];\n for (let i = 1; i < bars.length; i++) {\n changes.push(bars[i].value - bars[i - 1].value);\n }\n let avgGain = 0;\n let avgLoss = 0;\n for (let i = 0; i < lookback; i++) {\n if (changes[i] > 0) avgGain += changes[i];\n else avgLoss += Math.abs(changes[i]);\n }\n avgGain /= lookback;\n avgLoss /= lookback;\n const result: DailyBar[] = [];\n const rs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n result.push({\n date: bars[lookback].date,\n value: avgLoss === 0 ? 100 : 100 - 100 / (1 + rs),\n });\n for (let i = lookback; i < changes.length; i++) {\n const gain = changes[i] > 0 ? changes[i] : 0;\n const loss = changes[i] < 0 ? Math.abs(changes[i]) : 0;\n avgGain = (avgGain * (lookback - 1) + gain) / lookback;\n avgLoss = (avgLoss * (lookback - 1) + loss) / lookback;\n const smoothRs = avgLoss === 0 ? 100 : avgGain / avgLoss;\n result.push({\n date: bars[i + 1].date,\n value: avgLoss === 0 ? 100 : 100 - 100 / (1 + smoothRs),\n });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport type ReturnMode = 'pct' | 'abs';\n\nexport function computeReturns(bars: DailyBar[], lookback: number, mode: ReturnMode = 'pct'): DailyBar[] {\n if (bars.length <= lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback; i < bars.length; i++) {\n const curr = bars[i]!.value;\n const prev = bars[i - lookback]!.value;\n const value = mode === 'abs' ? curr - prev : (curr - prev) / prev;\n result.push({ date: bars[i]!.date, value });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeVolatility(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback + 1) return [];\n const dailyReturns: { date: string; value: number }[] = [];\n for (let i = 1; i < bars.length; i++) {\n dailyReturns.push({\n date: bars[i].date,\n value: bars[i].value / bars[i - 1].value - 1,\n });\n }\n if (dailyReturns.length < lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback - 1; i < dailyReturns.length; i++) {\n const window = dailyReturns.slice(i - lookback + 1, i + 1);\n const mean = window.reduce((s, r) => s + r.value, 0) / lookback;\n const variance = window.reduce((s, r) => s + (r.value - mean) ** 2, 0) / lookback;\n result.push({ date: dailyReturns[i].date, value: Math.sqrt(variance) });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\nexport function computeDrawdown(bars: DailyBar[], lookback: number): DailyBar[] {\n if (bars.length < lookback) return [];\n const result: DailyBar[] = [];\n for (let i = lookback - 1; i < bars.length; i++) {\n let max = -Infinity;\n for (let j = i - lookback + 1; j <= i; j++) {\n if (bars[j].value > max) max = bars[j].value;\n }\n result.push({ date: bars[i].date, value: (bars[i].value - max) / max });\n }\n return result;\n}\n","import type { DailyBar } from '../handles/indicator';\n\ntype CalendarPeriod = 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year';\n\nfunction dayOfYear(d: Date): number {\n const start = new Date(d.getFullYear(), 0, 0);\n const diff = d.getTime() - start.getTime();\n return Math.floor(diff / (1000 * 60 * 60 * 24));\n}\n\nexport function computeCalendar(bars: DailyBar[], period: CalendarPeriod): DailyBar[] {\n return bars.map((bar) => {\n const [y, m, d] = bar.date.split('-').map(Number);\n const date = new Date(y, m - 1, d);\n let value: number;\n switch (period) {\n case 'Month':\n value = date.getMonth() + 1;\n break;\n case 'Day of Week':\n value = date.getDay();\n break;\n case 'Day of Month':\n value = date.getDate();\n break;\n case 'Day of Year':\n value = dayOfYear(date);\n break;\n }\n return { date: bar.date, value };\n });\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { IndicatorType } from '../providers/types';\nimport { computeSma } from './sma';\nimport { computeEma } from './ema';\nimport { computeRsi } from './rsi';\nimport { computeReturns } from './returns';\nimport { computeVolatility } from './volatility';\nimport { computeDrawdown } from './drawdown';\n\nexport { computeSma } from './sma';\nexport { computeEma } from './ema';\nexport { computeRsi } from './rsi';\nexport { computeReturns } from './returns';\nexport { computeVolatility } from './volatility';\nexport { computeDrawdown } from './drawdown';\nexport { computeCalendar } from './calendar';\ntype ComputeFn = (bars: DailyBar[], lookback: number) => DailyBar[];\n\nconst COMPUTATIONS: Partial<Record<IndicatorType, ComputeFn>> = {\n SMA: computeSma,\n EMA: computeEma,\n RSI: computeRsi,\n Return: computeReturns,\n Volatility: computeVolatility,\n Drawdown: computeDrawdown,\n};\n\nexport function getComputation(type: IndicatorType): ComputeFn | null {\n return COMPUTATIONS[type] ?? null;\n}\n","import type { MarketProvider } from './market';\nimport type { DailyBar } from '../handles/indicator';\n\nexport interface OverlayOptions {\n /**\n * When a given date in `overridesByDate` has no entry for the requested\n * symbol, append a synthetic bar using the last base bar's value.\n * Off by default — callers must opt in.\n */\n fallbackMissingQuotes?: boolean;\n}\n\n/**\n * Wraps a `MarketProvider` so that, for the dates listed in `overridesByDate`,\n * `fetchBars(symbol, ...)` returns a series with the corresponding bar either\n * appended (if the date is after the last base bar) or replaced (if it already\n * exists in the base bars).\n *\n * **Leverage invariant:** `MarketProvider.fetchBars` returns *raw* bars. This\n * overlay injects raw values only. Leverage compounding happens downstream in\n * `IndicatorHandle` sync; the overlay is intentionally leverage-agnostic.\n * If that downstream assumption ever changes, the override shape will need to\n * change too.\n */\nexport function createQuoteOverlay(\n base: MarketProvider,\n overridesByDate: Record<string, Record<string, number>>,\n options: OverlayOptions = {},\n): MarketProvider {\n return {\n async fetchBars(symbol: string, from?: string): Promise<DailyBar[]> {\n const bars = await base.fetchBars(symbol, from);\n const dates = Object.keys(overridesByDate).sort();\n if (dates.length === 0) return bars;\n\n const result = [...bars];\n for (const date of dates) {\n const overrideValue = overridesByDate[date]![symbol];\n let value: number | undefined = overrideValue;\n if (value === undefined) {\n if (!options.fallbackMissingQuotes) continue;\n if (result.length === 0) continue;\n value = result[result.length - 1]!.value;\n }\n const existingIdx = result.findIndex((b) => b.date === date);\n if (existingIdx >= 0) {\n result[existingIdx] = { date, value };\n } else {\n result.push({ date, value });\n }\n }\n return result;\n },\n };\n}\n","import type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { IndicatorType, Unit } from '../providers/types';\nimport { TickerHandle } from './ticker';\nimport { getProviderInfo, isRateTickerSymbol } from '../providers/mappings';\nimport { getComputation } from '../computations/index';\nimport { computeReturns } from '../computations/returns';\nimport { computeCalendar } from '../computations/calendar';\nimport { createQuoteOverlay } from '../providers/quote-overlay';\n\n/**\n * Subtract `days` calendar days from an ISO date string (YYYY-MM-DD).\n * Used to compute a `from` cutoff for bounded bar fetches in `computeAt`.\n */\nfunction _subtractCalendarDays(date: string, days: number): string {\n const d = new Date(date);\n d.setUTCDate(d.getUTCDate() - days);\n return d.toISOString().slice(0, 10);\n}\n\nexport interface DailyBar {\n date: string;\n value: number;\n}\n\nexport interface IndicatorIdentity {\n type: IndicatorType;\n ticker: TickerHandle | null;\n lookback: number;\n delay: number;\n unit: Unit | null;\n threshold: number | null;\n}\n\nexport interface DateRange {\n from?: string;\n to?: string;\n}\n\nexport class IndicatorHandle {\n readonly type: IndicatorType;\n readonly ticker: TickerHandle | null;\n readonly lookback: number;\n readonly delay: number;\n readonly unit: Unit | null;\n readonly threshold: number | null;\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n private _cachedSeries: DailyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, identity: IndicatorIdentity) {\n this._storage = storage;\n this._market = market;\n this.type = identity.type;\n this.ticker = identity.ticker;\n this.lookback = identity.lookback;\n this.delay = identity.delay;\n this.unit = identity.unit;\n this.threshold = identity.threshold;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('IndicatorHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(\n storage: StorageProvider,\n market: MarketProvider,\n id: number,\n identity: IndicatorIdentity,\n ): IndicatorHandle {\n const handle = new IndicatorHandle(storage, market, identity);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const tickerId = this.ticker ? (await this.ticker.resolve()).id : null;\n const result = await this._storage.indicators.findOrCreate({\n type: this.type,\n tickerId,\n lookback: this.lookback,\n delay: this.delay,\n unit: this.unit,\n threshold: this.threshold,\n });\n this._resolvedId = result.id;\n return result;\n }\n\n // ── Freshness & Sync ───────────────────────────────────────────────\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestSeriesDate(indicatorId: number): Promise<string | null> {\n return this._storage.indicators.getLatestSeriesDate(indicatorId);\n }\n\n private async _ensureFresh(): Promise<void> {\n const { id } = await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n // In-memory cache still valid\n if (this._cachedAsOf === latestClosed) return;\n\n const latestSeries = await this._getLatestSeriesDate(id);\n\n if (latestSeries === latestClosed) {\n // DB is fresh — invalidate in-memory cache so next read picks up DB data\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n // Need to sync — deduplicate concurrent calls\n if (!this._syncing) {\n this._syncing = this._sync(latestSeries ?? undefined, latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(fromDate: string | undefined, latestClosed: string): Promise<void> {\n const tickerSymbol = this.ticker?.symbol ?? null;\n const info = getProviderInfo(this.type, tickerSymbol);\n\n let bars: DailyBar[];\n\n switch (info.provider) {\n case 'yahoo':\n bars = await this._market.fetchBars(info.symbol, fromDate);\n break;\n\n case 'fred':\n bars = await this._market.fetchBars(info.seriesId, fromDate);\n break;\n\n case 'computed': {\n // Create an internal Price handle for the same ticker\n const priceHandle = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker: this.ticker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n\n // Recursively ensure Price data is fresh\n await priceHandle._ensureFresh();\n\n // Read Price series from DB\n const priceBars = await priceHandle._querySeriesFromDb();\n\n if (this.type === 'Return') {\n // For rate/yield series (e.g. DTB3, DFF), percentage change is broken\n // near zero and semantically wrong; use absolute differences instead.\n bars = computeReturns(priceBars, this.lookback, info.rateSeries ? 'abs' : 'pct');\n } else {\n const computeFn = getComputation(this.type);\n if (!computeFn) throw new Error(`No computation found for type \"${this.type}\"`);\n bars = computeFn(priceBars, this.lookback);\n }\n\n // If incremental, filter to only new bars\n if (fromDate) {\n bars = bars.filter((b) => b.date > fromDate);\n }\n break;\n }\n\n case 'calendar': {\n // Fetch all trading days to compute calendar values\n const allDays = await this._storage.tradingDays.getRange();\n const dayBars: DailyBar[] = allDays.map((date) => ({ date, value: 0 }));\n bars = computeCalendar(dayBars, this.type as 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year');\n\n if (fromDate) {\n bars = bars.filter((b) => b.date > fromDate);\n }\n break;\n }\n\n case 'none':\n // Threshold indicators have no series to sync\n return;\n }\n\n // Apply leverage to daily returns only for fetched (non-computed) indicators.\n // Computed indicators (RSI, SMA, etc.) already read from the leveraged price series.\n if (info.provider !== 'computed') {\n bars = await this._applyLeverage(bars, fromDate);\n }\n\n // Filter bars up to latestClosed\n bars = bars.filter((b) => b.date <= latestClosed);\n\n if (bars.length > 0) {\n await this._upsertSeries(bars);\n }\n }\n\n private async _upsertSeries(bars: DailyBar[]): Promise<void> {\n const { id } = await this.resolve();\n await this._storage.indicators.writeSeries(id, bars);\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<DailyBar[]> {\n const { id } = await this.resolve();\n return this._storage.indicators.getSeries(id, range);\n }\n\n withMarket(market: MarketProvider): IndicatorHandle {\n if (market === this._market) return this;\n return IndicatorHandle.fromResolved(this._storage, market, this.id, {\n type: this.type,\n ticker: this.ticker,\n lookback: this.lookback,\n delay: this.delay,\n unit: this.unit,\n threshold: this.threshold,\n });\n }\n\n /**\n * Apply leverage compounding to a raw bar series, anchored to a stored\n * leveraged value. Used by both `_sync` and `computeAt` so they stay\n * consistent.\n *\n * `anchorDate` is the date of the last *already-stored* leveraged bar\n * (i.e., the bar just before `rawBars[0]`). The stored leveraged value\n * at that date becomes `leveraged[0]`; raw returns are then compounded\n * forward for each subsequent bar.\n *\n * If no stored anchor exists (first-ever sync), falls back to rawBars[0]\n * as the starting raw value — identical to `_sync`'s behaviour.\n */\n private async _applyLeverage(rawBars: DailyBar[], anchorDate: string | undefined): Promise<DailyBar[]> {\n const leverage = this.ticker?.leverage ?? 1;\n if (leverage === 1 || rawBars.length === 0) return rawBars;\n // Rate tickers (DTB3, DFF, etc.) skip leverage compounding: the stored series\n // stays raw; the simulator applies the leverage multiplier at accrual time.\n if (isRateTickerSymbol(this.ticker?.symbol ?? null)) return rawBars;\n\n let anchor: number;\n if (anchorDate) {\n const lastStored = await this._storage.indicators.getValue(this._resolvedId!, anchorDate);\n anchor = lastStored ?? rawBars[0]!.value;\n } else {\n anchor = rawBars[0]!.value;\n }\n\n const leveraged: DailyBar[] = [{ date: rawBars[0]!.date, value: anchor }];\n for (let i = 1; i < rawBars.length; i++) {\n const dailyReturn = (rawBars[i]!.value - rawBars[i - 1]!.value) / rawBars[i - 1]!.value;\n const prev = leveraged[i - 1]!.value;\n leveraged.push({ date: rawBars[i]!.date, value: prev * (1 + leverage * dailyReturn) });\n }\n return leveraged;\n }\n\n /**\n * Compute the indicator's value at `date` using the given market (typically\n * an overlay market for pre-close preview). Pure — no writes to storage.\n *\n * For fetched types (yahoo/fred): fetches a small window of bars from\n * `market`, applies leverage compounding anchored to the stored leveraged\n * value at the bar before `date`.\n * For computed types (SMA, RSI, etc.): fetches enough raw price bars to\n * cover the indicator's lookback from `market`, applies leverage anchored\n * to the stored value just before the fetch window, runs the computation,\n * and returns the value at `date`.\n * For Threshold: returns the threshold constant.\n * For calendar: computes calendar value from the trading days list.\n * Returns null if the value cannot be computed.\n */\n async computeAt(market: MarketProvider, date: string): Promise<number | null> {\n // Threshold is a special case: it has no market data, just a constant value.\n if (this.type === 'Threshold') return this.threshold;\n\n const tickerSymbol = this.ticker?.symbol ?? null;\n const info = getProviderInfo(this.type, tickerSymbol);\n\n if (info.provider === 'none') return null;\n\n if (info.provider === 'calendar') {\n const allDays = await this._storage.tradingDays.getRange();\n const dayBars: DailyBar[] = allDays.map((d) => ({ date: d, value: 0 }));\n const computed = computeCalendar(dayBars, this.type as 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year');\n return computed.find((b) => b.date === date)?.value ?? null;\n }\n\n if (info.provider === 'computed') {\n // Fetch enough raw price bars to cover lookback + buffer (weekends/holidays).\n // We need `lookback` trading days before `date`, so we request a calendar\n // window of (lookback + 10) days to comfortably cover non-trading days.\n const from = _subtractCalendarDays(date, this.lookback + 10);\n const rawBars = await market.fetchBars(info.symbol, from);\n\n // Apply leverage anchored to the stored leveraged value at the date just\n // before the first fetched raw bar. This mirrors _sync's anchor logic\n // exactly: fromDate is the last stored bar, anchor is getValue(id, fromDate).\n const anchorDate = rawBars.length > 0 ? rawBars[0]!.date : undefined;\n const priceBars = await this._applyLeverage(rawBars, anchorDate);\n\n const computeFn = getComputation(this.type);\n if (!computeFn) throw new Error(`No computation found for type \"${this.type}\"`);\n const computed = computeFn(priceBars, this.lookback);\n return computed.find((b) => b.date === date)?.value ?? null;\n }\n\n // yahoo or fred: fetch a small window — just enough to get `date` and one\n // prior bar (needed for leverage return calculation). 5 calendar days is\n // enough to bridge a long weekend.\n const symbol = info.provider === 'yahoo' ? info.symbol : info.seriesId;\n const from = _subtractCalendarDays(date, 5);\n const rawBars = await market.fetchBars(symbol, from);\n\n const leverage = this.ticker?.leverage ?? 1;\n if (leverage === 1) {\n return rawBars.find((b) => b.date === date)?.value ?? null;\n }\n\n // Apply leverage compounding.\n // Find the bar just before `date` in rawBars to use as anchor reference.\n const dateIdx = rawBars.findIndex((b) => b.date === date);\n if (dateIdx < 0) return null; // date not in bars at all\n\n // We need the stored leveraged value at the previous day to anchor.\n const prevBar = rawBars[dateIdx - 1];\n if (!prevBar) {\n // No previous bar in the window — can't compound. Return raw value as fallback.\n return rawBars[dateIdx]!.value;\n }\n\n const storedPrev = await this._storage.indicators.getValue(this._resolvedId!, prevBar.date);\n const leveragedPrev = storedPrev ?? prevBar.value;\n const rawReturn = (rawBars[dateIdx]!.value - prevBar.value) / prevBar.value;\n return leveragedPrev * (1 + leverage * rawReturn);\n }\n\n // ── Public data access ─────────────────────────────────────────────\n\n async series(range?: DateRange): Promise<DailyBar[]> {\n if (this.type === 'Threshold') {\n return this._syntheticThresholdSeries(range);\n }\n await this._ensureFresh();\n if (this._cachedSeries && !range) return this._cachedSeries;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cachedSeries = bars;\n return bars;\n }\n\n private async _syntheticThresholdSeries(range?: DateRange): Promise<DailyBar[]> {\n const v = this.threshold!;\n const dates = await this._storage.tradingDays.getRange(range);\n return dates.map((date) => ({ date, value: v }));\n }\n\n async value(date?: string): Promise<number | null> {\n await this._ensureFresh();\n const { id } = await this.resolve();\n return this._storage.indicators.getValue(id, date);\n }\n\n /**\n * Read-only preview of the indicator series that includes an in-memory bar\n * at `date` computed via `computeAt` against a quote-overlay market. Does\n * NOT write to `indicators_series`. Safe to call before market close.\n *\n * @param date - Target trading day whose value is computed in-memory from\n * the overridden quotes. Must be in `tradingDays.getRange()`.\n * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.\n * Symbols omitted here fall back to yesterday's close via the overlay.\n * @param range - Optional filter applied to the returned bars.\n * @returns Stored historical bars plus (or with) today's in-memory value.\n */\n async previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<DailyBar[]> {\n const tradingDays = await this._storage.tradingDays.getRange();\n if (!tradingDays.includes(date)) {\n throw new Error(`previewSeries: ${date} is not a trading day`);\n }\n\n const overlay = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });\n\n let bars: DailyBar[];\n if (this.type === 'Threshold') {\n bars = await this._syntheticThresholdSeries();\n } else {\n bars = await this._querySeriesFromDb();\n }\n\n const todayValue = await this.computeAt(overlay, date);\n if (todayValue !== null) {\n const idx = bars.findIndex((b) => b.date === date);\n if (idx >= 0) {\n bars[idx] = { date, value: todayValue };\n } else {\n bars = [...bars, { date, value: todayValue }].sort((a, b) => a.date.localeCompare(b.date));\n }\n }\n\n if (range) {\n bars = bars.filter(\n (b) => (range.from === undefined || b.date >= range.from) && (range.to === undefined || b.date <= range.to),\n );\n }\n\n return bars;\n }\n}\n","import type { DailyBar } from '../handles/indicator';\n\ntype Comparison = '>' | '<' | '=';\n\nfunction computeBuffers(v2: number, tolerance: number, absolute: boolean): { upper: number; lower: number } {\n if (tolerance === 0) return { upper: v2, lower: v2 };\n if (absolute) return { upper: v2 + tolerance, lower: v2 - tolerance };\n return { upper: v2 * (1 + tolerance / 100), lower: v2 * (1 - tolerance / 100) };\n}\n\nfunction rawCompare(v1: number, v2: number, comparison: Comparison): number {\n switch (comparison) {\n case '>':\n return v1 > v2 ? 1 : 0;\n case '<':\n return v1 < v2 ? 1 : 0;\n case '=':\n return v1 === v2 ? 1 : 0;\n }\n}\n\nexport function evaluateSignal(\n series1: DailyBar[],\n series2: DailyBar[],\n comparison: Comparison,\n tolerance: number,\n absolute: boolean,\n previousValue?: number,\n): DailyBar[] {\n const s2Map = new Map<string, number>();\n for (const bar of series2) {\n s2Map.set(bar.date, bar.value);\n }\n\n const result: DailyBar[] = [];\n let prev = previousValue;\n\n for (const bar1 of series1) {\n const v2 = s2Map.get(bar1.date);\n if (v2 === undefined) continue;\n\n const v1 = bar1.value;\n const { upper, lower } = computeBuffers(v2, tolerance, absolute);\n\n let value: number;\n\n if (tolerance === 0) {\n value = rawCompare(v1, v2, comparison);\n } else if (comparison === '=') {\n value = v1 >= lower && v1 <= upper ? 1 : 0;\n } else if (prev === undefined) {\n value = rawCompare(v1, v2, comparison);\n } else if (comparison === '>') {\n if (prev === 1) {\n value = v1 < lower ? 0 : 1;\n } else {\n value = v1 > upper ? 1 : 0;\n }\n } else {\n // comparison === '<'\n if (prev === 1) {\n value = v1 > upper ? 0 : 1;\n } else {\n value = v1 < lower ? 1 : 0;\n }\n }\n\n result.push({ date: bar1.date, value });\n prev = value;\n }\n\n return result;\n}\n","// src/handles/signal.ts\nimport type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { Comparison } from '../providers/types';\nimport type { IndicatorHandle, DailyBar, DateRange } from './indicator';\nimport { evaluateSignal } from '../computations/signal';\nimport { createQuoteOverlay } from '../providers/quote-overlay';\n\nconst ABSOLUTE_TOLERANCE_TYPES = new Set([\n 'Return',\n 'Volatility',\n 'Drawdown',\n 'VIX',\n 'VIX3M',\n 'T3M',\n 'T6M',\n 'T1Y',\n 'T2Y',\n 'T3Y',\n 'T5Y',\n 'T7Y',\n 'T10Y',\n 'T20Y',\n 'T30Y',\n]);\n\nexport interface SignalIdentity {\n indicator1: IndicatorHandle;\n indicator2: IndicatorHandle;\n comparison: Comparison;\n tolerance: number;\n}\n\nexport class SignalHandle {\n readonly indicator1: IndicatorHandle;\n readonly indicator2: IndicatorHandle;\n readonly comparison: Comparison;\n readonly tolerance: number;\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n private _cachedSeries: DailyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, identity: SignalIdentity) {\n this._storage = storage;\n this._market = market;\n this.indicator1 = identity.indicator1;\n this.indicator2 = identity.indicator2;\n this.comparison = identity.comparison;\n this.tolerance = identity.tolerance;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('SignalHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(\n storage: StorageProvider,\n market: MarketProvider,\n id: number,\n identity: SignalIdentity,\n ): SignalHandle {\n const handle = new SignalHandle(storage, market, identity);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n const [ind1, ind2] = await Promise.all([this.indicator1.resolve(), this.indicator2.resolve()]);\n const result = await this._storage.signals.findOrCreate({\n indicatorId1: ind1.id,\n indicatorId2: ind2.id,\n comparison: this.comparison,\n tolerance: this.tolerance,\n });\n this._resolvedId = result.id;\n return result;\n }\n\n // ── Freshness & Sync ───────────────────────────────────────────────\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestSignalSeriesDate(signalId: number): Promise<string | null> {\n return this._storage.signals.getLatestSeriesDate(signalId);\n }\n\n private async _getLastSignalValue(signalId: number): Promise<number | null> {\n return this._storage.signals.getLastValue(signalId);\n }\n\n private async _ensureFresh(): Promise<void> {\n const { id } = await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n if (this._cachedAsOf === latestClosed) return;\n\n // Ensure both indicators are fresh first\n await Promise.all([this.indicator1.series(), this.indicator2.series()]);\n\n const latestSeries = await this._getLatestSignalSeriesDate(id);\n\n if (latestSeries === latestClosed) {\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n if (!this._syncing) {\n this._syncing = this._sync(latestSeries ?? undefined, latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cachedSeries = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(fromDate: string | undefined, latestClosed: string): Promise<void> {\n const { id } = await this.resolve();\n\n const range = fromDate ? { from: fromDate } : undefined;\n const [series1, series2] = await Promise.all([this.indicator1.series(range), this.indicator2.series(range)]);\n\n const previousValue = fromDate ? ((await this._getLastSignalValue(id)) ?? undefined) : undefined;\n\n const absolute = ABSOLUTE_TOLERANCE_TYPES.has(this.indicator1.type);\n const signalBars = evaluateSignal(series1, series2, this.comparison, this.tolerance, absolute, previousValue);\n\n const bars = signalBars.filter((b) => b.date <= latestClosed);\n\n if (bars.length > 0) {\n await this._upsertSeries(bars);\n }\n }\n\n private async _upsertSeries(bars: DailyBar[]): Promise<void> {\n const { id } = await this.resolve();\n await this._storage.signals.writeSeries(id, bars);\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<DailyBar[]> {\n const { id } = await this.resolve();\n return this._storage.signals.getSeries(id, range);\n }\n\n withMarket(market: MarketProvider): SignalHandle {\n if (market === this._market) return this;\n return SignalHandle.fromResolved(this._storage, market, this.id, {\n indicator1: this.indicator1.withMarket(market),\n indicator2: this.indicator2.withMarket(market),\n comparison: this.comparison,\n tolerance: this.tolerance,\n });\n }\n\n /**\n * Compute the signal's boolean value at `date` using the given market\n * (typically an overlay market for pre-close preview). Pure — no writes.\n * Returns null if either indicator cannot produce a value at `date`.\n *\n * @param prevBool - The signal's boolean value at the bar immediately\n * preceding `date`, used for hysteresis when `tolerance > 0`. If not\n * provided, falls back to `storage.signals.getLastValue` (suitable for\n * standalone callers). On the preview path `_evaluate` passes this from\n * the in-memory `dateMap` so we never read stale storage.\n */\n async computeAt(market: MarketProvider, date: string, prevBool?: boolean | null): Promise<boolean | null> {\n const [v1, v2] = await Promise.all([\n this.indicator1.computeAt(market, date),\n this.indicator2.computeAt(market, date),\n ]);\n if (v1 === null || v2 === null) return null;\n\n const absolute = ABSOLUTE_TOLERANCE_TYPES.has(this.indicator1.type);\n\n // Replicate the evaluateSignal single-bar logic inline (no hysteresis needed\n // for a single-point preview; we use the last historical value as \"prev\").\n if (this.tolerance === 0) {\n switch (this.comparison) {\n case '>':\n return v1 > v2;\n case '<':\n return v1 < v2;\n case '=':\n return v1 === v2;\n }\n }\n\n const tolerance = this.tolerance;\n const upper = absolute ? v2 + tolerance : v2 * (1 + tolerance / 100);\n const lower = absolute ? v2 - tolerance : v2 * (1 - tolerance / 100);\n\n if (this.comparison === '=') {\n return v1 >= lower && v1 <= upper;\n }\n // For '>' and '<' with tolerance, we need hysteresis (prev state).\n // Use the in-memory prevBool if provided (preview path); otherwise fall\n // back to storage (standalone callers / write path).\n let resolvedPrevBool: boolean;\n if (prevBool !== undefined && prevBool !== null) {\n resolvedPrevBool = prevBool;\n } else {\n const prev = await this._storage.signals.getLastValue(this.id);\n resolvedPrevBool = prev === 1;\n }\n if (this.comparison === '>') {\n return resolvedPrevBool ? v1 >= lower : v1 > upper;\n }\n // '<'\n return resolvedPrevBool ? v1 <= upper : v1 < lower;\n }\n\n // ── Public data access ─────────────────────────────────────────────\n\n async series(range?: DateRange): Promise<DailyBar[]> {\n await this._ensureFresh();\n if (this._cachedSeries && !range) return this._cachedSeries;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cachedSeries = bars;\n return bars;\n }\n\n async value(date?: string): Promise<number | null> {\n await this._ensureFresh();\n if (date) {\n const series = await this._querySeriesFromDb({ from: date, to: date });\n return series.length > 0 ? series[0]!.value : null;\n }\n const { id } = await this.resolve();\n return this._storage.signals.getLastValue(id);\n }\n\n /**\n * Read-only preview of the signal series with an in-memory bar at `date`\n * computed via `computeAt` against a quote-overlay market. Does NOT write\n * to `signals_series`.\n *\n * @param date - Target trading day whose boolean is computed in-memory.\n * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.\n * @param range - Optional filter applied to the returned bars.\n */\n async previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<DailyBar[]> {\n const tradingDays = await this._storage.tradingDays.getRange();\n if (!tradingDays.includes(date)) {\n throw new Error(`previewSeries: ${date} is not a trading day`);\n }\n\n const overlay = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });\n\n let bars = await this._querySeriesFromDb();\n\n // Derive yesterday's boolean from the in-memory dateMap for hysteresis,\n // mirroring StrategyHandle._evaluate's preview path.\n const dateMap = new Map<string, boolean>();\n for (const bar of bars) dateMap.set(bar.date, bar.value === 1);\n\n const limitIdx = tradingDays.indexOf(date);\n const prevDate = limitIdx > 0 ? tradingDays[limitIdx - 1] : undefined;\n const prevBool = prevDate !== undefined ? (dateMap.get(prevDate) ?? null) : null;\n\n const todayBool = await this.computeAt(overlay, date, prevBool);\n if (todayBool !== null) {\n const numeric = todayBool ? 1 : 0;\n const idx = bars.findIndex((b) => b.date === date);\n if (idx >= 0) {\n bars[idx] = { date, value: numeric };\n } else {\n bars = [...bars, { date, value: numeric }].sort((a, b) => a.date.localeCompare(b.date));\n }\n }\n\n if (range) {\n bars = bars.filter(\n (b) => (range.from === undefined || b.date >= range.from) && (range.to === undefined || b.date <= range.to),\n );\n }\n\n return bars;\n }\n}\n","import type { StorageProvider } from '../providers/storage';\nimport { TickerHandle } from './ticker';\n\nexport class AllocationHandle {\n readonly holdings: [TickerHandle, number][];\n\n private _storage: StorageProvider;\n private _resolvedId: number | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n\n constructor(storage: StorageProvider, holdings: [TickerHandle, number][]) {\n const total = holdings.reduce((sum, [, weight]) => sum + weight, 0);\n if (Math.abs(total - 1) > 1e-9) {\n throw new Error(`Allocation weights must sum to 1, got ${total}`);\n }\n this._storage = storage;\n this.holdings = holdings;\n }\n\n get id(): number {\n if (this._resolvedId == null)\n throw new Error('AllocationHandle not yet resolved. Call resolve(), or access via an async method.');\n return this._resolvedId;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) this._resolving = this._doResolve();\n return this._resolving;\n }\n\n static fromResolved(storage: StorageProvider, id: number, holdings: [TickerHandle, number][]): AllocationHandle {\n const handle = new AllocationHandle(storage, holdings);\n handle._resolvedId = id;\n return handle;\n }\n\n private async _doResolve(): Promise<{ id: number }> {\n await Promise.all(this.holdings.map(([ticker]) => ticker.resolve()));\n\n const holdingsJson: Record<string, number> = {};\n for (const [ticker, weight] of this.holdings) {\n const key = ticker.leverage !== 1 ? `${ticker.symbol}?L=${ticker.leverage}` : ticker.symbol;\n holdingsJson[key] = weight;\n }\n\n const result = await this._storage.allocations.findOrCreate(holdingsJson);\n this._resolvedId = result.id;\n return result;\n }\n}\n","import { customAlphabet } from 'nanoid';\nimport type { StorageProvider } from '../providers/storage';\nimport type { MarketProvider } from '../providers/market';\nimport type { TradingFreq, StrategySeriesEntry } from '../providers/types';\nimport { SignalHandle } from './signal';\nimport { AllocationHandle } from './allocation';\nimport { TickerHandle } from './ticker';\nimport { IndicatorHandle } from './indicator';\nimport type { DateRange } from './indicator';\nimport { evaluateStrategy, computeRebalanceDates } from '../computations/strategy';\nimport { runSimulation } from '../backtest/simulate';\nimport { SimulationHandle } from '../backtest/types';\nimport type { SimulateOptions, FinalState } from '../backtest/types';\nimport { createQuoteOverlay } from '../providers/quote-overlay';\n\nconst nanoid = customAlphabet('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 21);\n\nexport interface StrategyRule {\n when?: SignalHandle[];\n hold: AllocationHandle;\n}\n\nexport interface StrategyBar {\n date: string;\n allocation: AllocationHandle;\n}\n\nexport interface StrategyOptions {\n name: string;\n freq?: TradingFreq;\n offset?: number;\n rules: StrategyRule[];\n}\n\nexport class StrategyHandle {\n private _linkId: string | null;\n private _name: string | null;\n private _freq: TradingFreq;\n private _offset: number;\n private _rules: StrategyRule[];\n\n private _storage: StorageProvider;\n private _market: MarketProvider;\n private _resolvedId: number | null = null;\n private _resolvedLinkId: string | null = null;\n private _resolving: Promise<{ id: number }> | null = null;\n private _allocationMap: Map<number, AllocationHandle> = new Map();\n\n private _cache: StrategyBar[] | null = null;\n private _cachedAsOf: string | null = null;\n private _syncing: Promise<void> | null = null;\n\n constructor(storage: StorageProvider, market: MarketProvider, optionsOrLinkId: StrategyOptions | string) {\n this._storage = storage;\n this._market = market;\n\n if (typeof optionsOrLinkId === 'string') {\n this._linkId = optionsOrLinkId;\n this._name = null;\n this._freq = 'Daily';\n this._offset = 0;\n this._rules = [];\n } else {\n const opts = optionsOrLinkId;\n if (opts.rules.length === 0) {\n throw new Error('Strategy must have at least one rule');\n }\n const lastRule = opts.rules[opts.rules.length - 1]!;\n if (lastRule.when && lastRule.when.length > 0) {\n throw new Error('Last rule must be a fallback (no when clause)');\n }\n for (let i = 0; i < opts.rules.length - 1; i++) {\n const rule = opts.rules[i]!;\n if (rule.when !== undefined && rule.when.length === 0) {\n throw new Error(\n `Rule ${i} has an empty when clause and will match unconditionally, making subsequent rules unreachable`,\n );\n }\n }\n this._linkId = null;\n this._name = opts.name;\n this._freq = opts.freq ?? 'Daily';\n this._offset = opts.offset ?? 0;\n this._rules = opts.rules;\n }\n }\n\n get id(): number {\n if (this._resolvedId == null) throw new Error('StrategyHandle not yet resolved. Call resolve() first.');\n return this._resolvedId;\n }\n\n get link(): string {\n if (this._resolvedLinkId == null) throw new Error('StrategyHandle not yet resolved. Call resolve() first.');\n return this._resolvedLinkId;\n }\n\n get name(): string | null {\n return this._name;\n }\n\n get freq(): TradingFreq {\n return this._freq;\n }\n\n get offset(): number {\n return this._offset;\n }\n\n get rules(): StrategyRule[] {\n return this._rules;\n }\n\n async resolve(): Promise<{ id: number }> {\n if (this._resolvedId != null) return { id: this._resolvedId };\n if (!this._resolving) {\n this._resolving =\n this._linkId !== null && this._name === null ? this._doResolveReference() : this._doResolveCreate();\n }\n return this._resolving;\n }\n\n private async _doResolveCreate(): Promise<{ id: number }> {\n const allSignals = new Set<SignalHandle>();\n const allAllocations = new Set<AllocationHandle>();\n for (const rule of this._rules) {\n if (rule.when) rule.when.forEach((s) => allSignals.add(s));\n allAllocations.add(rule.hold);\n }\n\n await Promise.all([\n ...Array.from(allSignals).map((s) => s.resolve()),\n ...Array.from(allAllocations).map((a) => a.resolve()),\n ]);\n\n const linkId = nanoid();\n const result = await this._storage.strategies.create({\n linkId,\n name: this._name!,\n freq: this._freq,\n offset: this._offset,\n rules: this._rules.map((rule) => ({\n signalIds: (rule.when ?? []).map((s) => s.id),\n allocationId: rule.hold.id,\n })),\n });\n\n this._resolvedId = result.id;\n this._resolvedLinkId = linkId;\n\n for (const rule of this._rules) {\n this._allocationMap.set(rule.hold.id, rule.hold);\n }\n\n return result;\n }\n\n private async _doResolveReference(): Promise<{ id: number }> {\n const ref = await this._storage.strategies.resolveReference(this._linkId!);\n this._resolvedId = ref.id;\n this._resolvedLinkId = this._linkId!;\n this._name = ref.name;\n this._freq = ref.freq;\n this._offset = ref.offset;\n\n // Build handles bottom-up from reference data\n const tickerMap = new Map<number, TickerHandle>();\n for (const t of ref.rules.tickers) {\n tickerMap.set(t.id, TickerHandle.fromResolved(this._storage, t.id, t.symbol, t.leverage));\n }\n\n const indicatorMap = new Map<number, IndicatorHandle>();\n for (const ind of ref.rules.indicators) {\n const ticker = ind.tickerId ? (tickerMap.get(ind.tickerId) ?? null) : null;\n indicatorMap.set(\n ind.id,\n IndicatorHandle.fromResolved(this._storage, this._market, ind.id, {\n type: ind.type,\n ticker,\n lookback: ind.lookback,\n delay: ind.delay,\n unit: ind.unit,\n threshold: ind.threshold,\n }),\n );\n }\n\n const signalMap = new Map<number, SignalHandle>();\n for (const sig of ref.rules.signals) {\n signalMap.set(\n sig.id,\n SignalHandle.fromResolved(this._storage, this._market, sig.id, {\n indicator1: indicatorMap.get(sig.indicatorId1)!,\n indicator2: indicatorMap.get(sig.indicatorId2)!,\n comparison: sig.comparison,\n tolerance: sig.tolerance,\n }),\n );\n }\n\n const allocationHandleMap = new Map<number, AllocationHandle>();\n for (const alloc of ref.rules.allocations) {\n const holdings: [TickerHandle, number][] = Object.entries(alloc.holdings).map(([key, weight]) => {\n const match = key.match(/^(.+)\\?L=(.+)$/);\n const symbol = match ? match[1]! : key;\n const leverage = match ? Number(match[2]) : 1;\n return [new TickerHandle(this._storage, symbol, leverage), weight];\n });\n const handle = AllocationHandle.fromResolved(this._storage, alloc.id, holdings);\n allocationHandleMap.set(alloc.id, handle);\n this._allocationMap.set(alloc.id, handle);\n }\n\n // Reconstruct rules\n this._rules = ref.rules.definition.map((rule) => ({\n when: rule.signalIds && rule.signalIds.length > 0 ? rule.signalIds.map((id) => signalMap.get(id)!) : undefined,\n hold: allocationHandleMap.get(rule.allocationId)!,\n }));\n\n return { id: ref.id };\n }\n\n private async _getLatestClosedTradingDay(): Promise<string> {\n const date = await this._storage.tradingDays.getLatestClosed();\n if (!date) throw new Error('No closed trading days found');\n return date;\n }\n\n private async _getLatestStrategySeriesDate(): Promise<string | null> {\n const { id } = await this.resolve();\n return this._storage.strategies.getLatestSeriesDate(id);\n }\n\n private async _ensureFresh(): Promise<void> {\n await this.resolve();\n const latestClosed = await this._getLatestClosedTradingDay();\n\n if (this._cachedAsOf === latestClosed) return;\n\n const latestSeries = await this._getLatestStrategySeriesDate();\n\n if (latestSeries === latestClosed) {\n this._cache = null;\n this._cachedAsOf = latestClosed;\n return;\n }\n\n if (!this._syncing) {\n this._syncing = this._sync(latestClosed).finally(() => {\n this._syncing = null;\n });\n }\n await this._syncing;\n\n this._cache = null;\n this._cachedAsOf = latestClosed;\n }\n\n private async _sync(latestClosed: string): Promise<void> {\n const { id } = await this.resolve();\n const { entries } = await this._evaluate(this._market, latestClosed);\n if (entries.length > 0) {\n await this._storage.strategies.writeSeries(id, entries);\n }\n }\n\n /**\n * Pure evaluate — runs the same pipeline as _sync but returns the computed\n * evaluation instead of persisting. Used by both _sync (post-close write\n * path) and previewAllocation (pre-close read-only path).\n *\n * The `market === this._market` identity check is what distinguishes the two\n * paths: when they are the same object the method takes the write path (syncing\n * signals through storage as normal); when they differ it takes the read-only\n * preview path (historical bars from storage, today's value computed in-memory\n * via `computeAt`). Callers that want the preview path must therefore supply a\n * *different* market object — for example one produced by `createQuoteOverlay`.\n */\n private async _evaluate(\n market: MarketProvider,\n limitDate: string,\n ): Promise<{ allocations: AllocationHandle[]; entries: StrategySeriesEntry[] }> {\n const allSignals = new Set<SignalHandle>();\n for (const rule of this._rules) {\n if (rule.when) rule.when.forEach((s) => allSignals.add(s));\n }\n\n const signalSeries = new Map<number, Map<string, boolean>>();\n\n // Collect the ordered list of trading days once so the preview path can\n // look up the day immediately before limitDate without a second storage call.\n const tradingDays = await this._storage.tradingDays.getRange();\n\n if (market === this._market) {\n // Normal (post-close) path: sync signals through storage, may write.\n await Promise.all(\n Array.from(allSignals).map(async (signal) => {\n const bars = await signal.withMarket(market).series();\n const dateMap = new Map<string, boolean>();\n for (const bar of bars) dateMap.set(bar.date, bar.value === 1);\n signalSeries.set(signal.id, dateMap);\n }),\n );\n } else {\n // Overlay (pre-close preview) path: read historical from storage, then\n // compute today's signal value in-memory via computeAt. No writes anywhere.\n //\n // Find the trading day immediately before limitDate so we can pass its\n // in-memory boolean as prevBool to computeAt (hysteresis, Issue 4).\n const limitIdx = tradingDays.indexOf(limitDate);\n const prevDate = limitIdx > 0 ? tradingDays[limitIdx - 1] : undefined;\n\n await Promise.all(\n Array.from(allSignals).map(async (signal) => {\n // Read all historical signal bars from storage (pure read).\n const historicalBars = await this._storage.signals.getSeries(signal.id);\n const dateMap = new Map<string, boolean>();\n for (const bar of historicalBars) dateMap.set(bar.date, bar.value === 1);\n\n // Look up yesterday's boolean from the in-memory map (avoids stale\n // storage read for hysteresis on the preview path).\n const prevBool = prevDate !== undefined ? (dateMap.get(prevDate) ?? null) : null;\n\n // Compute today's (limitDate) signal value using the overlay market.\n const todayValue = await signal.computeAt(market, limitDate, prevBool);\n if (todayValue !== null) {\n dateMap.set(limitDate, todayValue);\n }\n\n signalSeries.set(signal.id, dateMap);\n }),\n );\n }\n\n const rebalanceDates = computeRebalanceDates(tradingDays, this._freq, this._offset);\n\n const allocations: AllocationHandle[] = [];\n const allocIndexMap = new Map<number, number>();\n const rulesInput = this._rules.map((rule) => {\n let allocIdx = allocIndexMap.get(rule.hold.id);\n if (allocIdx === undefined) {\n allocIdx = allocations.length;\n allocations.push(rule.hold);\n allocIndexMap.set(rule.hold.id, allocIdx);\n }\n return {\n signalIds: (rule.when ?? []).map((s) => s.id),\n allocationIndex: allocIdx,\n };\n });\n\n const evalResult = evaluateStrategy(signalSeries, rulesInput, rebalanceDates, tradingDays);\n const entries: StrategySeriesEntry[] = Array.from(evalResult.entries())\n .filter(([date]) => date <= limitDate)\n .map(([date, allocIdx]) => ({ date, allocationId: allocations[allocIdx]!.id }));\n\n return { allocations, entries };\n }\n\n private async _querySeriesFromDb(range?: DateRange): Promise<StrategyBar[]> {\n const { id } = await this.resolve();\n const entries = await this._storage.strategies.getSeries(id, range);\n return entries.map((e) => ({\n date: e.date,\n allocation: this._allocationMap.get(e.allocationId)!,\n }));\n }\n\n async series(range?: DateRange): Promise<StrategyBar[]> {\n await this._ensureFresh();\n if (this._cache && !range) return this._cache;\n const bars = await this._querySeriesFromDb(range);\n if (!range) this._cache = bars;\n return bars;\n }\n\n async value(date?: string): Promise<AllocationHandle | null> {\n await this._ensureFresh();\n const bars = date ? await this._querySeriesFromDb({ from: date, to: date }) : await this._querySeriesFromDb();\n if (bars.length === 0) return null;\n return date ? bars[0]!.allocation : bars[bars.length - 1]!.allocation;\n }\n\n async simulate(options: SimulateOptions): Promise<SimulationHandle> {\n const bars = await this.series({ from: options.from, to: options.to });\n if (bars.length === 0) {\n return new SimulationHandle([], [], options.portfolio);\n }\n\n const prices = await this._fetchPricesForTickers(bars, options.from, options.to);\n const tradingDays = bars.map((b) => b.date);\n const rebalanceDates = computeRebalanceDates(tradingDays, this._freq, this._offset);\n\n // Force day 1 rebalance so existing positions align to strategy\n rebalanceDates.add(bars[0]!.date);\n\n const result = runSimulation(bars, prices, rebalanceDates, options.portfolio);\n\n // Build finalState for live push support\n const lastBar = bars[bars.length - 1]!;\n const lastDate = lastBar.date;\n const lastAllocation = lastBar.allocation;\n\n // leveragedPrices: keyed as \"symbol:leverage\", values are the leveraged prices from _fetchPricesForTickers\n const leveragedPrices: Record<string, number> = {};\n for (const [ticker, _weight] of lastAllocation.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const key = `${ticker.symbol}:${ticker.leverage}`;\n const price = prices[key]?.[lastDate];\n if (price != null) leveragedPrices[key] = price;\n }\n\n // closePrices: raw (unleveraged) close prices for computing real returns\n const closePrices: Record<string, number> = {};\n await this._fetchRawClosePrices(bars, lastDate, closePrices);\n\n const finalState: FinalState = {\n portfolio: result.finalPortfolio,\n allocation: lastAllocation,\n closePrices,\n leveragedPrices,\n };\n\n return new SimulationHandle(result.series, result.trades, options.portfolio, finalState);\n }\n\n /**\n * Preview the allocation this strategy would produce for `date` if today\n * closed at the provided raw quote prices. Does NOT write to strategies_series,\n * signals_series, or indicators_series. Safe to call before market close.\n *\n * @param date - The trading day to preview (must be in tradingDays.getRange()).\n * @param quoteOverrides - Raw (unleveraged) live prices keyed by ticker symbol.\n * Symbols absent from this map will fall back to yesterday's close via the\n * quote overlay.\n * @returns The AllocationHandle for `date`, or null if the strategy has no\n * evaluable entry for that date.\n */\n async previewAllocation(date: string, quoteOverrides: Record<string, number>): Promise<AllocationHandle | null> {\n await this.resolve();\n\n const tradingDays = await this._storage.tradingDays.getRange();\n if (!tradingDays.includes(date)) {\n throw new Error(`previewAllocation: ${date} is not a trading day`);\n }\n\n const overlayMarket = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });\n\n // _evaluate detects market !== this._market and takes the no-write path.\n const { allocations, entries } = await this._evaluate(overlayMarket, date);\n\n const target = entries.find((e) => e.date === date);\n if (!target) return null;\n\n const alloc = allocations.find((a) => a.id === target.allocationId);\n return alloc ?? this._allocationMap.get(target.allocationId) ?? null;\n }\n\n /**\n * Read-only preview of the strategy's allocation series including `date`.\n * Returns stored historical allocations plus an in-memory bar at `date`\n * computed via the same overlay path as `previewAllocation`.\n *\n * @param date - Target trading day to splice in-memory via overlay market.\n * @param quoteOverrides - Raw (unleveraged) quotes keyed by ticker symbol.\n * @param range - Optional filter applied to the returned bars.\n */\n async previewSeries(date: string, quoteOverrides: Record<string, number>, range?: DateRange): Promise<StrategyBar[]> {\n await this.resolve();\n\n const tradingDays = await this._storage.tradingDays.getRange();\n if (!tradingDays.includes(date)) {\n throw new Error(`previewSeries: ${date} is not a trading day`);\n }\n\n const overlayMarket = createQuoteOverlay(this._market, { [date]: quoteOverrides }, { fallbackMissingQuotes: true });\n\n const { allocations, entries } = await this._evaluate(overlayMarket, date);\n\n const allocById = new Map<number, AllocationHandle>();\n for (const a of allocations) allocById.set(a.id, a);\n for (const [id, a] of this._allocationMap) if (!allocById.has(id)) allocById.set(id, a);\n\n let bars: StrategyBar[] = entries.map((e) => ({\n date: e.date,\n allocation: allocById.get(e.allocationId)!,\n }));\n\n if (range) {\n bars = bars.filter(\n (b) => (range.from === undefined || b.date >= range.from) && (range.to === undefined || b.date <= range.to),\n );\n }\n\n return bars;\n }\n\n private async _fetchPricesForTickers(\n bars: StrategyBar[],\n from: string,\n to: string,\n ): Promise<Record<string, Record<string, number>>> {\n const tickerMap = new Map<string, TickerHandle>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n const key = `${ticker.symbol}:${ticker.leverage}`;\n if (!tickerMap.has(key)) {\n tickerMap.set(key, ticker);\n }\n }\n }\n\n const entries = await Promise.all(\n Array.from(tickerMap.entries()).map(async ([key, ticker]) => {\n const priceIndicator = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n const priceBars = await priceIndicator.series({ from, to });\n const dateMap: Record<string, number> = {};\n for (const bar of priceBars) {\n dateMap[bar.date] = bar.value;\n }\n return [key, dateMap] as const;\n }),\n );\n\n return Object.fromEntries(entries);\n }\n\n private async _fetchRawClosePrices(\n bars: StrategyBar[],\n lastDate: string,\n closePrices: Record<string, number>,\n ): Promise<void> {\n const symbols = new Set<string>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n if (ticker.symbol !== 'CASHX') symbols.add(ticker.symbol);\n }\n }\n\n await Promise.all(\n Array.from(symbols).map(async (symbol) => {\n const rawTicker = new TickerHandle(this._storage, symbol, 1);\n const priceIndicator = new IndicatorHandle(this._storage, this._market, {\n type: 'Price',\n ticker: rawTicker,\n lookback: 0,\n delay: 0,\n unit: null,\n threshold: null,\n });\n const priceBars = await priceIndicator.series({ from: lastDate, to: lastDate });\n if (priceBars.length > 0) {\n closePrices[symbol] = priceBars[0]!.value;\n }\n }),\n );\n }\n}\n","import type { TradingFreq } from '../providers/types';\n\nfunction getPeriodKey(dateStr: string, freq: TradingFreq): string {\n const d = new Date(dateStr + 'T00:00:00Z');\n const y = d.getUTCFullYear();\n const m = d.getUTCMonth();\n\n switch (freq) {\n case 'Weekly': {\n const thu = new Date(d);\n thu.setUTCDate(thu.getUTCDate() + 3 - ((thu.getUTCDay() + 6) % 7));\n const yearStart = new Date(Date.UTC(thu.getUTCFullYear(), 0, 1));\n const weekNo = Math.ceil(((thu.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\n return `${thu.getUTCFullYear()}-W${weekNo}`;\n }\n case 'Monthly':\n return `${y}-${m}`;\n case 'Bi-monthly':\n return `${y}-${Math.floor(m / 2)}`;\n case 'Quarterly':\n return `${y}-Q${Math.floor(m / 3)}`;\n case 'Every 4 Months':\n return `${y}-${Math.floor(m / 4)}`;\n case 'Semiannually':\n return `${y}-H${Math.floor(m / 6)}`;\n case 'Yearly':\n return `${y}`;\n default:\n return `${y}-${m}`;\n }\n}\n\nexport function computeRebalanceDates(tradingDays: string[], freq: TradingFreq, offset: number): Set<string> {\n if (freq === 'Daily') return new Set(tradingDays);\n\n const groups = new Map<string, number[]>();\n for (let i = 0; i < tradingDays.length; i++) {\n const key = getPeriodKey(tradingDays[i], freq);\n if (!groups.has(key)) groups.set(key, []);\n groups.get(key)!.push(i);\n }\n\n const result = new Set<string>();\n for (const indices of groups.values()) {\n const lastIdx = indices[indices.length - 1];\n const targetIdx = lastIdx - offset;\n if (targetIdx >= 0 && targetIdx < tradingDays.length) {\n result.add(tradingDays[targetIdx]);\n }\n }\n\n return result;\n}\n\nexport interface StrategyRuleInput {\n signalIds: number[];\n allocationIndex: number;\n}\n\nexport function evaluateStrategy(\n signalSeries: Map<number, Map<string, boolean>>,\n rules: StrategyRuleInput[],\n rebalanceDates: Set<string>,\n tradingDays: string[],\n): Map<string, number> {\n const result = new Map<string, number>();\n let current: number | undefined;\n\n for (const date of tradingDays) {\n if (rebalanceDates.has(date)) {\n for (const rule of rules) {\n if (rule.signalIds.length === 0) {\n current = rule.allocationIndex;\n break;\n }\n const allTrue = rule.signalIds.every((id) => signalSeries.get(id)?.get(date) ?? false);\n if (allTrue) {\n current = rule.allocationIndex;\n break;\n }\n }\n }\n if (current !== undefined) {\n result.set(date, current);\n }\n }\n\n return result;\n}\n","import { TickerHandle } from './ticker';\nimport type { Trade } from '../backtest/types';\nimport { AllocationHandle } from './allocation';\nimport { isRateTickerSymbol } from '../providers/mappings';\n\nexport class PortfolioHandle {\n readonly holdings: [TickerHandle, number][];\n\n constructor(holdings: [TickerHandle, number][]) {\n // Check for duplicates\n const seen = new Set<string>();\n for (const [ticker] of holdings) {\n const key = `${ticker.symbol}:${ticker.leverage}`;\n if (seen.has(key)) {\n throw new Error(`Duplicate ticker: ${ticker.symbol}`);\n }\n seen.add(key);\n }\n\n this.holdings = holdings;\n }\n\n private _priceMap(prices: [TickerHandle, number][]): Map<string, number> {\n const map = new Map<string, number>();\n for (const [ticker, price] of prices) {\n map.set(`${ticker.symbol}:${ticker.leverage}`, price);\n }\n return map;\n }\n\n private _priceFor(ticker: TickerHandle, priceMap: Map<string, number>): number {\n if (ticker.symbol === 'CASHX') return 1;\n if (isRateTickerSymbol(ticker.symbol)) return 1;\n const key = `${ticker.symbol}:${ticker.leverage}`;\n const price = priceMap.get(key);\n if (price == null) {\n throw new Error(`Missing price for ${ticker.symbol}`);\n }\n return price;\n }\n\n value(prices: [TickerHandle, number][]): number {\n const priceMap = this._priceMap(prices);\n let total = 0;\n for (const [ticker, quantity] of this.holdings) {\n total += quantity * this._priceFor(ticker, priceMap);\n }\n return total;\n }\n\n weights(prices: [TickerHandle, number][]): [TickerHandle, number][] {\n const total = this.value(prices);\n if (total === 0) return [];\n\n const priceMap = this._priceMap(prices);\n const result: [TickerHandle, number][] = [];\n for (const [ticker, quantity] of this.holdings) {\n const dollarValue = quantity * this._priceFor(ticker, priceMap);\n if (dollarValue === 0) continue;\n result.push([ticker, dollarValue / total]);\n }\n return result;\n }\n\n trades(target: AllocationHandle, prices: [TickerHandle, number][], date: string): Trade[] {\n const priceMap = this._priceMap(prices);\n const totalValue = this.value(prices);\n\n // Build current dollar amounts by symbol\n const currentDollars = new Map<string, number>();\n for (const [ticker, quantity] of this.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const price = this._priceFor(ticker, priceMap);\n currentDollars.set(ticker.symbol, quantity * price);\n }\n\n // Build target dollar amounts by symbol\n const targetDollars = new Map<string, number>();\n for (const [ticker, weight] of target.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n targetDollars.set(ticker.symbol, totalValue * weight);\n }\n\n // Build a symbol → TickerHandle lookup for price resolution\n const tickerBySymbol = new Map<string, TickerHandle>();\n for (const [ticker] of this.holdings) {\n if (ticker.symbol !== 'CASHX') tickerBySymbol.set(ticker.symbol, ticker);\n }\n for (const [ticker] of target.holdings) {\n if (ticker.symbol === 'CASHX') continue;\n const existing = tickerBySymbol.get(ticker.symbol);\n if (existing && existing.leverage !== ticker.leverage) {\n throw new Error(`Conflicting leverage for ${ticker.symbol}`);\n }\n tickerBySymbol.set(ticker.symbol, ticker);\n }\n\n // Collect all non-CASHX symbols from both sides\n const allSymbols = new Set([...currentDollars.keys(), ...targetDollars.keys()]);\n\n const sells: Trade[] = [];\n const buys: Trade[] = [];\n\n for (const symbol of allSymbols) {\n const current = currentDollars.get(symbol) ?? 0;\n const target$ = targetDollars.get(symbol) ?? 0;\n const delta = target$ - current;\n\n const ticker = tickerBySymbol.get(symbol)!;\n const price = this._priceFor(ticker, priceMap);\n\n const quantity = Math.abs(delta) / price;\n if (quantity < 1e-10) continue;\n\n const trade: Trade = { date, symbol, quantity, price, action: delta > 0 ? 'buy' : 'sell' };\n\n if (trade.action === 'sell') {\n sells.push(trade);\n } else {\n buys.push(trade);\n }\n }\n\n return [...sells, ...buys];\n }\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { StrategyBar } from '../handles/strategy';\nimport type { TickerHandle } from '../handles/ticker';\nimport type { Trade } from './types';\nimport { PortfolioHandle } from '../handles/portfolio';\nimport { isRateTickerSymbol } from '../providers/mappings';\n\nconst EPSILON = 1e-8;\n\nfunction tkey(symbol: string, leverage: number): string {\n return `${symbol}:${leverage}`;\n}\n\nfunction symbolFromKey(key: string): string {\n const idx = key.lastIndexOf(':');\n return idx === -1 ? key : key.slice(0, idx);\n}\n\nfunction isRateKey(key: string): boolean {\n return isRateTickerSymbol(symbolFromKey(key));\n}\n\nfunction navPriceForKey(\n key: string,\n date: string,\n prices: Record<string, Record<string, number>>,\n lastPrice: Record<string, number>,\n): number | undefined {\n if (isRateKey(key)) return 1;\n const live = prices[key]?.[date];\n if (live != null) {\n lastPrice[key] = live;\n return live;\n }\n return lastPrice[key];\n}\n\nfunction daysBetween(prevIsoDate: string, currIsoDate: string): number {\n // Both inputs are 'YYYY-MM-DD'. UTC midnight → diff in ms → days.\n const ms =\n Date.UTC(Number(currIsoDate.slice(0, 4)), Number(currIsoDate.slice(5, 7)) - 1, Number(currIsoDate.slice(8, 10))) -\n Date.UTC(Number(prevIsoDate.slice(0, 4)), Number(prevIsoDate.slice(5, 7)) - 1, Number(prevIsoDate.slice(8, 10)));\n return Math.round(ms / (1000 * 60 * 60 * 24));\n}\n\nexport function runSimulation(\n bars: StrategyBar[],\n prices: Record<string, Record<string, number>>,\n rebalanceDates: Set<string>,\n portfolio: PortfolioHandle,\n): { series: DailyBar[]; trades: Trade[]; finalPortfolio: PortfolioHandle } {\n const positions: Record<string, number> = {};\n const lastPrice: Record<string, number> = {};\n let cash = 0;\n for (const [ticker, quantity] of portfolio.holdings) {\n if (ticker.symbol === 'CASHX') {\n cash = quantity;\n } else {\n positions[tkey(ticker.symbol, ticker.leverage)] = quantity;\n }\n }\n const series: DailyBar[] = [];\n const trades: Trade[] = [];\n\n // Carry forward the last known close when today's price is missing so\n // a held position isn't silently valued at $0 (e.g. mutual fund NAV that\n // posts after the trading-day cutoff).\n function valuationPrice(key: string, date: string): number | undefined {\n return navPriceForKey(key, date, prices, lastPrice);\n }\n\n let prevDate: string | null = null;\n\n for (const bar of bars) {\n const date = bar.date;\n\n // Accrue interest on rate-ticker positions between the previous bar and today.\n if (prevDate != null) {\n const days = daysBetween(prevDate, date);\n if (days > 0) {\n for (const [key, shares] of Object.entries(positions)) {\n if (!isRateKey(key)) continue;\n const ratePct = prices[key]?.[prevDate];\n if (ratePct == null) continue;\n const leverage = Number(key.slice(key.lastIndexOf(':') + 1)) || 1;\n const factor = 1 + leverage * (ratePct / 100) * (days / 360);\n positions[key] = shares * factor;\n }\n }\n }\n\n if (rebalanceDates.has(date)) {\n // Compute current portfolio value before rebalancing\n let portfolioValue = cash;\n for (const [key, shares] of Object.entries(positions)) {\n const price = valuationPrice(key, date);\n if (price != null) portfolioValue += shares * price;\n }\n\n // Determine target holdings\n const targetWeights: Record<string, number> = {};\n for (const [ticker, weight] of bar.allocation.holdings) {\n targetWeights[tkey(ticker.symbol, ticker.leverage)] = weight;\n }\n\n // Compute target shares and execute trades\n const allKeys = new Set([...Object.keys(positions), ...Object.keys(targetWeights)]);\n for (const key of allKeys) {\n let price: number;\n if (isRateKey(key)) {\n price = 1;\n } else {\n const live = prices[key]?.[date];\n if (live == null || live <= 0) continue;\n price = live;\n }\n\n const currentShares = positions[key] ?? 0;\n const targetValue = portfolioValue * (targetWeights[key] ?? 0);\n const targetShares = targetValue / price;\n const delta = targetShares - currentShares;\n\n if (Math.abs(delta) <= EPSILON) continue;\n\n if (Math.abs(targetShares) <= EPSILON) {\n delete positions[key];\n } else {\n positions[key] = targetShares;\n }\n cash -= delta * price;\n\n trades.push({\n date,\n symbol: key.split(':')[0]!,\n quantity: Math.abs(delta),\n price,\n action: delta > 0 ? 'buy' : 'sell',\n });\n }\n\n if (Math.abs(cash) <= EPSILON) cash = 0;\n }\n\n // Compute end-of-day portfolio value\n let value = cash;\n for (const [key, shares] of Object.entries(positions)) {\n const price = valuationPrice(key, date);\n if (price != null) value += shares * price;\n }\n series.push({ date, value });\n prevDate = date;\n }\n\n // Build finalPortfolio from ending positions + cash\n const finalHoldings: [TickerHandle, number][] = [];\n\n // Map ticker keys back to TickerHandles from allocations and starting portfolio\n const tickerByKey = new Map<string, TickerHandle>();\n for (const bar of bars) {\n for (const [ticker] of bar.allocation.holdings) {\n const key = tkey(ticker.symbol, ticker.leverage);\n if (!tickerByKey.has(key)) {\n tickerByKey.set(key, ticker);\n }\n }\n }\n for (const [ticker] of portfolio.holdings) {\n const key = tkey(ticker.symbol, ticker.leverage);\n if (!tickerByKey.has(key)) {\n tickerByKey.set(key, ticker);\n }\n }\n\n for (const [key, shares] of Object.entries(positions)) {\n const ticker = tickerByKey.get(key);\n if (ticker && Math.abs(shares) > EPSILON) {\n finalHoldings.push([ticker, shares]);\n }\n }\n\n // Add CASHX\n const cashKey = tkey('CASHX', 1);\n const cashTicker = tickerByKey.get(cashKey) ?? portfolio.holdings.find(([t]) => t.symbol === 'CASHX')?.[0];\n if (cashTicker && Math.abs(cash) > EPSILON) {\n finalHoldings.push([cashTicker, cash]);\n }\n\n const finalPortfolio = new PortfolioHandle(finalHoldings);\n\n return { series, trades, finalPortfolio };\n}\n","import type { DailyBar } from '../handles/indicator';\nimport type { AllocationHandle } from '../handles/allocation';\nimport { PortfolioHandle } from '../handles/portfolio';\nimport type { TickerHandle } from '../handles/ticker';\n\nexport interface SimulateOptions {\n from: string;\n to: string;\n portfolio: PortfolioHandle;\n}\n\nexport interface Trade {\n date: string;\n symbol: string;\n quantity: number;\n price: number;\n action: 'buy' | 'sell';\n}\n\nexport interface PortfolioSnapshot {\n value: number;\n holdings: [TickerHandle, number][];\n weights: [TickerHandle, number][];\n pendingTrades: Trade[];\n}\n\nexport interface FinalState {\n portfolio: PortfolioHandle;\n allocation: AllocationHandle;\n closePrices: Record<string, number>;\n leveragedPrices: Record<string, number>;\n}\n\nexport class SimulationHandle {\n readonly series: DailyBar[];\n readonly trades: Trade[];\n readonly startingPortfolio: PortfolioHandle;\n\n private _portfolio: PortfolioHandle | null;\n private _currentAllocation: AllocationHandle | null;\n private _lastClosePrices: Record<string, number>;\n private _lastLeveragedPrices: Map<string, number>;\n private _currentLeveragedPrices: Map<string, number>;\n private _lastDate: string;\n\n constructor(series: DailyBar[], trades: Trade[], startingPortfolio: PortfolioHandle, finalState?: FinalState) {\n this.series = series;\n this.trades = trades;\n this.startingPortfolio = startingPortfolio;\n\n if (finalState) {\n this._portfolio = finalState.portfolio;\n this._currentAllocation = finalState.allocation;\n this._lastClosePrices = finalState.closePrices;\n this._lastLeveragedPrices = new Map(Object.entries(finalState.leveragedPrices));\n this._currentLeveragedPrices = new Map(Object.entries(finalState.leveragedPrices));\n this._lastDate = series.at(-1)?.date ?? '';\n } else {\n this._portfolio = null;\n this._currentAllocation = null;\n this._lastClosePrices = {};\n this._lastLeveragedPrices = new Map();\n this._currentLeveragedPrices = new Map();\n this._lastDate = '';\n }\n }\n\n push(...prices: [TickerHandle, number][]): PortfolioSnapshot {\n if (!this._portfolio || !this._currentAllocation) {\n return { value: 0, holdings: [], weights: [], pendingTrades: [] };\n }\n\n // Update leveraged prices from raw market prices\n for (const [ticker, realPrice] of prices) {\n if (ticker.symbol === 'CASHX') continue;\n const lastClose = this._lastClosePrices[ticker.symbol];\n if (lastClose == null) continue;\n\n const realReturn = (realPrice - lastClose) / lastClose;\n\n // Apply leverage to all portfolio tickers sharing this symbol\n for (const [held] of this._portfolio.holdings) {\n if (held.symbol !== ticker.symbol) continue;\n if (held.symbol === 'CASHX') continue;\n const key = `${held.symbol}:${held.leverage}`;\n const baseLeveragedPrice = this._lastLeveragedPrices.get(key);\n if (baseLeveragedPrice == null) continue;\n const leveragedReturn = held.leverage * realReturn;\n this._currentLeveragedPrices.set(key, baseLeveragedPrice * (1 + leveragedReturn));\n }\n }\n\n // Build price array for PortfolioHandle methods\n const priceArray: [TickerHandle, number][] = [];\n for (const [held] of this._portfolio.holdings) {\n if (held.symbol === 'CASHX') continue;\n const key = `${held.symbol}:${held.leverage}`;\n const price = this._currentLeveragedPrices.get(key);\n if (price != null) priceArray.push([held, price]);\n }\n\n return {\n value: this._portfolio.value(priceArray),\n holdings: this._portfolio.holdings,\n weights: this._portfolio.weights(priceArray),\n pendingTrades: this._portfolio.trades(this._currentAllocation, priceArray, this._lastDate),\n };\n }\n}\n","import type { StorageProvider } from './providers/storage';\nimport type { MarketProvider } from './providers/market';\nimport type { IndicatorType, Unit } from './providers/types';\nimport { TickerHandle } from './handles/ticker';\nimport { IndicatorHandle } from './handles/indicator';\nimport { SignalHandle } from './handles/signal';\nimport { AllocationHandle } from './handles/allocation';\nimport { StrategyHandle } from './handles/strategy';\nimport { PortfolioHandle } from './handles/portfolio';\nimport type { StrategyOptions } from './handles/strategy';\n\ntype TreasuryTenor = Extract<\n IndicatorType,\n 'T3M' | 'T6M' | 'T1Y' | 'T2Y' | 'T3Y' | 'T5Y' | 'T7Y' | 'T10Y' | 'T20Y' | 'T30Y'\n>;\ntype CalendarPeriod = Extract<IndicatorType, 'Month' | 'Day of Week' | 'Day of Month' | 'Day of Year'>;\n\ninterface IndicatorOpts {\n delay?: number;\n}\n\nexport interface LivefolioClient {\n ticker(symbol: string, leverage?: number): TickerHandle;\n\n // Ticker-bound\n sma(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n ema(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n price(ticker: TickerHandle, opts?: IndicatorOpts): IndicatorHandle;\n returns(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n volatility(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n drawdown(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n rsi(ticker: TickerHandle, lookback: number, opts?: IndicatorOpts): IndicatorHandle;\n\n // Standalone\n vix(opts?: IndicatorOpts): IndicatorHandle;\n vix3m(opts?: IndicatorOpts): IndicatorHandle;\n treasury(tenor: TreasuryTenor, opts?: IndicatorOpts): IndicatorHandle;\n calendar(period: CalendarPeriod, opts?: IndicatorOpts): IndicatorHandle;\n\n // Threshold\n threshold(value: number, unit?: Unit): IndicatorHandle;\n\n // Signals\n gt(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n lt(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n eq(ind1: IndicatorHandle, ind2: IndicatorHandle, tolerance?: number): SignalHandle;\n\n // Allocations\n allocation(...holdings: [TickerHandle, number][]): AllocationHandle;\n\n // Portfolios\n portfolio(...holdings: [TickerHandle, number][]): PortfolioHandle;\n\n // Strategies\n strategy(linkId: string): StrategyHandle;\n strategy(options: StrategyOptions): StrategyHandle;\n strategy(optionsOrLinkId: string | StrategyOptions): StrategyHandle;\n}\n\nexport interface LivefolioClientOptions {\n storage: StorageProvider;\n market: MarketProvider;\n}\n\nfunction tickerBound(\n storage: StorageProvider,\n market: MarketProvider,\n type: IndicatorType,\n ticker: TickerHandle,\n lookback: number,\n opts?: IndicatorOpts,\n): IndicatorHandle {\n return new IndicatorHandle(storage, market, {\n type,\n ticker,\n lookback,\n delay: opts?.delay ?? 0,\n unit: null,\n threshold: null,\n });\n}\n\nfunction standalone(\n storage: StorageProvider,\n market: MarketProvider,\n type: IndicatorType,\n opts?: IndicatorOpts,\n): IndicatorHandle {\n return new IndicatorHandle(storage, market, {\n type,\n ticker: null,\n lookback: 0,\n delay: opts?.delay ?? 0,\n unit: null,\n threshold: null,\n });\n}\n\nexport function createClient(options: LivefolioClientOptions): LivefolioClient {\n const { storage, market } = options;\n\n return {\n ticker: (symbol, leverage) => new TickerHandle(storage, symbol, leverage),\n\n sma: (ticker, lookback, opts?) => tickerBound(storage, market, 'SMA', ticker, lookback, opts),\n ema: (ticker, lookback, opts?) => tickerBound(storage, market, 'EMA', ticker, lookback, opts),\n price: (ticker, opts?) => tickerBound(storage, market, 'Price', ticker, 0, opts),\n returns: (ticker, lookback, opts?) => tickerBound(storage, market, 'Return', ticker, lookback, opts),\n volatility: (ticker, lookback, opts?) => tickerBound(storage, market, 'Volatility', ticker, lookback, opts),\n drawdown: (ticker, lookback, opts?) => tickerBound(storage, market, 'Drawdown', ticker, lookback, opts),\n rsi: (ticker, lookback, opts?) => tickerBound(storage, market, 'RSI', ticker, lookback, opts),\n\n vix: (opts?) => standalone(storage, market, 'VIX', opts),\n vix3m: (opts?) => standalone(storage, market, 'VIX3M', opts),\n treasury: (tenor, opts?) => standalone(storage, market, tenor, opts),\n calendar: (period, opts?) => standalone(storage, market, period, opts),\n\n threshold: (value, unit?) =>\n new IndicatorHandle(storage, market, {\n type: 'Threshold',\n ticker: null,\n lookback: 0,\n delay: 0,\n unit: unit ?? null,\n threshold: value,\n }),\n\n gt: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '>',\n tolerance: tolerance ?? 0,\n }),\n lt: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '<',\n tolerance: tolerance ?? 0,\n }),\n eq: (ind1, ind2, tolerance?) =>\n new SignalHandle(storage, market, {\n indicator1: ind1,\n indicator2: ind2,\n comparison: '=',\n tolerance: tolerance ?? 0,\n }),\n\n allocation: (...holdings) => new AllocationHandle(storage, holdings),\n\n portfolio: (...holdings) => new PortfolioHandle(holdings),\n\n strategy: (optionsOrLinkId: StrategyOptions | string) => new StrategyHandle(storage, market, optionsOrLinkId),\n };\n}\n"],"mappings":"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","names":["from","rawBars"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livefolio/sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",