@adaptic/utils 0.0.1031 → 0.0.1032

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.
Files changed (29) hide show
  1. package/dist/index.cjs +306 -133
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.mjs +303 -134
  4. package/dist/index.mjs.map +1 -1
  5. package/dist/types/__tests__/indicator-parity/generate.d.ts +64 -0
  6. package/dist/types/__tests__/indicator-parity/generate.d.ts.map +1 -0
  7. package/dist/types/__tests__/indicator-parity/record.d.ts +144 -0
  8. package/dist/types/__tests__/indicator-parity/record.d.ts.map +1 -0
  9. package/dist/types/__tests__/indicator-parity/reference.d.ts +92 -0
  10. package/dist/types/__tests__/indicator-parity/reference.d.ts.map +1 -0
  11. package/dist/types/__tests__/indicator-parity/series.d.ts +64 -0
  12. package/dist/types/__tests__/indicator-parity/series.d.ts.map +1 -0
  13. package/dist/types/__tests__/indicator-parity/subjects.d.ts +55 -0
  14. package/dist/types/__tests__/indicator-parity/subjects.d.ts.map +1 -0
  15. package/dist/types/__tests__/support/statistic.d.ts +18 -0
  16. package/dist/types/__tests__/support/statistic.d.ts.map +1 -0
  17. package/dist/types/index.d.ts +1 -0
  18. package/dist/types/index.d.ts.map +1 -1
  19. package/dist/types/metrics-calcs.d.ts +25 -0
  20. package/dist/types/metrics-calcs.d.ts.map +1 -1
  21. package/dist/types/performance-metrics.d.ts +16 -4
  22. package/dist/types/performance-metrics.d.ts.map +1 -1
  23. package/dist/types/sample-statistic.d.ts +123 -0
  24. package/dist/types/sample-statistic.d.ts.map +1 -0
  25. package/dist/types/strategy-metrics.d.ts +38 -16
  26. package/dist/types/strategy-metrics.d.ts.map +1 -1
  27. package/dist/types/types/alpaca-types.d.ts +26 -2
  28. package/dist/types/types/alpaca-types.d.ts.map +1 -1
  29. package/package.json +3 -1
package/dist/index.mjs CHANGED
@@ -20221,6 +20221,93 @@ function getEquityValues(equityData, portfolioHistory, marketTimeUtil, period) {
20221
20221
  };
20222
20222
  }
20223
20223
 
20224
+ /**
20225
+ * A measured statistic and the cohort it was measured on, carried as one
20226
+ * inseparable value.
20227
+ *
20228
+ * A ratio is meaningless without the population it was taken over: the same
20229
+ * `0.42` is a strong result on 2,000 trades and noise on five, and a `0.0`
20230
+ * returned because nothing could be computed is indistinguishable from a `0.0`
20231
+ * that was genuinely measured. Both confusions are the same error — a number
20232
+ * read apart from its unit and its cohort — and both have produced wrong
20233
+ * conclusions from correct arithmetic.
20234
+ *
20235
+ * This type removes the option. Every statistic shaped by a population carries
20236
+ * `sampleCount` (how many observations actually entered the computation) and
20237
+ * `coverage` (what fraction of the observations the caller offered were usable),
20238
+ * on BOTH branches: an unavailable statistic still reports how much data it
20239
+ * saw, because "we had nothing" and "we had 900 rows and still could not
20240
+ * compute it" are different facts with different responses.
20241
+ *
20242
+ * Absence is a branch of the union rather than a sentinel value. There is no
20243
+ * number a caller can read without first proving the statistic exists, which is
20244
+ * what keeps an unknown from silently becoming a zero on its way to a decision.
20245
+ *
20246
+ * @module sample-statistic
20247
+ */
20248
+ /**
20249
+ * Build the cohort descriptor for a computation.
20250
+ *
20251
+ * `coverage` is derived here rather than supplied, so it cannot drift from the
20252
+ * counts it claims to summarise. A zero request yields zero coverage: no
20253
+ * observations were asked for, so none were covered, and the alternative (`1`)
20254
+ * would report a vacuous computation as fully covered.
20255
+ *
20256
+ * @param requestedCount - Observations offered, or the window width requested.
20257
+ * @param sampleCount - Observations that entered the computation.
20258
+ * @returns The cohort descriptor with `coverage` derived from the two counts.
20259
+ * @throws When either count is negative or non-finite, which is a programming
20260
+ * error rather than a data condition.
20261
+ */
20262
+ function sampleCohort(requestedCount, sampleCount) {
20263
+ if (!Number.isFinite(requestedCount) || requestedCount < 0) {
20264
+ throw new Error(`sampleCohort: requestedCount must be a non-negative finite number (got ${requestedCount})`);
20265
+ }
20266
+ if (!Number.isFinite(sampleCount) || sampleCount < 0) {
20267
+ throw new Error(`sampleCohort: sampleCount must be a non-negative finite number (got ${sampleCount})`);
20268
+ }
20269
+ const NOTHING_REQUESTED_COVERAGE = 0;
20270
+ const FULL_COVERAGE = 1;
20271
+ const coverage = requestedCount === 0
20272
+ ? NOTHING_REQUESTED_COVERAGE
20273
+ : Math.min(FULL_COVERAGE, sampleCount / requestedCount);
20274
+ return { sampleCount, requestedCount, coverage };
20275
+ }
20276
+ /**
20277
+ * Wrap a computed value with its cohort.
20278
+ *
20279
+ * @param value - The measured statistic.
20280
+ * @param cohort - The cohort it was measured on.
20281
+ * @returns The available branch of {@link SampleStatistic}.
20282
+ */
20283
+ function availableStatistic(value, cohort) {
20284
+ return { available: true, value, ...cohort };
20285
+ }
20286
+ /**
20287
+ * Record that a statistic could not be computed, and what was seen instead.
20288
+ *
20289
+ * @param reason - Which class of failure prevented the computation.
20290
+ * @param detail - Specifics for logs; never machine-parsed.
20291
+ * @param cohort - What data was available when the attempt was abandoned.
20292
+ * @returns The unavailable branch of {@link SampleStatistic}.
20293
+ */
20294
+ function unavailableStatistic(reason, detail, cohort) {
20295
+ return { available: false, reason, detail, ...cohort };
20296
+ }
20297
+ /**
20298
+ * Narrow a statistic to its available branch.
20299
+ *
20300
+ * Exists so consumers in other packages can discriminate without restating the
20301
+ * predicate, and so the discriminant stays a single named concept if the shape
20302
+ * ever grows a third branch.
20303
+ *
20304
+ * @param statistic - The statistic to test.
20305
+ * @returns Whether the statistic carries a value.
20306
+ */
20307
+ function isAvailable(statistic) {
20308
+ return statistic.available;
20309
+ }
20310
+
20224
20311
  // risk-free-rate.ts
20225
20312
  /**
20226
20313
  * Conservative fallback annual risk-free rate used when no live rate has been
@@ -20579,57 +20666,60 @@ function alignReturns(tradeBars, benchmarkBars) {
20579
20666
  });
20580
20667
  return { alignedTradeReturns, alignedBenchmarkReturns, alignedDates };
20581
20668
  }
20582
- /*
20583
- * Calculate Beta from Returns
20584
- * @param portfolioReturns - Array of portfolio returns
20585
- * @param benchmarkReturns - Array of benchmark returns
20586
- * @returns Object containing beta, covariance, variance, and average returns
20669
+ /**
20670
+ * Beta of a portfolio against a benchmark, from paired period returns.
20671
+ *
20672
+ * Non-finite rows are dropped pairwise — a return that is `NaN` on either leg
20673
+ * cannot contribute to a covariance — and the count that survives is reported
20674
+ * as the cohort rather than discarded. That reporting is the point: silently
20675
+ * computing a beta on the 12 rows that happened to be clean, and returning it
20676
+ * with the same shape as a beta over all 900, is how a statistic measured on
20677
+ * one population gets applied to another.
20678
+ *
20679
+ * When beta cannot be computed the result is the unavailable branch, never a
20680
+ * numeric stand-in. A beta of `0` asserts that the portfolio does not move with
20681
+ * the market, which is a strong and consequential claim; emitting it to mean
20682
+ * "we could not tell" makes every alpha derived from it wrong by the whole
20683
+ * benchmark term.
20684
+ *
20685
+ * @param portfolioReturns - Portfolio period returns.
20686
+ * @param benchmarkReturns - Benchmark period returns, index-aligned to the portfolio.
20687
+ * @returns The beta components with their cohort, or a typed unavailable result.
20587
20688
  * @example
20588
- * const portfolioReturns = [0.05, -0.02, 0.03];
20589
- * const benchmarkReturns = [0.03, -0.01, 0.02];
20590
- * const beta = calculateBetaFromReturns(portfolioReturns, benchmarkReturns);
20591
- * // beta = { beta: 1.5, covariance: 0.0005, variance: 0.0003, averagePortfolioReturn: 0.02, averageBenchmarkReturn: 0.02 }
20592
- * @throws Will log warnings if input data is invalid or insufficient
20593
- * @throws Will log warnings if benchmark variance is effectively zero
20594
- * @throws Will log warnings if beta calculation results in a non-finite value
20595
- * @throws Will log warnings if there are not enough valid data points for calculation
20596
- * @throws Will log warnings if benchmark variance is zero or non-finite
20689
+ * const result = calculateBetaFromReturns([0.05, -0.02, 0.03], [0.03, -0.01, 0.02]);
20690
+ * if (result.available) {
20691
+ * // result.value.beta, alongside result.sampleCount and result.coverage
20692
+ * }
20597
20693
  */
20598
20694
  function calculateBetaFromReturns$1(portfolioReturns, benchmarkReturns) {
20599
- // Input validation
20600
- if (!Array.isArray(portfolioReturns) ||
20601
- !Array.isArray(benchmarkReturns) ||
20602
- portfolioReturns.length !== benchmarkReturns.length ||
20603
- portfolioReturns.length < 2) {
20604
- getLogger().warn("Invalid or insufficient return data for beta calculation");
20605
- return {
20606
- beta: 0,
20607
- covariance: 0,
20608
- variance: 0,
20609
- averagePortfolioReturn: 0,
20610
- averageBenchmarkReturn: 0,
20611
- };
20612
- }
20613
- // Filter out any non-finite values before calculations
20614
- const validIndices = [...Array(portfolioReturns.length).keys()].filter((i) => isFinite(portfolioReturns[i]) && isFinite(benchmarkReturns[i]));
20615
- if (validIndices.length < 2) {
20616
- getLogger().warn("Not enough valid data points for beta calculation");
20617
- return {
20618
- beta: 0,
20619
- covariance: 0,
20620
- variance: 0,
20621
- averagePortfolioReturn: 0,
20622
- averageBenchmarkReturn: 0,
20623
- };
20695
+ // A covariance is defined over PAIRS, so the offered cohort is the number of
20696
+ // index positions both series can supply. Ragged input is a caller defect
20697
+ // rather than a data condition, and it is reported as such instead of being
20698
+ // silently truncated to the shorter series.
20699
+ if (!Array.isArray(portfolioReturns) || !Array.isArray(benchmarkReturns)) {
20700
+ return unavailableStatistic("invalid_input", "portfolioReturns and benchmarkReturns must both be arrays", sampleCohort(0, 0));
20701
+ }
20702
+ const requestedCount = portfolioReturns.length;
20703
+ if (portfolioReturns.length !== benchmarkReturns.length) {
20704
+ return unavailableStatistic("invalid_input", `series lengths differ: portfolio ${portfolioReturns.length}, benchmark ${benchmarkReturns.length}`, sampleCohort(requestedCount, 0));
20705
+ }
20706
+ // Pairwise finiteness filter. Both legs must be usable for the pair to
20707
+ // contribute; keeping a pair on the strength of one leg would mix a real
20708
+ // observation with a fabricated one.
20709
+ const validIndices = [...Array(requestedCount).keys()].filter((i) => isFinite(portfolioReturns[i]) && isFinite(benchmarkReturns[i]));
20710
+ const cohort = sampleCohort(requestedCount, validIndices.length);
20711
+ // Bessel-corrected estimators need at least one degree of freedom, so two
20712
+ // usable pairs is the floor below which no sample variance exists.
20713
+ const MIN_PAIRS_FOR_SAMPLE_VARIANCE = 2;
20714
+ if (validIndices.length < MIN_PAIRS_FOR_SAMPLE_VARIANCE) {
20715
+ getLogger().warn(`Beta unavailable: ${validIndices.length} usable pairs of ${requestedCount} offered.`);
20716
+ return unavailableStatistic(validIndices.length === 0 ? "no_usable_samples" : "insufficient_samples", `beta needs at least ${MIN_PAIRS_FOR_SAMPLE_VARIANCE} finite pairs; ${validIndices.length} of ${requestedCount} were usable`, cohort);
20624
20717
  }
20625
- // Use validated indices only
20626
20718
  const validPortfolioReturns = validIndices.map((i) => portfolioReturns[i]);
20627
20719
  const validBenchmarkReturns = validIndices.map((i) => benchmarkReturns[i]);
20628
- // Calculate means
20629
20720
  const n = validIndices.length;
20630
20721
  const averagePortfolioReturn = validPortfolioReturns.reduce((sum, ret) => sum + ret, 0) / n;
20631
20722
  const averageBenchmarkReturn = validBenchmarkReturns.reduce((sum, ret) => sum + ret, 0) / n;
20632
- // Calculate covariance and variance with Welford's online algorithm for numerical stability
20633
20723
  let covariance = 0;
20634
20724
  let variance = 0;
20635
20725
  for (let i = 0; i < n; i++) {
@@ -20638,30 +20728,26 @@ function calculateBetaFromReturns$1(portfolioReturns, benchmarkReturns) {
20638
20728
  covariance += portfolioDiff * benchmarkDiff;
20639
20729
  variance += benchmarkDiff * benchmarkDiff;
20640
20730
  }
20641
- // Finalize calculations using sample (Bessel-corrected) estimators —
20642
- // divide by (n - 1), not n. The guard above (validIndices.length < 2)
20643
- // already ensures n >= 2, so (n - 1) is always safe.
20731
+ // Sample (Bessel-corrected) estimators — divide by (n - 1), not n. The guard
20732
+ // above ensures n >= 2, so (n - 1) is always safe.
20644
20733
  covariance /= n - 1;
20645
20734
  variance /= n - 1;
20646
- // Handle zero variance case
20647
- if (Math.abs(variance) < 1e-10) {
20648
- getLogger().warn("Benchmark variance is effectively zero. Setting beta to 0.");
20649
- return {
20650
- beta: 0,
20651
- covariance,
20652
- variance,
20653
- averagePortfolioReturn,
20654
- averageBenchmarkReturn,
20655
- };
20656
- }
20657
- const beta = covariance / variance;
20658
- return {
20659
- beta,
20735
+ // A benchmark that never moved has no variance to regress against, so beta is
20736
+ // undefined rather than zero. VARIANCE_NOISE_FLOOR absorbs the case where a
20737
+ // constant series still produces a tiny positive variance because the computed
20738
+ // mean differs from the constant by a rounding unit.
20739
+ const VARIANCE_NOISE_FLOOR = 1e-10;
20740
+ if (Math.abs(variance) < VARIANCE_NOISE_FLOOR) {
20741
+ getLogger().warn("Beta unavailable: benchmark variance is effectively zero.");
20742
+ return unavailableStatistic("degenerate_population", `benchmark variance ${variance} is below the noise floor ${VARIANCE_NOISE_FLOOR}; beta is undefined`, cohort);
20743
+ }
20744
+ return availableStatistic({
20745
+ beta: covariance / variance,
20660
20746
  covariance,
20661
20747
  variance,
20662
20748
  averagePortfolioReturn,
20663
20749
  averageBenchmarkReturn,
20664
- };
20750
+ }, cohort);
20665
20751
  }
20666
20752
  /**
20667
20753
  * Calculates the total return for a position, respecting position direction
@@ -20745,7 +20831,18 @@ async function calculateAlphaAndBeta$1(tradeBars, benchmarkBars, isShort) {
20745
20831
  : rawTradeReturns;
20746
20832
  // Calculate beta with position-adjusted returns
20747
20833
  const beta = calculateBetaFromReturns$1(alignedTradeReturns, alignedBenchmarkReturns);
20748
- if (!isFinite(beta.beta)) {
20834
+ // Alpha is the return left over after the benchmark term, so an unknown beta
20835
+ // makes alpha unknown too. Substituting any number here — zero most of all —
20836
+ // would credit the whole benchmark move to the strategy.
20837
+ if (!beta.available) {
20838
+ getLogger().warn(`Alpha unavailable: beta could not be computed (${beta.reason}: ${beta.detail}).`);
20839
+ return {
20840
+ alpha: "N/A",
20841
+ alphaAnnualized: "N/A",
20842
+ beta: "N/A",
20843
+ };
20844
+ }
20845
+ if (!isFinite(beta.value.beta)) {
20749
20846
  getLogger().warn("Beta calculation resulted in a non-finite value.");
20750
20847
  return {
20751
20848
  alpha: "N/A",
@@ -20756,7 +20853,7 @@ async function calculateAlphaAndBeta$1(tradeBars, benchmarkBars, isShort) {
20756
20853
  // For short positions, the interpretation of beta changes
20757
20854
  // A positive beta on a short means the position moves with the market,
20758
20855
  // which is bad for a short. We invert it for consistency.
20759
- const positionAwareBeta = isShort ? -beta.beta : beta.beta;
20856
+ const positionAwareBeta = isShort ? -beta.value.beta : beta.value.beta;
20760
20857
  const avgTradeReturn = alignedTradeReturns.reduce((sum, ret) => sum + ret, 0) /
20761
20858
  alignedTradeReturns.length;
20762
20859
  const avgBenchmarkReturn = alignedBenchmarkReturns.reduce((sum, ret) => sum + ret, 0) /
@@ -21375,7 +21472,18 @@ async function calculateAlphaAndBeta(portfolioHistory, benchmarkBars) {
21375
21472
  const benchmarkAvgReturn = alignedBenchmarkReturns.reduce((sum, ret) => sum + ret, 0) / n;
21376
21473
  // **Calculate beta**
21377
21474
  const beta = calculateBetaFromReturns(alignedPortfolioReturns, alignedBenchmarkReturns);
21378
- if (!isFinite(beta.beta)) {
21475
+ // Alpha is what remains after subtracting the benchmark term, so an unknown
21476
+ // beta leaves alpha unknown. Any numeric stand-in — zero above all — would
21477
+ // attribute the entire benchmark move to the strategy.
21478
+ if (!beta.available) {
21479
+ getLogger().warn(`Alpha unavailable: beta could not be computed (${beta.reason}: ${beta.detail}).`);
21480
+ return {
21481
+ alpha: "N/A",
21482
+ alphaAnnualized: "N/A",
21483
+ beta: "N/A",
21484
+ };
21485
+ }
21486
+ if (!isFinite(beta.value.beta)) {
21379
21487
  getLogger().warn("Beta calculation resulted in a non-finite value.");
21380
21488
  return {
21381
21489
  alpha: "N/A",
@@ -21390,7 +21498,7 @@ async function calculateAlphaAndBeta(portfolioHistory, benchmarkBars) {
21390
21498
  const tradingDaysPerYear = 252;
21391
21499
  const riskFreeRateDaily = riskFreeRateAnnual / tradingDaysPerYear;
21392
21500
  const alpha = portfolioAvgReturn -
21393
- (riskFreeRateDaily + beta.beta * (benchmarkAvgReturn - riskFreeRateDaily));
21501
+ (riskFreeRateDaily + beta.value.beta * (benchmarkAvgReturn - riskFreeRateDaily));
21394
21502
  const alphaAnnualized = alpha * tradingDaysPerYear;
21395
21503
  if (!isFinite(alphaAnnualized)) {
21396
21504
  getLogger().warn("Alpha calculation resulted in a non-finite value.");
@@ -21403,7 +21511,7 @@ async function calculateAlphaAndBeta(portfolioHistory, benchmarkBars) {
21403
21511
  return {
21404
21512
  alpha: `${(alpha * 100).toFixed(2)}`,
21405
21513
  alphaAnnualized: `${(alphaAnnualized * 100).toFixed(2)}`,
21406
- beta: `${(beta.beta * 100).toFixed(2)}`,
21514
+ beta: `${(beta.value.beta * 100).toFixed(2)}`,
21407
21515
  };
21408
21516
  }
21409
21517
  // **Helper function to calculate daily returns with Unix millisecond timestamps**
@@ -21626,27 +21734,40 @@ function alignReturnsByDate(portfolioHistory, benchmarkBars) {
21626
21734
  return { alignedPortfolioReturns, alignedBenchmarkReturns };
21627
21735
  }
21628
21736
  /**
21629
- * Calculates the beta of the portfolio compared to a benchmark.
21630
- * @param portfolioReturns - Array of portfolio returns.
21631
- * @param benchmarkReturns - Array of benchmark returns.
21632
- * @returns An object containing beta and intermediate calculations.
21737
+ * Beta of a portfolio against a benchmark, from paired period returns.
21738
+ *
21739
+ * The two series are index-aligned pairs by contract: every mean, covariance
21740
+ * and variance below is taken over the SAME row set. A length mismatch is
21741
+ * therefore reported as invalid input rather than absorbed, because dividing
21742
+ * one series' sum by the other series' length produces a mean of a population
21743
+ * that does not exist — a number with no cohort, which is the failure this
21744
+ * return type exists to make impossible.
21745
+ *
21746
+ * An uncomputable beta is returned as the unavailable branch, never as `0`.
21747
+ * Zero beta is a claim of no market exposure, and downstream alpha attributes
21748
+ * the entire benchmark move to the strategy when it believes that claim.
21749
+ *
21750
+ * @param portfolioReturns - Portfolio period returns.
21751
+ * @param benchmarkReturns - Benchmark period returns, index-aligned to the portfolio.
21752
+ * @returns The beta components with their cohort, or a typed unavailable result.
21633
21753
  */
21634
21754
  function calculateBetaFromReturns(portfolioReturns, benchmarkReturns) {
21635
- const n = portfolioReturns.length;
21636
- if (n === 0) {
21637
- getLogger().warn("No returns to calculate beta.");
21638
- return {
21639
- beta: 0,
21640
- covariance: 0,
21641
- variance: 0,
21642
- averagePortfolioReturn: 0,
21643
- averageBenchmarkReturn: 0,
21644
- };
21645
- }
21646
- // Calculate average returns
21755
+ const requestedCount = portfolioReturns.length;
21756
+ if (portfolioReturns.length !== benchmarkReturns.length) {
21757
+ getLogger().warn(`Beta unavailable: series lengths differ (portfolio ${portfolioReturns.length}, benchmark ${benchmarkReturns.length}).`);
21758
+ return unavailableStatistic("invalid_input", `series lengths differ: portfolio ${portfolioReturns.length}, benchmark ${benchmarkReturns.length}`, sampleCohort(requestedCount, 0));
21759
+ }
21760
+ // Bessel-corrected estimators need one degree of freedom, so two paired
21761
+ // observations is the floor below which no sample variance exists.
21762
+ const MIN_PAIRS_FOR_SAMPLE_VARIANCE = 2;
21763
+ const n = requestedCount;
21764
+ if (n < MIN_PAIRS_FOR_SAMPLE_VARIANCE) {
21765
+ getLogger().warn(`Beta unavailable: ${n} paired returns offered.`);
21766
+ return unavailableStatistic(n === 0 ? "no_usable_samples" : "insufficient_samples", `beta needs at least ${MIN_PAIRS_FOR_SAMPLE_VARIANCE} paired returns; ${n} were offered`, sampleCohort(requestedCount, n));
21767
+ }
21768
+ const cohort = sampleCohort(requestedCount, n);
21647
21769
  const averagePortfolioReturn = portfolioReturns.reduce((sum, ret) => sum + ret, 0) / n;
21648
21770
  const averageBenchmarkReturn = benchmarkReturns.reduce((sum, ret) => sum + ret, 0) / n;
21649
- // Calculate covariance and variance
21650
21771
  let covariance = 0;
21651
21772
  let variance = 0;
21652
21773
  for (let i = 0; i < n; i++) {
@@ -21656,37 +21777,26 @@ function calculateBetaFromReturns(portfolioReturns, benchmarkReturns) {
21656
21777
  variance += benchmarkDiff ** 2;
21657
21778
  }
21658
21779
  // Use sample (Bessel-corrected) estimators — divide by (n - 1), not n.
21659
- // For n === 1 there is no degrees-of-freedom left; treat as zero variance
21660
- // so beta falls through to the zero-variance guard below.
21661
- const denom = n > 1 ? n - 1 : 1;
21662
- covariance /= denom;
21663
- variance /= denom;
21664
- // Handle zero (or numerically-degenerate) variance. A constant benchmark
21665
- // series can still produce a tiny nonzero variance because the computed
21666
- // mean differs from the constant by an ulp; dividing covariance by that
21667
- // rounding noise yields a meaningless beta. Treat any variance at or
21668
- // below the summation noise floor — (n * eps * |mean|)^2, the square of
21669
- // the worst-case naive-summation error — as zero. When the mean is
21670
- // exactly 0 this reduces to the exact zero check.
21780
+ covariance /= n - 1;
21781
+ variance /= n - 1;
21782
+ // A constant benchmark series can still produce a tiny nonzero variance
21783
+ // because the computed mean differs from the constant by an ulp; dividing
21784
+ // covariance by that rounding noise yields a meaningless beta. Treat any
21785
+ // variance at or below the summation noise floor — (n * eps * |mean|)^2, the
21786
+ // square of the worst-case naive-summation error — as no variance at all.
21787
+ // When the mean is exactly 0 this reduces to the exact zero check.
21671
21788
  const varianceNoiseFloor = (n * Number.EPSILON * Math.abs(averageBenchmarkReturn)) ** 2;
21672
21789
  if (variance <= varianceNoiseFloor) {
21673
- getLogger().warn("Benchmark variance is zero or below the floating-point noise floor. Setting beta to 0.");
21674
- return {
21675
- beta: 0,
21676
- covariance,
21677
- variance,
21678
- averagePortfolioReturn,
21679
- averageBenchmarkReturn,
21680
- };
21790
+ getLogger().warn("Beta unavailable: benchmark variance is zero or below the floating-point noise floor.");
21791
+ return unavailableStatistic("degenerate_population", `benchmark variance ${variance} is at or below the summation noise floor ${varianceNoiseFloor}; beta is undefined`, cohort);
21681
21792
  }
21682
- const beta = covariance / variance;
21683
- return {
21684
- beta,
21793
+ return availableStatistic({
21794
+ beta: covariance / variance,
21685
21795
  covariance,
21686
21796
  variance,
21687
21797
  averagePortfolioReturn,
21688
21798
  averageBenchmarkReturn,
21689
- };
21799
+ }, cohort);
21690
21800
  }
21691
21801
  /**
21692
21802
  * Calculates the information ratio of the portfolio compared to a benchmark.
@@ -22165,7 +22275,14 @@ var riskNs = /*#__PURE__*/Object.freeze({
22165
22275
  * Conventions:
22166
22276
  * - tradePnls / tradeReturns is an array of per-trade realised P&L or return
22167
22277
  * (positive = win, negative = loss, zero = breakeven).
22168
- * - All "rolling*" functions return null when fewer than `windowSize` trades exist.
22278
+ * - Every statistic here is a ratio or a mean over a WINDOW, so every one is
22279
+ * returned as a {@link SampleStatistic}: the value cannot be read without the
22280
+ * `sampleCount` it was taken over and the `coverage` of the window that was
22281
+ * asked for. A hit-rate is a different claim on 5 trades than on 500, and a
22282
+ * window that could only be half-filled is a different cohort from a full
22283
+ * one — a caller holding a bare number can tell neither apart.
22284
+ * - A window that cannot support the statistic returns the unavailable branch
22285
+ * with a reason, never a numeric stand-in. Zero is a measurement.
22169
22286
  * - All public functions reject non-finite inputs (NaN, Infinity) by throwing.
22170
22287
  * Callers must pre-validate or filter their inputs.
22171
22288
  */
@@ -22181,21 +22298,38 @@ function assertFiniteArray(name, arr) {
22181
22298
  }
22182
22299
  }
22183
22300
  }
22301
+ /**
22302
+ * Report a window that holds fewer trades than it asked for.
22303
+ *
22304
+ * Shared so every rolling function describes a short window the same way — the
22305
+ * cohort is `(requested = windowSize, sampled = what exists)`, which is the
22306
+ * pair a caller needs to distinguish a warm-up from a data gap.
22307
+ *
22308
+ * @param name - The calling function, for the detail string.
22309
+ * @param available - Trades actually present.
22310
+ * @param windowSize - Trades the window asked for.
22311
+ * @returns The unavailable branch describing the short window.
22312
+ */
22313
+ function insufficientWindow(name, available, windowSize) {
22314
+ return unavailableStatistic("insufficient_samples", `${name}: window of ${windowSize} requested, only ${available} trades available`, sampleCohort(windowSize, available));
22315
+ }
22184
22316
  /**
22185
22317
  * Rolling expectancy: mean P&L over the most-recent `windowSize` trades.
22186
22318
  *
22187
22319
  * @param tradePnls - Array of per-trade realised P&L values.
22188
22320
  * @param windowSize - Number of most-recent trades to include. Must be a positive integer.
22189
- * @returns Mean P&L of the last `windowSize` trades, or null when fewer than `windowSize` exist.
22321
+ * @returns Mean P&L of the last `windowSize` trades with its cohort, or a typed
22322
+ * unavailable result when fewer than `windowSize` trades exist.
22190
22323
  * @throws When `windowSize` is not a positive integer or any input is non-finite.
22191
22324
  */
22192
22325
  function calculateRollingExpectancy(tradePnls, windowSize) {
22193
22326
  assertWindowSize("calculateRollingExpectancy", windowSize);
22194
- if (tradePnls.length < windowSize)
22195
- return null;
22327
+ if (tradePnls.length < windowSize) {
22328
+ return insufficientWindow("calculateRollingExpectancy", tradePnls.length, windowSize);
22329
+ }
22196
22330
  assertFiniteArray("calculateRollingExpectancy", tradePnls);
22197
22331
  const slice = tradePnls.slice(-windowSize);
22198
- return slice.reduce((a, b) => a + b, 0) / windowSize;
22332
+ return availableStatistic(slice.reduce((a, b) => a + b, 0) / windowSize, sampleCohort(windowSize, windowSize));
22199
22333
  }
22200
22334
  /**
22201
22335
  * Rolling hit-rate: fraction of strictly-positive P&L trades in the most-recent
@@ -22203,42 +22337,53 @@ function calculateRollingExpectancy(tradePnls, windowSize) {
22203
22337
  *
22204
22338
  * @param tradePnls - Array of per-trade realised P&L values.
22205
22339
  * @param windowSize - Number of most-recent trades to include. Must be a positive integer.
22206
- * @returns Fraction of winning trades in the window, or null when fewer than `windowSize` exist.
22340
+ * @returns Fraction of winning trades in the window with its cohort, or a typed
22341
+ * unavailable result when fewer than `windowSize` trades exist.
22207
22342
  * @throws When `windowSize` is not a positive integer or any input is non-finite.
22208
22343
  */
22209
22344
  function calculateRollingHitRate(tradePnls, windowSize) {
22210
22345
  assertWindowSize("calculateRollingHitRate", windowSize);
22211
- if (tradePnls.length < windowSize)
22212
- return null;
22346
+ if (tradePnls.length < windowSize) {
22347
+ return insufficientWindow("calculateRollingHitRate", tradePnls.length, windowSize);
22348
+ }
22213
22349
  assertFiniteArray("calculateRollingHitRate", tradePnls);
22214
22350
  const slice = tradePnls.slice(-windowSize);
22215
22351
  const wins = slice.filter((p) => p > 0).length;
22216
- return wins / windowSize;
22352
+ return availableStatistic(wins / windowSize, sampleCohort(windowSize, windowSize));
22217
22353
  }
22218
22354
  /**
22219
22355
  * Rolling profit factor: sum(wins) / |sum(losses)| over the most-recent `windowSize` trades.
22220
22356
  *
22221
22357
  * Edge cases:
22222
- * - no losses and at least one win → +Infinity
22223
- * - no wins and no losses (all zeros) → 0
22224
- * - fewer than windowSize trades → null
22358
+ * - no losses and at least one win → +Infinity (an unbounded but real ratio)
22359
+ * - no wins and no losses (all zeros) → unavailable: `0 / 0` is undefined, and a
22360
+ * window of breakeven trades has no profit factor rather than a profit factor
22361
+ * of zero
22362
+ * - fewer than windowSize trades → unavailable
22225
22363
  *
22226
22364
  * @param tradePnls - Array of per-trade realised P&L values.
22227
22365
  * @param windowSize - Number of most-recent trades to include. Must be a positive integer.
22228
- * @returns Profit factor for the rolling window, or null when fewer than `windowSize` exist.
22366
+ * @returns Profit factor for the rolling window with its cohort, or a typed
22367
+ * unavailable result.
22229
22368
  * @throws When `windowSize` is not a positive integer or any input is non-finite.
22230
22369
  */
22231
22370
  function calculateRollingProfitFactor(tradePnls, windowSize) {
22232
22371
  assertWindowSize("calculateRollingProfitFactor", windowSize);
22233
- if (tradePnls.length < windowSize)
22234
- return null;
22372
+ if (tradePnls.length < windowSize) {
22373
+ return insufficientWindow("calculateRollingProfitFactor", tradePnls.length, windowSize);
22374
+ }
22235
22375
  assertFiniteArray("calculateRollingProfitFactor", tradePnls);
22376
+ const cohort = sampleCohort(windowSize, windowSize);
22236
22377
  const slice = tradePnls.slice(-windowSize);
22237
22378
  const wins = slice.filter((p) => p > 0).reduce((a, b) => a + b, 0);
22238
22379
  const losses = slice.filter((p) => p < 0).reduce((a, b) => a + Math.abs(b), 0);
22239
- if (losses === 0)
22240
- return wins > 0 ? Number.POSITIVE_INFINITY : 0;
22241
- return wins / losses;
22380
+ if (losses === 0) {
22381
+ if (wins > 0) {
22382
+ return availableStatistic(Number.POSITIVE_INFINITY, cohort);
22383
+ }
22384
+ return unavailableStatistic("degenerate_population", `calculateRollingProfitFactor: window of ${windowSize} contains neither wins nor losses; the ratio is undefined`, cohort);
22385
+ }
22386
+ return availableStatistic(wins / losses, cohort);
22242
22387
  }
22243
22388
  /**
22244
22389
  * Rolling Sortino: delegate to `calculateSortino` over the most-recent `windowSize` returns.
@@ -22246,34 +22391,58 @@ function calculateRollingProfitFactor(tradePnls, windowSize) {
22246
22391
  * @param tradeReturns - Array of per-trade return values.
22247
22392
  * @param windowSize - Number of most-recent trades to include. Must be a positive integer.
22248
22393
  * @param riskFreeRate - Risk-free rate to subtract from returns (default 0).
22249
- * @returns Sortino ratio for the rolling window, or null when fewer than `windowSize` exist.
22394
+ * @returns Sortino ratio for the rolling window with its cohort, or a typed
22395
+ * unavailable result.
22250
22396
  * @throws When `windowSize` is not a positive integer or any input is non-finite.
22251
22397
  */
22252
22398
  function calculateRollingSortino(tradeReturns, windowSize, riskFreeRate = 0) {
22253
22399
  assertWindowSize("calculateRollingSortino", windowSize);
22254
- if (tradeReturns.length < windowSize)
22255
- return null;
22400
+ if (tradeReturns.length < windowSize) {
22401
+ return insufficientWindow("calculateRollingSortino", tradeReturns.length, windowSize);
22402
+ }
22256
22403
  assertFiniteArray("calculateRollingSortino", tradeReturns);
22257
- return calculateSortino(tradeReturns.slice(-windowSize), riskFreeRate);
22404
+ const cohort = sampleCohort(windowSize, windowSize);
22405
+ const sortino = calculateSortino(tradeReturns.slice(-windowSize), riskFreeRate);
22406
+ if (sortino === null) {
22407
+ // `calculateSortino` returns null only for a window it cannot form a
22408
+ // dispersion over — fewer than two samples. That is a property of the
22409
+ // window, so it is reported as one rather than as a ratio of zero.
22410
+ return unavailableStatistic("insufficient_samples", `calculateRollingSortino: window of ${windowSize} cannot support a dispersion estimate`, cohort);
22411
+ }
22412
+ return availableStatistic(sortino, cohort);
22258
22413
  }
22259
22414
  /**
22260
22415
  * Z-score of live-expectancy vs backtest-expectancy, scaled by the backtest stddev.
22261
22416
  * Positive Z = live outperforming; negative Z = live underperforming.
22262
22417
  *
22263
- * @param liveExpectancy - Mean P&L per trade in the live window.
22418
+ * The live expectancy is taken as a {@link SampleStatistic} rather than a bare
22419
+ * number so the z-score inherits the cohort it was actually derived from. A
22420
+ * z-score is a statement about how surprising a sample mean is, and how
22421
+ * surprising it is depends entirely on how many trades produced it — quoting
22422
+ * the z alone is the exact substitution this type exists to block. An
22423
+ * unavailable live expectancy yields an unavailable z, because there is no
22424
+ * mean to compare.
22425
+ *
22426
+ * @param liveExpectancy - Mean P&L per trade in the live window, with its cohort.
22264
22427
  * @param backtestExpectancy - Mean P&L per trade from the calibration backtest.
22265
22428
  * @param backtestStddev - Stddev of per-trade P&L in the backtest. Must be > 0.
22266
- * @returns Z-score measuring divergence between live and backtest performance.
22267
- * @throws When any input is non-finite or `backtestStddev` is not positive.
22429
+ * @returns Z-score measuring live-vs-backtest divergence, carrying the live cohort.
22430
+ * @throws When the backtest inputs are non-finite or `backtestStddev` is not positive.
22268
22431
  */
22269
22432
  function calculateBacktestDivergenceZ(liveExpectancy, backtestExpectancy, backtestStddev) {
22270
- if (!Number.isFinite(liveExpectancy) || !Number.isFinite(backtestExpectancy) || !Number.isFinite(backtestStddev)) {
22433
+ if (!Number.isFinite(backtestExpectancy) || !Number.isFinite(backtestStddev)) {
22271
22434
  throw new Error("calculateBacktestDivergenceZ: inputs must be finite numbers");
22272
22435
  }
22273
22436
  if (backtestStddev <= 0) {
22274
22437
  throw new Error("calculateBacktestDivergenceZ: stddev must be > 0");
22275
22438
  }
22276
- return (liveExpectancy - backtestExpectancy) / backtestStddev;
22439
+ if (!liveExpectancy.available) {
22440
+ return unavailableStatistic(liveExpectancy.reason, `calculateBacktestDivergenceZ: live expectancy unavailable (${liveExpectancy.detail})`, sampleCohort(liveExpectancy.requestedCount, liveExpectancy.sampleCount));
22441
+ }
22442
+ if (!Number.isFinite(liveExpectancy.value)) {
22443
+ throw new Error("calculateBacktestDivergenceZ: inputs must be finite numbers");
22444
+ }
22445
+ return availableStatistic((liveExpectancy.value - backtestExpectancy) / backtestStddev, sampleCohort(liveExpectancy.requestedCount, liveExpectancy.sampleCount));
22277
22446
  }
22278
22447
 
22279
22448
  var strategyNs = /*#__PURE__*/Object.freeze({
@@ -80094,5 +80263,5 @@ const adaptic = {
80094
80263
  };
80095
80264
  const adptc = adaptic;
80096
80265
 
80097
- export { API_RETRY_CONFIGS, AVNewsArticleSchema, AVNewsResponseSchema, AdapticUtilsError, AlpacaAccountDetailsSchema, AlpacaApiError, AlpacaBarSchema, AlpacaClient, AlpacaCryptoBarsResponseSchema, AlpacaHistoricalBarsResponseSchema, AlpacaLatestBarsResponseSchema, AlpacaLatestQuotesResponseSchema, AlpacaLatestTradesResponseSchema, AlpacaMarketDataAPI, AlpacaNewsArticleSchema, AlpacaNewsResponseSchema, AlpacaOrderSchema, AlpacaOrdersArraySchema, AlpacaPortfolioHistoryResponseSchema, AlpacaPositionSchema, AlpacaPositionsArraySchema, AlpacaQuoteSchema, AlpacaTradeSchema, AlpacaTradingAPI, AlphaVantageError, AlphaVantageQuoteResponseSchema, AssetAllocationEngine, AuthenticationError, AutonomyMode, BTC_PAIRS, BarError, ChainExhaustedError, CircuitBreakerRegistry, CircuitOpenError, CryptoDataError, CryptoOrderError, DEFAULT_CACHE_OPTIONS, DEFAULT_RISK_FREE_RATE, DEFAULT_TIMEOUTS, DEFAULT_TRADING_POLICY, DataFormatError, DecisionMemoryOutcome, DecisionOutcome, DecisionRecordStatus, DirectTransportRefusedError, DuplicateClientOrderIdError, GatewayResponseError, GatewayUnreachableError, HttpClientError, HttpServerError, KEEP_ALIVE_DEFAULTS, LlmProvider, MARKET_DATA_API, MassiveAggregatesResponseSchema, MassiveApiError, MassiveDailyOpenCloseSchema, MassiveErrorResponseSchema, MassiveGroupedDailyResponseSchema, MassiveLastTradeResponseSchema, MassiveTickerDetailsResponseSchema, MassiveTickerInfoSchema, MassiveTradeSchema as MassiveTradeZodSchema, MassiveTradesResponseSchema, NetworkError, NewsError, NoServableRouteError, OptionStrategyError, OptionsDataError, OverlaySeverity, OverlayStatus, OverlayType, QuoteError, RISK_FREE_RATE_TTL_MS, RateGuardTimeoutError, RateLimitError, RawMassivePriceDataSchema, SchemaRetryExhaustedError, StampedeProtectedCache, StreamProviderError, StreamTruncatedError, TRADING_API, TimeoutError, TokenBucketRateLimiter, TradeError, TrailingStopValidationError, USDC_PAIRS, USDT_PAIRS, USD_PAIRS, UnknownAliasError, UnsupportedBrokerError, UnsupportedCapabilityError, ValidationError, ValidationResponseError, WEBSOCKET_STREAMS, WebSocketError, account, adaptic, adptc, alpaca, analyzeBars, approximateImpliedVolatility, atrNs as atr, bracketOrders, buildOCCSymbol, buildOptionSymbol, buildRetryPrompt, buyCryptoNotional, buyToClose, buyToOpen, buyWithStopLoss, buyWithTrailingStop, calculateMoneyness, calculateOrderValue, calculatePeriodPerformance, calculatePutCallRatio, calculateTotalFilledValue, callLLMByAlias, callWithValidation, cancelAllCryptoOrders, cancelOCOOrder, cancelOTOOrder, cancelTrailingStop, cancelTrailingStopsForSymbol, checkTradingEligibility, clearClientCache, clock, closeAllOptionPositions, closeOptionPosition, closedIncumbentLeg, collectStream, configureLlmClient, createAlpacaClient, createAlpacaMarketDataAPI, createAlpacaTradingAPI, createBracketOrder, createBrokerClient, createButterflySpread, createClientFromEnv, createCoveredCall, createCryptoLimitOrder, createCryptoMarketOrder, createCryptoOrder, createCryptoStopLimitOrder, createCryptoStopOrder, createDirectTransport, createExecutorFromTradingAPI, createGatewayTransport, createIronCondor$1 as createIronCondor, createIronCondor as createIronCondorAdvanced, createMultiLegOptionOrder, createOCOOrder, createOTOOrder, createOptionOrder, createPortfolioTrailingStops, createProtectiveBracket, createStampedeProtectedCache, createStraddle$1 as createStraddle, createStraddle as createStraddleAdvanced, createStrangle$1 as createStrangle, createStrangle as createStrangleAdvanced, createStreamManager, createTimeoutSignal, createTrailingStop, createVerticalSpread$1 as createVerticalSpread, createVerticalSpread as createVerticalSpreadAdvanced, enrichAlpacaError, entryWithPercentStopLoss, exerciseOption, extractAlpacaBrokerError, extractGreeks, filterByExpiration, filterByStrike, filterByType, filterOrdersByDateRange, findATMOptions, findATMStrikes, findNearestExpiration, findOptionsByDelta, formatOrderForLog, formatOrderSummary, gatewayModelNameFor, generateOptimalAllocation, getAccountConfiguration, getAccountDetails, getAccountSummary, getAgentPoolStatus, getAllOrders, getAlpacaBrokerErrorCode, getAlpacaBrokerErrorDetail, getAlpacaCalendar, getAlpacaClock, getAverageDailyVolume, getBars, getBuyingPower, getCachedRiskFreeRateSync, getCachedRiskFreeRateSyncWithProvenance, getCrypto24HourChange, getCryptoBars, getCryptoDailyPrices, getCryptoPairsByQuote, getCryptoPrice, getCryptoSnapshots, getCryptoSpread, getCryptoStreamUrl, getCryptoTrades, getCurrentPrice, getCurrentPrices, getDailyPrices, getDailyReturns, getDaysToExpiration, getDefaultRiskProfile, getEquityCurve, getExpirationDates, getFilledOrders, getGroupedOptionChain, getHistoricalOptionsBars, getHistoricalTrades, getIntradayPrices, getLatestBars, getLatestCryptoQuotes, getLatestCryptoTrades, getLatestNews, getLatestOptionsQuotes, getLatestOptionsTrades, getLatestQuote, getLatestQuotes, getLatestTrade, getLatestTrades, getLogger, getMarginInfo, getNews, getNewsForSymbols, getOCOOrderStatus, getOTOOrderStatus, getOpenCryptoOrders, getOpenOrders$1 as getOpenOrdersQuery, getOpenTrailingStops, getOptionChain, getOptionContract, getOptionContracts, getOptionSpread, getOptionsChain, getOptionsSnapshots, getOptionsStreamUrl, getOptionsTradingLevel, getOrderHistory, getOrdersBySymbol, getPDTStatus, getPopularCryptoPairs, getPortfolioHistory, getPreviousClose, getPriceRange, getRiskFreeRate, getRiskFreeRateWithProvenance, getSpread, getSpreads, getStockStreamUrl, getStrikePrices, getSupportedCryptoPairs, getSymbolSentiment, getTimeout, getTradeVolume, getTradingApiUrl, getTradingWebSocketUrl, getTrailingStopHWM, groupOrdersByStatus, groupOrdersBySymbol, guardSnapshots, hasActiveTrailingStop, hasGoodLiquidity as hasOptionLiquidity, hasGoodLiquidity$1 as hasStockLiquidity, hasSufficientVolume, httpAgent, httpsAgent, isAlpacaBrokerCredentials, isContractTradable, isCryptoPair, isExpiringWithin, isMarginAccount, isOptionOrderCancelable, isOptionOrderTerminal, isOrderFillable, isOrderFilled, isOrderOpen, isOrderTerminal$1 as isOrderTerminalStatus, isSupportedCryptoPair, isTransientNetworkError, index$1 as legacyApi, limitBuyWithTakeProfit, limitsFor, limitsInventory, listAliases, llmAliases, llmBreakers, normaliseAnthropicStream, normaliseOpenAiStream, normaliseParams, normaliseStream, ocoOrders, orderUtils, orderedRoutes, otoOrders, paginate, paginateAll, parseOCCSymbol, protectLongPosition, protectShortPosition, rateLimiters$1 as rateLimiters, resetLogger, resetProviderGuards, resetRiskFreeRateCache, resolveChain, resolveDefaultDirectCaller, riskNs as risk, rollOptionPosition, roundPriceForAlpaca$3 as roundPriceForAlpaca, roundPriceForAlpacaNumber, routeKeyFor, routeSupports, routeTable, safeValidateResponse, searchNews, sellAllCrypto, sellCryptoNotional, sellToClose, sellToOpen, setLogger, setRiskFreeRate, shortWithStopLoss, sortOrdersByDate, strategyNs as strategy, sumUsage, index as tradingPolicy, trailingStops, updateAccountConfiguration, updateTrailingStop, validateAlpacaCredentials, validateAlphaVantageApiKey, validateMassiveApiKey$1 as validateMassiveApiKey, validateMultiLegOrder, validateResponse, verifyFetchKeepAlive, volatilityNs as volatility, waitForOrderFill, withProviderGuards, withRetry, withTimeout };
80266
+ export { API_RETRY_CONFIGS, AVNewsArticleSchema, AVNewsResponseSchema, AdapticUtilsError, AlpacaAccountDetailsSchema, AlpacaApiError, AlpacaBarSchema, AlpacaClient, AlpacaCryptoBarsResponseSchema, AlpacaHistoricalBarsResponseSchema, AlpacaLatestBarsResponseSchema, AlpacaLatestQuotesResponseSchema, AlpacaLatestTradesResponseSchema, AlpacaMarketDataAPI, AlpacaNewsArticleSchema, AlpacaNewsResponseSchema, AlpacaOrderSchema, AlpacaOrdersArraySchema, AlpacaPortfolioHistoryResponseSchema, AlpacaPositionSchema, AlpacaPositionsArraySchema, AlpacaQuoteSchema, AlpacaTradeSchema, AlpacaTradingAPI, AlphaVantageError, AlphaVantageQuoteResponseSchema, AssetAllocationEngine, AuthenticationError, AutonomyMode, BTC_PAIRS, BarError, ChainExhaustedError, CircuitBreakerRegistry, CircuitOpenError, CryptoDataError, CryptoOrderError, DEFAULT_CACHE_OPTIONS, DEFAULT_RISK_FREE_RATE, DEFAULT_TIMEOUTS, DEFAULT_TRADING_POLICY, DataFormatError, DecisionMemoryOutcome, DecisionOutcome, DecisionRecordStatus, DirectTransportRefusedError, DuplicateClientOrderIdError, GatewayResponseError, GatewayUnreachableError, HttpClientError, HttpServerError, KEEP_ALIVE_DEFAULTS, LlmProvider, MARKET_DATA_API, MassiveAggregatesResponseSchema, MassiveApiError, MassiveDailyOpenCloseSchema, MassiveErrorResponseSchema, MassiveGroupedDailyResponseSchema, MassiveLastTradeResponseSchema, MassiveTickerDetailsResponseSchema, MassiveTickerInfoSchema, MassiveTradeSchema as MassiveTradeZodSchema, MassiveTradesResponseSchema, NetworkError, NewsError, NoServableRouteError, OptionStrategyError, OptionsDataError, OverlaySeverity, OverlayStatus, OverlayType, QuoteError, RISK_FREE_RATE_TTL_MS, RateGuardTimeoutError, RateLimitError, RawMassivePriceDataSchema, SchemaRetryExhaustedError, StampedeProtectedCache, StreamProviderError, StreamTruncatedError, TRADING_API, TimeoutError, TokenBucketRateLimiter, TradeError, TrailingStopValidationError, USDC_PAIRS, USDT_PAIRS, USD_PAIRS, UnknownAliasError, UnsupportedBrokerError, UnsupportedCapabilityError, ValidationError, ValidationResponseError, WEBSOCKET_STREAMS, WebSocketError, account, adaptic, adptc, alpaca, analyzeBars, approximateImpliedVolatility, atrNs as atr, availableStatistic, bracketOrders, buildOCCSymbol, buildOptionSymbol, buildRetryPrompt, buyCryptoNotional, buyToClose, buyToOpen, buyWithStopLoss, buyWithTrailingStop, calculateMoneyness, calculateOrderValue, calculatePeriodPerformance, calculatePutCallRatio, calculateTotalFilledValue, callLLMByAlias, callWithValidation, cancelAllCryptoOrders, cancelOCOOrder, cancelOTOOrder, cancelTrailingStop, cancelTrailingStopsForSymbol, checkTradingEligibility, clearClientCache, clock, closeAllOptionPositions, closeOptionPosition, closedIncumbentLeg, collectStream, configureLlmClient, createAlpacaClient, createAlpacaMarketDataAPI, createAlpacaTradingAPI, createBracketOrder, createBrokerClient, createButterflySpread, createClientFromEnv, createCoveredCall, createCryptoLimitOrder, createCryptoMarketOrder, createCryptoOrder, createCryptoStopLimitOrder, createCryptoStopOrder, createDirectTransport, createExecutorFromTradingAPI, createGatewayTransport, createIronCondor$1 as createIronCondor, createIronCondor as createIronCondorAdvanced, createMultiLegOptionOrder, createOCOOrder, createOTOOrder, createOptionOrder, createPortfolioTrailingStops, createProtectiveBracket, createStampedeProtectedCache, createStraddle$1 as createStraddle, createStraddle as createStraddleAdvanced, createStrangle$1 as createStrangle, createStrangle as createStrangleAdvanced, createStreamManager, createTimeoutSignal, createTrailingStop, createVerticalSpread$1 as createVerticalSpread, createVerticalSpread as createVerticalSpreadAdvanced, enrichAlpacaError, entryWithPercentStopLoss, exerciseOption, extractAlpacaBrokerError, extractGreeks, filterByExpiration, filterByStrike, filterByType, filterOrdersByDateRange, findATMOptions, findATMStrikes, findNearestExpiration, findOptionsByDelta, formatOrderForLog, formatOrderSummary, gatewayModelNameFor, generateOptimalAllocation, getAccountConfiguration, getAccountDetails, getAccountSummary, getAgentPoolStatus, getAllOrders, getAlpacaBrokerErrorCode, getAlpacaBrokerErrorDetail, getAlpacaCalendar, getAlpacaClock, getAverageDailyVolume, getBars, getBuyingPower, getCachedRiskFreeRateSync, getCachedRiskFreeRateSyncWithProvenance, getCrypto24HourChange, getCryptoBars, getCryptoDailyPrices, getCryptoPairsByQuote, getCryptoPrice, getCryptoSnapshots, getCryptoSpread, getCryptoStreamUrl, getCryptoTrades, getCurrentPrice, getCurrentPrices, getDailyPrices, getDailyReturns, getDaysToExpiration, getDefaultRiskProfile, getEquityCurve, getExpirationDates, getFilledOrders, getGroupedOptionChain, getHistoricalOptionsBars, getHistoricalTrades, getIntradayPrices, getLatestBars, getLatestCryptoQuotes, getLatestCryptoTrades, getLatestNews, getLatestOptionsQuotes, getLatestOptionsTrades, getLatestQuote, getLatestQuotes, getLatestTrade, getLatestTrades, getLogger, getMarginInfo, getNews, getNewsForSymbols, getOCOOrderStatus, getOTOOrderStatus, getOpenCryptoOrders, getOpenOrders$1 as getOpenOrdersQuery, getOpenTrailingStops, getOptionChain, getOptionContract, getOptionContracts, getOptionSpread, getOptionsChain, getOptionsSnapshots, getOptionsStreamUrl, getOptionsTradingLevel, getOrderHistory, getOrdersBySymbol, getPDTStatus, getPopularCryptoPairs, getPortfolioHistory, getPreviousClose, getPriceRange, getRiskFreeRate, getRiskFreeRateWithProvenance, getSpread, getSpreads, getStockStreamUrl, getStrikePrices, getSupportedCryptoPairs, getSymbolSentiment, getTimeout, getTradeVolume, getTradingApiUrl, getTradingWebSocketUrl, getTrailingStopHWM, groupOrdersByStatus, groupOrdersBySymbol, guardSnapshots, hasActiveTrailingStop, hasGoodLiquidity as hasOptionLiquidity, hasGoodLiquidity$1 as hasStockLiquidity, hasSufficientVolume, httpAgent, httpsAgent, isAlpacaBrokerCredentials, isAvailable, isContractTradable, isCryptoPair, isExpiringWithin, isMarginAccount, isOptionOrderCancelable, isOptionOrderTerminal, isOrderFillable, isOrderFilled, isOrderOpen, isOrderTerminal$1 as isOrderTerminalStatus, isSupportedCryptoPair, isTransientNetworkError, index$1 as legacyApi, limitBuyWithTakeProfit, limitsFor, limitsInventory, listAliases, llmAliases, llmBreakers, normaliseAnthropicStream, normaliseOpenAiStream, normaliseParams, normaliseStream, ocoOrders, orderUtils, orderedRoutes, otoOrders, paginate, paginateAll, parseOCCSymbol, protectLongPosition, protectShortPosition, rateLimiters$1 as rateLimiters, resetLogger, resetProviderGuards, resetRiskFreeRateCache, resolveChain, resolveDefaultDirectCaller, riskNs as risk, rollOptionPosition, roundPriceForAlpaca$3 as roundPriceForAlpaca, roundPriceForAlpacaNumber, routeKeyFor, routeSupports, routeTable, safeValidateResponse, sampleCohort, searchNews, sellAllCrypto, sellCryptoNotional, sellToClose, sellToOpen, setLogger, setRiskFreeRate, shortWithStopLoss, sortOrdersByDate, strategyNs as strategy, sumUsage, index as tradingPolicy, trailingStops, unavailableStatistic, updateAccountConfiguration, updateTrailingStop, validateAlpacaCredentials, validateAlphaVantageApiKey, validateMassiveApiKey$1 as validateMassiveApiKey, validateMultiLegOrder, validateResponse, verifyFetchKeepAlive, volatilityNs as volatility, waitForOrderFill, withProviderGuards, withRetry, withTimeout };
80098
80267
  //# sourceMappingURL=index.mjs.map