@livefolio/sdk 0.5.0-rc.3 → 0.5.0-rc.5

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
@@ -127,6 +127,22 @@ type Series = ReadonlyArray<{
127
127
  t: Date;
128
128
  v: number;
129
129
  }>;
130
+ /**
131
+ * A cash distribution (dividend) or interest payment for an asset, carrying
132
+ * what the SDK needs to credit cash and classify the income per-lot.
133
+ *
134
+ * `incomeKind: 'qualified-eligible'` means the distribution CAN be qualified if
135
+ * a holding lot satisfies the 60-of-121-day rule; the runtime resolves the
136
+ * actual qualified-vs-ordinary split per lot. `'ordinary'`/`'interest'` are
137
+ * never qualified.
138
+ */
139
+ type DividendEvent = {
140
+ asset: Asset;
141
+ exDate: Date;
142
+ payDate: Date;
143
+ amountPerShare: number;
144
+ incomeKind: 'qualified-eligible' | 'ordinary' | 'interest';
145
+ };
130
146
 
131
147
  /**
132
148
  * Stable opaque string identifier for a {@link Position}. Generated by the
@@ -187,7 +203,7 @@ type IncomeKind = 'capital-gain' | 'qualified-dividend' | 'ordinary-dividend' |
187
203
  * sales reduce `quantity` and pro-rate `basis`.
188
204
  */
189
205
  type Lot = {
190
- /** Opaque id assigned by {@link nextLotId} on creation. */
206
+ /** Opaque id assigned by `nextLotId` (internal) on creation. */
191
207
  id: string;
192
208
  asset: Asset;
193
209
  /** Shares remaining in this lot after any partial sales. */
@@ -767,9 +783,13 @@ interface DataFeed {
767
783
  * @param asset - The instrument to fetch bars for.
768
784
  * @param range - Half-open date range; `range.from` inclusive, `range.to` exclusive.
769
785
  * @param freq - Bar width. `'1d'` returns one bar per trading day.
786
+ * @param kind - `'adjusted'` (default) applies split/dividend adjustments;
787
+ * `'unadjusted'` returns raw prices. Indicators consume adjusted bars;
788
+ * execution fills and dividend cash-flow use unadjusted bars. Vendors that
789
+ * do not distinguish may ignore this and always return their single series.
770
790
  * @returns An async iterable of {@link Bar} objects.
771
791
  */
772
- bars(asset: Asset, range: DateRange, freq: Frequency): AsyncIterable<Bar>;
792
+ bars(asset: Asset, range: DateRange, freq: Frequency, kind?: 'adjusted' | 'unadjusted'): AsyncIterable<Bar>;
773
793
  /**
774
794
  * Returns a snapshot of fundamental data for `asset` as of `t`.
775
795
  * Optional — not all data providers carry fundamentals.
@@ -790,6 +810,17 @@ interface DataFeed {
790
810
  * @returns An async iterable of {@link DataEvent} objects.
791
811
  */
792
812
  events?(range: DateRange, kinds: ReadonlyArray<EventKind>): AsyncIterable<DataEvent>;
813
+ /**
814
+ * Returns cash distributions (dividends / interest) for `asset` over `range`.
815
+ * Optional — providers without dividend data omit it. Consumed by
816
+ * `runBacktest`'s per-session dividend hook. Amounts are per-share, on the
817
+ * unadjusted price basis.
818
+ *
819
+ * @param asset - The instrument to query.
820
+ * @param range - Half-open date range.
821
+ * @returns A promise resolving to an array of {@link DividendEvent} objects.
822
+ */
823
+ dividends?(asset: Asset, range: DateRange): Promise<DividendEvent[]>;
793
824
  }
794
825
 
795
826
  /**
@@ -1620,6 +1651,26 @@ type CashEvent = {
1620
1651
  */
1621
1652
  reason?: 'deposit' | 'withdrawal' | 'interest' | 'dividend';
1622
1653
  };
1654
+ /** How dividends are handled during a backtest. `reinvest: true` enables DRIP (dividend reinvestment). */
1655
+ type DividendsConfig = {
1656
+ reinvest: boolean;
1657
+ };
1658
+ /**
1659
+ * How idle cash earns interest during a backtest.
1660
+ * - `none` — cash earns nothing (default).
1661
+ * - `flat` — a constant annual percentage yield; daily rate is `apy / 365`.
1662
+ * - `tbill` — track a macro yield series (default `DGS3MO`) minus `spread`, as `(yield/100 - spread) / 365`.
1663
+ */
1664
+ type CashYieldConfig = {
1665
+ kind: 'none';
1666
+ } | {
1667
+ kind: 'flat';
1668
+ apy: number;
1669
+ } | {
1670
+ kind: 'tbill';
1671
+ spread: number;
1672
+ assetId?: AssetId;
1673
+ };
1623
1674
  /**
1624
1675
  * All inputs required to run a historical backtest.
1625
1676
  *
@@ -1684,6 +1735,32 @@ type RunBacktestOptions<F extends Features = Features, S = unknown> = {
1684
1735
  * fund withdrawals is deferred to a later release, so this behavior may change.
1685
1736
  */
1686
1737
  cashEvents?: ReadonlyArray<CashEvent>;
1738
+ /**
1739
+ * Optional dividend handling. When `dataFeed.dividends` exists, the universe's
1740
+ * day-0 dividends are pre-fetched and dividends are applied to held lots on the
1741
+ * first session on/after their `exDate`: cash mode credits cash, DRIP mode
1742
+ * (`reinvest: true`) reinvests into a new lot at the unadjusted pay-date close.
1743
+ *
1744
+ * @remarks Default = no dividends applied unless `dataFeed.dividends` exists;
1745
+ * `reinvest` defaults to `false` (cash mode).
1746
+ * @remarks Static-universe assumption: dividends are queried once for the day-0
1747
+ * universe (`strategy.universe(sessions[0], initialPortfolio)`). Assets that
1748
+ * enter the universe on later sessions — e.g. a dynamic-universe strategy that
1749
+ * opens a new position mid-run — will NOT have their dividends applied. This is
1750
+ * a non-issue for `fromSpec` strategies, whose universe is statically declared.
1751
+ */
1752
+ dividends?: DividendsConfig;
1753
+ /**
1754
+ * Optional idle-cash interest accrual. Each session — after dividends, before
1755
+ * the strategy runs — interest is accrued on positive cash at a daily rate
1756
+ * resolved from this config (`flat` → `apy/365`; `tbill` → macro yield series
1757
+ * `(yield/100 - spread)/365`, clamped ≥ 0). The interest is credited to cash,
1758
+ * recorded as an `interest` `RealizedEvent` on the synthetic cash asset, and
1759
+ * reported via `BacktestSnapshot.interestIncome`.
1760
+ *
1761
+ * @remarks Default = `{ kind: 'none' }` (no interest → today's behavior).
1762
+ */
1763
+ cashYield?: CashYieldConfig;
1687
1764
  };
1688
1765
  /**
1689
1766
  * A point-in-time snapshot of the simulation at the end of a single trading session.
@@ -1704,6 +1781,13 @@ type BacktestSnapshot = {
1704
1781
  * Net cash delta applied this session via `cashEvents`. Omitted when zero.
1705
1782
  */
1706
1783
  cashFlow?: number;
1784
+ /** Dividend income recognized this session, split by qualified status. Omitted when zero. */
1785
+ dividendIncome?: {
1786
+ qualified: number;
1787
+ ordinary: number;
1788
+ };
1789
+ /** Interest income accrued on cash this session. Omitted when zero. */
1790
+ interestIncome?: number;
1707
1791
  };
1708
1792
  /**
1709
1793
  * The return value of `runBacktest`, containing the full simulation history
@@ -2202,6 +2286,28 @@ type BacktestExecutorOptions = {
2202
2286
  * the fill quantity and recorded in `Fill.fees`. Defaults to `0`.
2203
2287
  */
2204
2288
  perShareFee?: number;
2289
+ /**
2290
+ * Tax-lot selection method applied to long sells (a `rebalance` reduce or a
2291
+ * `close` of a long position). When set to a non-default method
2292
+ * (`'LIFO'` / `'HIFO'` / `'min-tax'`), such a sell is split into one
2293
+ * {@link Fill} per selected lot — each carrying `Fill.lotId` — so
2294
+ * {@link applyFills} consumes those exact lots.
2295
+ *
2296
+ * Defaults to `'FIFO'` (equivalently, leaving this unset): the executor emits
2297
+ * a single fill per order with no `lotId`, and `applyFills` performs its own
2298
+ * internal FIFO. Buys, short-side closes, and `adjust` orders are never split.
2299
+ */
2300
+ lotMethod?: 'FIFO' | 'LIFO' | 'HIFO' | 'min-tax';
2301
+ /**
2302
+ * Short- and long-term capital-gains tax rates (as decimals, e.g. `0.37`)
2303
+ * forwarded to the `'min-tax'` selector. **Required** when
2304
+ * `lotMethod === 'min-tax'`; the constructor throws otherwise. Ignored for
2305
+ * all other lot methods.
2306
+ */
2307
+ taxRates?: {
2308
+ shortTerm: number;
2309
+ longTerm: number;
2310
+ };
2205
2311
  };
2206
2312
  /**
2207
2313
  * Reference {@link Executor} implementation for backtesting. Fills each order
@@ -2222,6 +2328,12 @@ type BacktestExecutorOptions = {
2222
2328
  * A flat per-share fee is added to `Fill.fees`. Orders with zero quantity are
2223
2329
  * silently skipped.
2224
2330
  *
2331
+ * **Lot selection**: by default each order yields exactly one fill. When a
2332
+ * non-default `lotMethod` (`'LIFO'` / `'HIFO'` / `'min-tax'`) is configured,
2333
+ * long sells (a `rebalance` reduce or a `close` of a long position) are split
2334
+ * into one fill per selected lot — each tagged with `Fill.lotId` — so
2335
+ * {@link applyFills} consumes those exact lots. See {@link BacktestExecutorOptions.lotMethod}.
2336
+ *
2225
2337
  * @example
2226
2338
  * ```ts
2227
2339
  * import { BacktestExecutor } from '@livefolio/sdk';
@@ -2250,7 +2362,8 @@ declare class BacktestExecutor implements Executor {
2250
2362
  * when the routed feed does not support the requested optional method.
2251
2363
  *
2252
2364
  * Distinguish the two cases via the message text: "no feed registered" vs
2253
- * "does not implement fundamentals".
2365
+ * "does not implement `<method>`" (e.g. "does not implement fundamentals()" or
2366
+ * "does not implement dividends()").
2254
2367
  */
2255
2368
  declare class RoutingDataFeedError extends Error {
2256
2369
  constructor(message: string);
@@ -2271,9 +2384,11 @@ type RoutingDataFeedRouteMap = Readonly<Partial<Record<Asset['kind'], DataFeed>>
2271
2384
  * - **Function form:** `new RoutingDataFeed((a) => a.kind === 'macro' ? fred : yahoo)`.
2272
2385
  * Use when routing depends on more than `kind` (e.g. allowlists).
2273
2386
  *
2274
- * The router does **not** implement `events()` — the optional method is
2275
- * genuinely absent (`'events' in router === false`). Cross-feed event
2276
- * fan-out is deferred until a real consumer materializes.
2387
+ * `dividends()` and `fundamentals()` ARE implemented each targets a single
2388
+ * asset, so it resolves to that asset's routed feed (or throws if the feed
2389
+ * lacks the method). The router does **not** implement `events()` — the
2390
+ * optional method is genuinely absent (`'events' in router === false`) because
2391
+ * cross-feed event fan-out is a separate, deferred problem.
2277
2392
  *
2278
2393
  * @example
2279
2394
  * ```ts
@@ -2292,8 +2407,17 @@ type RoutingDataFeedRouteMap = Readonly<Partial<Record<Asset['kind'], DataFeed>>
2292
2407
  declare class RoutingDataFeed implements DataFeed {
2293
2408
  private readonly route;
2294
2409
  constructor(routes: RoutingDataFeedRouteMap | RoutingDataFeedRouteFn);
2295
- bars(asset: Asset, range: DateRange, freq: Frequency): AsyncGenerator<Bar>;
2410
+ bars(asset: Asset, range: DateRange, freq: Frequency, kind?: 'adjusted' | 'unadjusted'): AsyncGenerator<Bar>;
2296
2411
  fundamentals(asset: Asset, t: Date): Promise<Fundamentals>;
2412
+ /**
2413
+ * Resolves `asset` to its routed feed and delegates `dividends`. This method
2414
+ * is ALWAYS present on the router (unlike a leaf feed's optional `dividends?`),
2415
+ * so `typeof routingFeed.dividends === 'function'` is always `true` — capability
2416
+ * detection must account for the routed feed possibly lacking it at call time.
2417
+ *
2418
+ * @throws {RoutingDataFeedError} when the routed feed does not implement `dividends`.
2419
+ */
2420
+ dividends(asset: Asset, range: DateRange): Promise<DividendEvent[]>;
2297
2421
  private resolve;
2298
2422
  }
2299
2423
 
@@ -3194,7 +3318,7 @@ declare function evaluateFeatureSpecs(specs: ReadonlyArray<TacticalFeatureSpec>,
3194
3318
  * independently scaled); `volume` is passed through from the underlying bar.
3195
3319
  *
3196
3320
  * Non-synthetic assets are proxied transparently to the original `dataFeed`.
3197
- * `fundamentals` and `events` methods, if present, are forwarded unchanged.
3321
+ * `fundamentals`, `events`, and `dividends` methods, if present, are forwarded unchanged.
3198
3322
  *
3199
3323
  * Throws at construction time if `synthetics` contains duplicate `id` values.
3200
3324
  *
@@ -3923,25 +4047,166 @@ declare function computeTaxBill(income: TaxableIncome, rates: TaxRates): {
3923
4047
  };
3924
4048
  };
3925
4049
 
4050
+ /**
4051
+ * Options for the 60-of-121-day qualified-dividend holding test.
4052
+ *
4053
+ * Both fields default to values for common stock dividends: the investor must
4054
+ * have held the lot throughout the 60-day window ending at the ex-dividend date, within
4055
+ * the 121-day window that begins 60 days before the ex-date.
4056
+ */
4057
+ type QualificationOpts = {
4058
+ /** Minimum days the lot must be held within the window. Defaults to `60`. */
4059
+ holdingDaysRequired?: number;
4060
+ /** Width of the holding window in calendar days. Defaults to `121`. */
4061
+ windowDays?: number;
4062
+ };
4063
+ /**
4064
+ * Determines whether a single {@link Lot} satisfies the IRS 60-of-121-day
4065
+ * qualified-dividend holding requirement as of a given `exDate`.
4066
+ *
4067
+ * The 121-day window is centred on `exDate` with `half = floor(121 / 2) = 60`,
4068
+ * so it spans the 60 days before `exDate`, the ex-date itself, and the 60 days
4069
+ * after. Only days the lot was held **on or before** `exDate` count — `heldTo`
4070
+ * is capped at `exDate` so future hold time never qualifies a dividend. This
4071
+ * keeps the test lookahead-free and conservative: it never over-grants
4072
+ * qualified status. Because `heldTo` is capped at `exDate`, the most a lot can
4073
+ * accumulate is the 60-day run-up to the ex-date, so the default threshold of
4074
+ * `60` models "held throughout the 60-day window ending at ex-date"
4075
+ * (`60 >= 60`). Returns `true` when the days held within the window are
4076
+ * `>= holdingDaysRequired`.
4077
+ *
4078
+ * @param lot - The tax lot to test.
4079
+ * @param exDate - The dividend ex-dividend date.
4080
+ * @param opts - Optional overrides for `holdingDaysRequired` (default `60` —
4081
+ * "held throughout the 60-day window ending at ex-date") and `windowDays`
4082
+ * (default `121`).
4083
+ * @returns `true` when the lot satisfies the holding-period test.
4084
+ */
4085
+ declare function isQualifiedForLot(lot: Lot, exDate: Date, opts?: QualificationOpts): boolean;
4086
+ /**
4087
+ * The result of {@link distributeDividend}: per-lot cash amounts with
4088
+ * qualified/ordinary classification, plus rolled-up totals.
4089
+ */
4090
+ type DividendDistribution = {
4091
+ /** Rolled-up qualified and ordinary dividend totals across all participating lots. */
4092
+ totals: {
4093
+ qualified: number;
4094
+ ordinary: number;
4095
+ };
4096
+ /** One entry per participating lot: the cash received and whether it is qualified. */
4097
+ perLot: {
4098
+ lotId: string;
4099
+ cash: number;
4100
+ qualified: boolean;
4101
+ }[];
4102
+ };
4103
+ /**
4104
+ * Distributes a {@link DividendEvent} across a set of lots held at the
4105
+ * ex-dividend date, classifying each lot's income as qualified or ordinary.
4106
+ *
4107
+ * Only lots that pass all three eligibility tests participate:
4108
+ * - `quantity > 0`
4109
+ * - `openDate <= exDate` (lot was open before or on the ex-date)
4110
+ * - `asset.id === event.asset.id` (same asset)
4111
+ *
4112
+ * For `incomeKind: 'ordinary'` or `'interest'` events every participating lot
4113
+ * is classified as ordinary regardless of how long it was held. For
4114
+ * `'qualified-eligible'` events each lot is tested individually via
4115
+ * {@link isQualifiedForLot} using the default 60-of-121-day rule.
4116
+ *
4117
+ * @param event - The dividend event to distribute.
4118
+ * @param lotsHeldAtExDate - All lots in the portfolio at the ex-dividend date
4119
+ * (the function filters to eligible ones internally).
4120
+ * @returns A {@link DividendDistribution} with per-lot breakdown and rolled-up totals.
4121
+ */
4122
+ declare function distributeDividend(event: DividendEvent, lotsHeldAtExDate: readonly Lot[]): DividendDistribution;
4123
+ /**
4124
+ * Converts dividend cash into a new whole-share DRIP tax lot at the pay-date price.
4125
+ *
4126
+ * Computes `shares = floor(cashAvailable / pricePayDate)` and opens a fresh
4127
+ * {@link Lot} with `openDate = payDate`, `openPrice = pricePayDate`,
4128
+ * `basis = shares * pricePayDate`, and `dripParent` set to the originating lot
4129
+ * id. Any fractional-share remainder is returned as `residual`.
4130
+ *
4131
+ * When `cashAvailable` is less than one share (`shares === 0`), `newLot.quantity`
4132
+ * will be `0` and `residual` will equal `cashAvailable`. The caller is
4133
+ * responsible for skipping zero-quantity lots.
4134
+ *
4135
+ * @param cashAvailable - Total dividend cash to reinvest.
4136
+ * @param asset - The asset being purchased.
4137
+ * @param pricePayDate - Share price on the dividend pay date.
4138
+ * @param payDate - The dividend pay date; becomes `openDate` on the new lot.
4139
+ * @param dripParent - Id of the originating lot that generated the dividend cash.
4140
+ * @returns An object with `newLot` (the freshly created {@link Lot}) and
4141
+ * `residual` (uninvested cash remainder).
4142
+ */
4143
+ declare function reinvestDividend(cashAvailable: number, asset: Asset, pricePayDate: number, payDate: Date, dripParent: string): {
4144
+ newLot: Lot;
4145
+ residual: number;
4146
+ };
4147
+
4148
+ /**
4149
+ * Result of a single {@link accrueCashInterest} call: the updated cash balance
4150
+ * and the interest earned in that session.
4151
+ */
4152
+ type CashInterestResult = {
4153
+ /** Cash balance after interest has been credited: `cash + interest`. */
4154
+ newCash: number;
4155
+ /** Interest earned in this session: `cash * dailyRate`. */
4156
+ interest: number;
4157
+ };
4158
+ /**
4159
+ * Pure per-session interest accrual using the actual/365 day-count convention.
4160
+ *
4161
+ * Computes simple (non-compounding within a single call) interest for one
4162
+ * trading session. To model compounding over multiple sessions, call this
4163
+ * function repeatedly, passing the returned `newCash` as `cash` in each
4164
+ * subsequent call.
4165
+ *
4166
+ * `dailyRate` should be `APY / 365` for an actual/365 day-count (e.g.
4167
+ * `0.05 / 365` for a 5% APY). A daily rate of `0` returns the original cash
4168
+ * balance with zero interest.
4169
+ *
4170
+ * @param cash - The current cash balance before interest is applied.
4171
+ * @param dailyRate - The per-session interest rate expressed as a decimal
4172
+ * fraction (e.g. `0.05 / 365` for 5% APY on an actual/365 basis).
4173
+ * @returns A {@link CashInterestResult} with `newCash` (updated balance) and
4174
+ * `interest` (amount earned this session).
4175
+ *
4176
+ * @example
4177
+ * ```ts
4178
+ * // Single session at 5% APY
4179
+ * const { newCash, interest } = accrueCashInterest(10_000, 0.05 / 365);
4180
+ * ```
4181
+ */
4182
+ declare function accrueCashInterest(cash: number, dailyRate: number): CashInterestResult;
4183
+
4184
+ type index_CashInterestResult = CashInterestResult;
4185
+ type index_DividendDistribution = DividendDistribution;
3926
4186
  type index_LotSlice = LotSlice;
3927
4187
  declare const index_ORDINARY_OFFSET_CAP: typeof ORDINARY_OFFSET_CAP;
4188
+ type index_QualificationOpts = QualificationOpts;
3928
4189
  type index_RealizeResult = RealizeResult;
3929
4190
  type index_TaxRates = TaxRates;
3930
4191
  type index_TaxableIncome = TaxableIncome;
4192
+ declare const index_accrueCashInterest: typeof accrueCashInterest;
3931
4193
  declare const index_aggregateByYear: typeof aggregateByYear;
3932
4194
  declare const index_bucketByTerm: typeof bucketByTerm;
3933
4195
  declare const index_computeTaxBill: typeof computeTaxBill;
3934
4196
  declare const index_crossOffset: typeof crossOffset;
4197
+ declare const index_distributeDividend: typeof distributeDividend;
3935
4198
  declare const index_holdingPeriodDays: typeof holdingPeriodDays;
3936
4199
  declare const index_isLongTerm: typeof isLongTerm;
4200
+ declare const index_isQualifiedForLot: typeof isQualifiedForLot;
3937
4201
  declare const index_netWithinBucket: typeof netWithinBucket;
3938
4202
  declare const index_realize: typeof realize;
4203
+ declare const index_reinvestDividend: typeof reinvestDividend;
3939
4204
  declare const index_selectFIFO: typeof selectFIFO;
3940
4205
  declare const index_selectHIFO: typeof selectHIFO;
3941
4206
  declare const index_selectLIFO: typeof selectLIFO;
3942
4207
  declare const index_selectMinTax: typeof selectMinTax;
3943
4208
  declare namespace index {
3944
- export { type index_LotSlice as LotSlice, index_ORDINARY_OFFSET_CAP as ORDINARY_OFFSET_CAP, type index_RealizeResult as RealizeResult, type index_TaxRates as TaxRates, type index_TaxableIncome as TaxableIncome, index_aggregateByYear as aggregateByYear, index_bucketByTerm as bucketByTerm, index_computeTaxBill as computeTaxBill, index_crossOffset as crossOffset, index_holdingPeriodDays as holdingPeriodDays, index_isLongTerm as isLongTerm, index_netWithinBucket as netWithinBucket, index_realize as realize, index_selectFIFO as selectFIFO, index_selectHIFO as selectHIFO, index_selectLIFO as selectLIFO, index_selectMinTax as selectMinTax };
4209
+ export { type index_CashInterestResult as CashInterestResult, type index_DividendDistribution as DividendDistribution, type index_LotSlice as LotSlice, index_ORDINARY_OFFSET_CAP as ORDINARY_OFFSET_CAP, type index_QualificationOpts as QualificationOpts, type index_RealizeResult as RealizeResult, type index_TaxRates as TaxRates, type index_TaxableIncome as TaxableIncome, index_accrueCashInterest as accrueCashInterest, index_aggregateByYear as aggregateByYear, index_bucketByTerm as bucketByTerm, index_computeTaxBill as computeTaxBill, index_crossOffset as crossOffset, index_distributeDividend as distributeDividend, index_holdingPeriodDays as holdingPeriodDays, index_isLongTerm as isLongTerm, index_isQualifiedForLot as isQualifiedForLot, index_netWithinBucket as netWithinBucket, index_realize as realize, index_reinvestDividend as reinvestDividend, index_selectFIFO as selectFIFO, index_selectHIFO as selectHIFO, index_selectLIFO as selectLIFO, index_selectMinTax as selectMinTax };
3945
4210
  }
3946
4211
 
3947
4212
  /**
@@ -4057,4 +4322,4 @@ declare function applyOrders(portfolio: Portfolio, orders: ReadonlyArray<Order>)
4057
4322
  */
4058
4323
  declare function positionsByAsset(portfolio: Portfolio): Position[];
4059
4324
 
4060
- export { type AdhocTimeOverrides, type AdjustOrder, type AllocateNode, type Asset, type AssetId, type AssetRef, BacktestExecutor, type BacktestExecutorOptions, type BacktestResult, type BacktestSnapshot, type Bar, type BarField, type Calendar, type CashEvent, CashEventQueue, type CloseOrder, type Comparison, type ComparisonOp, type ComputeFn, Crypto24x7Calendar, type DataEvent, type DataFeed, type DateRange, type EquityAsset, type EventKind, ExchangeCalendar, type ExchangeName, type Executor, type FeatureCache, type FeatureKey, type FeatureKind, type FeatureRef, FeatureRuntime, type FeatureRuntimeOptions, type FeatureScope, type FeatureSpec, type Features, type Fill, type Frequency, type FromSpecOptions, type Fundamentals, type HolidayRule, type IfNode, type IncomeKind, LSEExchangeCalendar, type LiveEvent, type Lot, type LotSlice, type MacroAsset, MemoryFeatureCache, NYSEExchangeCalendar, type NextOpenFn, ORDINARY_OFFSET_CAP, type OpenOrder, type Order, type PollingSchedule, type PollingStreamOptions, type Portfolio, type Position, type PositionId, type PriceMap, type Quote, type QuoteFeed, type RealizeResult, type RealizedEvent, type RebalanceConfig, type RebalanceFrequency, type RebalanceOrder, type ReturnMode, RoutingDataFeed, RoutingDataFeedError, type RoutingDataFeedRouteFn, type RoutingDataFeedRouteMap, RoutingQuoteFeed, RoutingQuoteFeedError, type RoutingQuoteFeedRouteFn, type RoutingQuoteFeedRouteMap, RoutingStreamingDataFeed, RoutingStreamingDataFeedError, type RoutingStreamingDataFeedRouteFn, type RoutingStreamingDataFeedRouteMap, type RuleNode, type RuleTreeState, type RunBacktestOptions, type RunLiveOptions, type Series, type Session, type SpecialClose, type SpecialOpen, type Strategy, type StreamingBar, type StreamingDataFeed, type SyntheticAsset, type TacticalFeatureKind, type TacticalFeatureSpec, type TacticalFeatures, type TacticalSpec, type TargetWeights, type TaxRates, type TaxableIncome, type TimeOfDay, type Tolerance, type WithStreamingSyntheticsOptions, aggregateByYear, applyFills, applyOrders, barsToSeries, bucketByTerm, collectBars, computeTaxBill, crossOffset, defineFeature, drawdown, ema, evaluateFeatureSpecs, evaluateRuleTree, index$1 as features, fromSpec, getCalendar, getFeatureCompute, holdingPeriodDays, isLongTerm, isRebalanceDay, netWithinBucket, paramsHash, periodKey, pollingStreamFromHistorical, positionsByAsset, realize, reconcile, returnSeries, rsi, runBacktest, runLive, selectFIFO, selectHIFO, selectLIFO, selectMinTax, seriesAt, sma, index$2 as tactical, index as tax, volatility, withStreamingSynthetics, withSynthetics };
4325
+ export { type AdhocTimeOverrides, type AdjustOrder, type AllocateNode, type Asset, type AssetId, type AssetRef, BacktestExecutor, type BacktestExecutorOptions, type BacktestResult, type BacktestSnapshot, type Bar, type BarField, type Calendar, type CashEvent, CashEventQueue, type CashInterestResult, type CashYieldConfig, type CloseOrder, type Comparison, type ComparisonOp, type ComputeFn, Crypto24x7Calendar, type DataEvent, type DataFeed, type DateRange, type DividendDistribution, type DividendEvent, type DividendsConfig, type EquityAsset, type EventKind, ExchangeCalendar, type ExchangeName, type Executor, type FeatureCache, type FeatureKey, type FeatureKind, type FeatureRef, FeatureRuntime, type FeatureRuntimeOptions, type FeatureScope, type FeatureSpec, type Features, type Fill, type Frequency, type FromSpecOptions, type Fundamentals, type HolidayRule, type IfNode, type IncomeKind, LSEExchangeCalendar, type LiveEvent, type Lot, type LotSlice, type MacroAsset, MemoryFeatureCache, NYSEExchangeCalendar, type NextOpenFn, ORDINARY_OFFSET_CAP, type OpenOrder, type Order, type PollingSchedule, type PollingStreamOptions, type Portfolio, type Position, type PositionId, type PriceMap, type QualificationOpts, type Quote, type QuoteFeed, type RealizeResult, type RealizedEvent, type RebalanceConfig, type RebalanceFrequency, type RebalanceOrder, type ReturnMode, RoutingDataFeed, RoutingDataFeedError, type RoutingDataFeedRouteFn, type RoutingDataFeedRouteMap, RoutingQuoteFeed, RoutingQuoteFeedError, type RoutingQuoteFeedRouteFn, type RoutingQuoteFeedRouteMap, RoutingStreamingDataFeed, RoutingStreamingDataFeedError, type RoutingStreamingDataFeedRouteFn, type RoutingStreamingDataFeedRouteMap, type RuleNode, type RuleTreeState, type RunBacktestOptions, type RunLiveOptions, type Series, type Session, type SpecialClose, type SpecialOpen, type Strategy, type StreamingBar, type StreamingDataFeed, type SyntheticAsset, type TacticalFeatureKind, type TacticalFeatureSpec, type TacticalFeatures, type TacticalSpec, type TargetWeights, type TaxRates, type TaxableIncome, type TimeOfDay, type Tolerance, type WithStreamingSyntheticsOptions, accrueCashInterest, aggregateByYear, applyFills, applyOrders, barsToSeries, bucketByTerm, collectBars, computeTaxBill, crossOffset, defineFeature, distributeDividend, drawdown, ema, evaluateFeatureSpecs, evaluateRuleTree, index$1 as features, fromSpec, getCalendar, getFeatureCompute, holdingPeriodDays, isLongTerm, isQualifiedForLot, isRebalanceDay, netWithinBucket, paramsHash, periodKey, pollingStreamFromHistorical, positionsByAsset, realize, reconcile, reinvestDividend, returnSeries, rsi, runBacktest, runLive, selectFIFO, selectHIFO, selectLIFO, selectMinTax, seriesAt, sma, index$2 as tactical, index as tax, volatility, withStreamingSynthetics, withSynthetics };