@livefolio/sdk 0.5.0-rc.1 → 0.5.0-rc.3
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 +395 -50
- package/dist/index.js +253 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1599,6 +1599,27 @@ declare class FeatureRuntime {
|
|
|
1599
1599
|
compute(spec: FeatureSpec, asset: Asset): Promise<Series>;
|
|
1600
1600
|
}
|
|
1601
1601
|
|
|
1602
|
+
/**
|
|
1603
|
+
* A scheduled cash injection or withdrawal. Applied at the start of the
|
|
1604
|
+
* matching session — BEFORE `universe`/`features`/`build` — by `runBacktest`
|
|
1605
|
+
* (see Task 10 wiring). Events with `t <= sessionT` that have not yet been
|
|
1606
|
+
* consumed are applied (and summed) on that session.
|
|
1607
|
+
*/
|
|
1608
|
+
type CashEvent = {
|
|
1609
|
+
t: Date;
|
|
1610
|
+
/** Positive = deposit, negative = withdrawal. */
|
|
1611
|
+
delta: number;
|
|
1612
|
+
/**
|
|
1613
|
+
* Optional attribution tag for downstream metrics. `'deposit'`/`'withdrawal'`
|
|
1614
|
+
* are the natural tags for user-scheduled flows (this surface's main use case).
|
|
1615
|
+
* `'interest'`/`'dividend'` are accepted for callers who want to tag a
|
|
1616
|
+
* manually-scheduled flow as income, but the SDK's automatic per-session
|
|
1617
|
+
* interest/dividend hooks do NOT emit `CashEvent`s — they credit cash directly
|
|
1618
|
+
* and report via `BacktestSnapshot.interestIncome`/`dividendIncome`. User code
|
|
1619
|
+
* typically only sets `'deposit'`/`'withdrawal'`.
|
|
1620
|
+
*/
|
|
1621
|
+
reason?: 'deposit' | 'withdrawal' | 'interest' | 'dividend';
|
|
1622
|
+
};
|
|
1602
1623
|
/**
|
|
1603
1624
|
* All inputs required to run a historical backtest.
|
|
1604
1625
|
*
|
|
@@ -1653,6 +1674,16 @@ type RunBacktestOptions<F extends Features = Features, S = unknown> = {
|
|
|
1653
1674
|
* runtime seed its buffer from the historical bars without refetching).
|
|
1654
1675
|
*/
|
|
1655
1676
|
featureRuntime?: FeatureRuntime;
|
|
1677
|
+
/**
|
|
1678
|
+
* Optional scheduled deposits/withdrawals applied per-session before the
|
|
1679
|
+
* strategy runs. Matched by `t <= sessionT`; multiple due events are summed.
|
|
1680
|
+
* Defaults to none (today's behavior). See `BacktestSnapshot.cashFlow`.
|
|
1681
|
+
*
|
|
1682
|
+
* @remarks A withdrawal that exceeds available cash is allowed to drive cash
|
|
1683
|
+
* negative (logged via `console.warn`); automatic force-selling of holdings to
|
|
1684
|
+
* fund withdrawals is deferred to a later release, so this behavior may change.
|
|
1685
|
+
*/
|
|
1686
|
+
cashEvents?: ReadonlyArray<CashEvent>;
|
|
1656
1687
|
};
|
|
1657
1688
|
/**
|
|
1658
1689
|
* A point-in-time snapshot of the simulation at the end of a single trading session.
|
|
@@ -1669,6 +1700,10 @@ type BacktestSnapshot = {
|
|
|
1669
1700
|
orders: ReadonlyArray<Order>;
|
|
1670
1701
|
/** Fills returned by the executor for the orders above. */
|
|
1671
1702
|
fills: ReadonlyArray<Fill>;
|
|
1703
|
+
/**
|
|
1704
|
+
* Net cash delta applied this session via `cashEvents`. Omitted when zero.
|
|
1705
|
+
*/
|
|
1706
|
+
cashFlow?: number;
|
|
1672
1707
|
};
|
|
1673
1708
|
/**
|
|
1674
1709
|
* The return value of `runBacktest`, containing the full simulation history
|
|
@@ -1820,6 +1855,18 @@ interface StreamingDataFeed {
|
|
|
1820
1855
|
subscribe(assets: ReadonlyArray<Asset>): AsyncIterable<StreamingBar>;
|
|
1821
1856
|
}
|
|
1822
1857
|
|
|
1858
|
+
/**
|
|
1859
|
+
* Mutable queue for scheduling {@link CashEvent}s into a running `runLive`
|
|
1860
|
+
* stream. Construct one, pass it via {@link RunLiveOptions.cashEventQueue}, and
|
|
1861
|
+
* `push` events from outside the generator; they are drained at each session
|
|
1862
|
+
* close. A non-breaking alternative to a returned scheduling handle.
|
|
1863
|
+
*/
|
|
1864
|
+
declare class CashEventQueue {
|
|
1865
|
+
private pending;
|
|
1866
|
+
push(e: CashEvent): void;
|
|
1867
|
+
/** Remove and return events with `t <= now`, leaving later events queued. */
|
|
1868
|
+
drainDue(now: Date): CashEvent[];
|
|
1869
|
+
}
|
|
1823
1870
|
/**
|
|
1824
1871
|
* Unified event stream from {@link runLive}. Discriminated union of two variants:
|
|
1825
1872
|
*
|
|
@@ -1861,6 +1908,25 @@ type LiveEvent<F extends Features = Features, _S = unknown> = {
|
|
|
1861
1908
|
* `portfolio` + `prices`.
|
|
1862
1909
|
*/
|
|
1863
1910
|
previewPortfolio: Portfolio;
|
|
1911
|
+
} | {
|
|
1912
|
+
/**
|
|
1913
|
+
* A net cash injection/withdrawal applied to the committed portfolio at a
|
|
1914
|
+
* session close. Emitted BEFORE the `snapshot` for that session, so the
|
|
1915
|
+
* subsequent snapshot's `portfolio.cash` already reflects this delta.
|
|
1916
|
+
* Only emitted when the summed delta of due events is non-zero.
|
|
1917
|
+
*/
|
|
1918
|
+
type: 'cash';
|
|
1919
|
+
/** Session-close timestamp at which the delta was applied. */
|
|
1920
|
+
t: Date;
|
|
1921
|
+
/** Net cash delta applied (sum of all due events). Positive = deposit. */
|
|
1922
|
+
delta: number;
|
|
1923
|
+
/**
|
|
1924
|
+
* Attribution tag of the FIRST contributing event. When multiple cash
|
|
1925
|
+
* events are due at the same session close they are summed into one delta
|
|
1926
|
+
* and the other reasons are dropped — use `cashEventQueue` and drain
|
|
1927
|
+
* manually if you need per-event attribution.
|
|
1928
|
+
*/
|
|
1929
|
+
reason?: CashEvent['reason'];
|
|
1864
1930
|
} | (BacktestSnapshot & {
|
|
1865
1931
|
type: 'snapshot';
|
|
1866
1932
|
});
|
|
@@ -1891,6 +1957,20 @@ type RunLiveOptions<F extends Features = Features, S = unknown> = {
|
|
|
1891
1957
|
* seeded from `history.bars`.
|
|
1892
1958
|
*/
|
|
1893
1959
|
streamingRuntime?: FeatureRuntime;
|
|
1960
|
+
/**
|
|
1961
|
+
* Cash injections/withdrawals known up front. Each is applied to the
|
|
1962
|
+
* committed portfolio at the first session close whose date is `>= e.t`,
|
|
1963
|
+
* summed with any other due events for that session. For dynamic scheduling
|
|
1964
|
+
* after the stream has started, use {@link RunLiveOptions.cashEventQueue}.
|
|
1965
|
+
*/
|
|
1966
|
+
cashEvents?: ReadonlyArray<CashEvent>;
|
|
1967
|
+
/**
|
|
1968
|
+
* Optional mutable queue for scheduling cash events into the running stream
|
|
1969
|
+
* from outside the generator. Drained (alongside `cashEvents`) at each
|
|
1970
|
+
* session close. Construct a {@link CashEventQueue}, pass it here, and `push`
|
|
1971
|
+
* events as they arrive.
|
|
1972
|
+
*/
|
|
1973
|
+
cashEventQueue?: CashEventQueue;
|
|
1894
1974
|
};
|
|
1895
1975
|
/**
|
|
1896
1976
|
* Drives a {@link Strategy} against a streaming market-data source and yields
|
|
@@ -3286,34 +3366,34 @@ declare function isRebalanceDay(t: Date, freq: RebalanceFrequency, calendar: Cal
|
|
|
3286
3366
|
*/
|
|
3287
3367
|
declare function fromSpec(spec: TacticalSpec, opts: FromSpecOptions): Strategy<TacticalFeatures, RuleTreeState>;
|
|
3288
3368
|
|
|
3289
|
-
type index$
|
|
3290
|
-
type index$
|
|
3291
|
-
type index$
|
|
3292
|
-
type index$
|
|
3293
|
-
type index$
|
|
3294
|
-
type index$
|
|
3295
|
-
type index$
|
|
3296
|
-
type index$
|
|
3297
|
-
type index$
|
|
3298
|
-
type index$
|
|
3299
|
-
type index$
|
|
3300
|
-
type index$
|
|
3301
|
-
type index$
|
|
3302
|
-
type index$
|
|
3303
|
-
type index$
|
|
3304
|
-
type index$
|
|
3305
|
-
type index$
|
|
3306
|
-
type index$
|
|
3307
|
-
declare const index$
|
|
3308
|
-
declare const index$
|
|
3309
|
-
declare const index$
|
|
3310
|
-
declare const index$
|
|
3311
|
-
declare const index$
|
|
3312
|
-
declare const index$
|
|
3313
|
-
declare const index$
|
|
3314
|
-
declare const index$
|
|
3315
|
-
declare namespace index$
|
|
3316
|
-
export { type index$
|
|
3369
|
+
type index$2_AllocateNode = AllocateNode;
|
|
3370
|
+
type index$2_AssetRef = AssetRef;
|
|
3371
|
+
type index$2_Comparison = Comparison;
|
|
3372
|
+
type index$2_ComparisonOp = ComparisonOp;
|
|
3373
|
+
type index$2_FeatureRef = FeatureRef;
|
|
3374
|
+
type index$2_FromSpecOptions = FromSpecOptions;
|
|
3375
|
+
type index$2_IfNode = IfNode;
|
|
3376
|
+
type index$2_RebalanceConfig = RebalanceConfig;
|
|
3377
|
+
type index$2_RebalanceFrequency = RebalanceFrequency;
|
|
3378
|
+
type index$2_RuleNode = RuleNode;
|
|
3379
|
+
type index$2_RuleTreeState = RuleTreeState;
|
|
3380
|
+
type index$2_SyntheticAsset = SyntheticAsset;
|
|
3381
|
+
type index$2_TacticalFeatureKind = TacticalFeatureKind;
|
|
3382
|
+
type index$2_TacticalFeatureSpec = TacticalFeatureSpec;
|
|
3383
|
+
type index$2_TacticalFeatures = TacticalFeatures;
|
|
3384
|
+
type index$2_TacticalSpec = TacticalSpec;
|
|
3385
|
+
type index$2_Tolerance = Tolerance;
|
|
3386
|
+
type index$2_WithStreamingSyntheticsOptions = WithStreamingSyntheticsOptions;
|
|
3387
|
+
declare const index$2__resetTacticalDeprecationWarningForTesting: typeof _resetTacticalDeprecationWarningForTesting;
|
|
3388
|
+
declare const index$2_evaluateFeatureSpecs: typeof evaluateFeatureSpecs;
|
|
3389
|
+
declare const index$2_evaluateRuleTree: typeof evaluateRuleTree;
|
|
3390
|
+
declare const index$2_fromSpec: typeof fromSpec;
|
|
3391
|
+
declare const index$2_isRebalanceDay: typeof isRebalanceDay;
|
|
3392
|
+
declare const index$2_periodKey: typeof periodKey;
|
|
3393
|
+
declare const index$2_withStreamingSynthetics: typeof withStreamingSynthetics;
|
|
3394
|
+
declare const index$2_withSynthetics: typeof withSynthetics;
|
|
3395
|
+
declare namespace index$2 {
|
|
3396
|
+
export { type index$2_AllocateNode as AllocateNode, type index$2_AssetRef as AssetRef, type index$2_Comparison as Comparison, type index$2_ComparisonOp as ComparisonOp, type index$2_FeatureRef as FeatureRef, type index$2_FromSpecOptions as FromSpecOptions, type index$2_IfNode as IfNode, type index$2_RebalanceConfig as RebalanceConfig, type index$2_RebalanceFrequency as RebalanceFrequency, type index$2_RuleNode as RuleNode, type index$2_RuleTreeState as RuleTreeState, type index$2_SyntheticAsset as SyntheticAsset, type index$2_TacticalFeatureKind as TacticalFeatureKind, type index$2_TacticalFeatureSpec as TacticalFeatureSpec, type index$2_TacticalFeatures as TacticalFeatures, type index$2_TacticalSpec as TacticalSpec, type index$2_Tolerance as Tolerance, type index$2_WithStreamingSyntheticsOptions as WithStreamingSyntheticsOptions, index$2__resetTacticalDeprecationWarningForTesting as _resetTacticalDeprecationWarningForTesting, index$2_evaluateFeatureSpecs as evaluateFeatureSpecs, index$2_evaluateRuleTree as evaluateRuleTree, index$2_fromSpec as fromSpec, index$2_isRebalanceDay as isRebalanceDay, index$2_periodKey as periodKey, index$2_withStreamingSynthetics as withStreamingSynthetics, index$2_withSynthetics as withSynthetics };
|
|
3317
3397
|
}
|
|
3318
3398
|
|
|
3319
3399
|
/**
|
|
@@ -3575,28 +3655,293 @@ declare function volatility(series: Series, period: number): Series;
|
|
|
3575
3655
|
*/
|
|
3576
3656
|
declare function drawdown(series: Series, period: number): Series;
|
|
3577
3657
|
|
|
3578
|
-
type
|
|
3579
|
-
type
|
|
3580
|
-
type
|
|
3581
|
-
type
|
|
3582
|
-
declare const
|
|
3583
|
-
type
|
|
3584
|
-
type
|
|
3585
|
-
type
|
|
3586
|
-
declare const
|
|
3587
|
-
declare const
|
|
3588
|
-
declare const
|
|
3589
|
-
declare const
|
|
3590
|
-
declare const
|
|
3591
|
-
declare const
|
|
3592
|
-
declare const
|
|
3593
|
-
declare const
|
|
3594
|
-
declare const
|
|
3595
|
-
declare const
|
|
3596
|
-
declare const
|
|
3597
|
-
declare const
|
|
3658
|
+
type index$1_BarField = BarField;
|
|
3659
|
+
type index$1_ComputeFn = ComputeFn;
|
|
3660
|
+
type index$1_FeatureKind = FeatureKind;
|
|
3661
|
+
type index$1_FeatureRuntime = FeatureRuntime;
|
|
3662
|
+
declare const index$1_FeatureRuntime: typeof FeatureRuntime;
|
|
3663
|
+
type index$1_FeatureRuntimeOptions = FeatureRuntimeOptions;
|
|
3664
|
+
type index$1_FeatureSpec = FeatureSpec;
|
|
3665
|
+
type index$1_ReturnMode = ReturnMode;
|
|
3666
|
+
declare const index$1_barsToSeries: typeof barsToSeries;
|
|
3667
|
+
declare const index$1_collectBars: typeof collectBars;
|
|
3668
|
+
declare const index$1_defineFeature: typeof defineFeature;
|
|
3669
|
+
declare const index$1_drawdown: typeof drawdown;
|
|
3670
|
+
declare const index$1_ema: typeof ema;
|
|
3671
|
+
declare const index$1_getFeatureCompute: typeof getFeatureCompute;
|
|
3672
|
+
declare const index$1_paramsHash: typeof paramsHash;
|
|
3673
|
+
declare const index$1_returnSeries: typeof returnSeries;
|
|
3674
|
+
declare const index$1_rsi: typeof rsi;
|
|
3675
|
+
declare const index$1_seriesAt: typeof seriesAt;
|
|
3676
|
+
declare const index$1_sma: typeof sma;
|
|
3677
|
+
declare const index$1_volatility: typeof volatility;
|
|
3678
|
+
declare namespace index$1 {
|
|
3679
|
+
export { type index$1_BarField as BarField, type index$1_ComputeFn as ComputeFn, type index$1_FeatureKind as FeatureKind, index$1_FeatureRuntime as FeatureRuntime, type index$1_FeatureRuntimeOptions as FeatureRuntimeOptions, type index$1_FeatureSpec as FeatureSpec, type index$1_ReturnMode as ReturnMode, index$1_barsToSeries as barsToSeries, index$1_collectBars as collectBars, index$1_defineFeature as defineFeature, index$1_drawdown as drawdown, index$1_ema as ema, index$1_getFeatureCompute as getFeatureCompute, index$1_paramsHash as paramsHash, index$1_returnSeries as returnSeries, index$1_rsi as rsi, index$1_seriesAt as seriesAt, index$1_sma as sma, index$1_volatility as volatility };
|
|
3680
|
+
}
|
|
3681
|
+
|
|
3682
|
+
/**
|
|
3683
|
+
* Calendar days between a lot's open date and `asOf` (float; may be fractional
|
|
3684
|
+
* or negative if `asOf` precedes `openDate`). Callers may `Math.floor` it.
|
|
3685
|
+
*/
|
|
3686
|
+
declare function holdingPeriodDays(lot: Lot, asOf: Date): number;
|
|
3687
|
+
/** IRS §1222 rule: a holding period of strictly more than 365 calendar days is long-term. */
|
|
3688
|
+
declare function isLongTerm(days: number): boolean;
|
|
3689
|
+
/** Result of {@link realize}: the realized event plus what's left of the lot (`null` on a full sale). */
|
|
3690
|
+
type RealizeResult = {
|
|
3691
|
+
event: RealizedEvent;
|
|
3692
|
+
remainingLot: Lot | null;
|
|
3693
|
+
};
|
|
3694
|
+
/**
|
|
3695
|
+
* Realizes `qty` shares of `lot` at `salePrice` as of `asOf`, producing one
|
|
3696
|
+
* {@link RealizedEvent} and the remaining lot (or `null` on a full sale).
|
|
3697
|
+
*
|
|
3698
|
+
* Pure gain/loss primitive for estimation and lot ranking (e.g. selectMinTax,
|
|
3699
|
+
* TLH preview). It does **not** model transaction fees: pass a `salePrice` that
|
|
3700
|
+
* is already net of any per-share fee if you need fee-adjusted proceeds. The
|
|
3701
|
+
* stateful, fee-aware realization path used during execution lives in
|
|
3702
|
+
* `applyFills` (`consumeLots`), which pro-rates `fill.fees` across slices.
|
|
3703
|
+
*
|
|
3704
|
+
* Basis is pro-rated as `lot.basis / lot.quantity * qty` (so any
|
|
3705
|
+
* `washSaleAdjustment` already folded into `lot.basis` is carried through).
|
|
3706
|
+
*
|
|
3707
|
+
* @param lot - The lot to realize against.
|
|
3708
|
+
* @param qty - Shares to realize. Must be `> 0` and `<= lot.quantity`.
|
|
3709
|
+
* @param salePrice - Per-share sale price (net of fees if fee-adjustment is desired).
|
|
3710
|
+
* @param asOf - Sale date; drives short/long classification via the 365-day rule.
|
|
3711
|
+
* @returns `{ event, remainingLot }`; `remainingLot` is `null` when the whole lot is sold.
|
|
3712
|
+
* @throws {RangeError} if `qty <= 0` or `qty > lot.quantity`.
|
|
3713
|
+
*/
|
|
3714
|
+
declare function realize(lot: Lot, qty: number, salePrice: number, asOf: Date): RealizeResult;
|
|
3715
|
+
|
|
3716
|
+
/** A slice of a tax lot consumed to fulfill part of a sell order. */
|
|
3717
|
+
type LotSlice = {
|
|
3718
|
+
lotId: string;
|
|
3719
|
+
quantity: number;
|
|
3720
|
+
};
|
|
3721
|
+
/** Short-term and long-term capital-gains tax rates (as decimals, e.g. 0.37). */
|
|
3722
|
+
type TaxRates = {
|
|
3723
|
+
shortTerm: number;
|
|
3724
|
+
longTerm: number;
|
|
3725
|
+
};
|
|
3726
|
+
/**
|
|
3727
|
+
* First-In-First-Out lot selection.
|
|
3728
|
+
*
|
|
3729
|
+
* Selects lots in ascending `openDate` order, consuming oldest lots first.
|
|
3730
|
+
*/
|
|
3731
|
+
declare function selectFIFO(lots: readonly Lot[], qty: number): LotSlice[];
|
|
3732
|
+
/**
|
|
3733
|
+
* Last-In-First-Out lot selection.
|
|
3734
|
+
*
|
|
3735
|
+
* Selects lots in descending `openDate` order, consuming newest lots first.
|
|
3736
|
+
*/
|
|
3737
|
+
declare function selectLIFO(lots: readonly Lot[], qty: number): LotSlice[];
|
|
3738
|
+
/**
|
|
3739
|
+
* Highest-In-First-Out lot selection.
|
|
3740
|
+
*
|
|
3741
|
+
* Selects lots in descending per-share basis (`basis / quantity`) order,
|
|
3742
|
+
* realizing the highest-cost lots first to minimize gains.
|
|
3743
|
+
*/
|
|
3744
|
+
declare function selectHIFO(lots: readonly Lot[], qty: number): LotSlice[];
|
|
3745
|
+
/**
|
|
3746
|
+
* Tax-minimizing lot selection.
|
|
3747
|
+
*
|
|
3748
|
+
* Ranks lots by a 4-tier comparator designed to realize the least tax:
|
|
3749
|
+
* 1. Long-term losses (tier 0) — offsets LT gains at the lower LT rate
|
|
3750
|
+
* 2. Short-term losses (tier 1) — offsets ST gains at the higher ST rate
|
|
3751
|
+
* 3. Long-term gains (tier 2) — taxed at the lower LT rate
|
|
3752
|
+
* 4. Short-term gains (tier 3) — taxed at the higher ST rate
|
|
3753
|
+
*
|
|
3754
|
+
* Within a tier, lots are sorted by ascending gain-per-share so that the
|
|
3755
|
+
* largest losses (or smallest gains) are consumed first.
|
|
3756
|
+
*
|
|
3757
|
+
* Uses `isLongTerm(holdingPeriodDays(lot, ctx.asOf))` for term classification
|
|
3758
|
+
* and `ctx.price - lot.basis / lot.quantity` for gain-per-share.
|
|
3759
|
+
*
|
|
3760
|
+
* `ctx.rates` is accepted for forward-compatibility and signature stability
|
|
3761
|
+
* (the executor's min-tax `lotMethod` passes it through); the current 4-tier
|
|
3762
|
+
* ranking does not read the rate magnitudes.
|
|
3763
|
+
*
|
|
3764
|
+
* NOTE: this is a conservative, IRS-aligned *ordering* heuristic, not a literal
|
|
3765
|
+
* rate-weighted per-share tax minimum. The two can diverge: a $100/share LT gain
|
|
3766
|
+
* (tier 2, $20 tax at a 20% LT rate) is selected before a $50/share ST gain
|
|
3767
|
+
* (tier 3, $18.50 tax at a 37% ST rate), even though the ST lot realizes less
|
|
3768
|
+
* tax. The tier order favors the lower-rate bucket and sidesteps marginal-bracket
|
|
3769
|
+
* complexity; it does not compute `gain × rate` per lot.
|
|
3770
|
+
*/
|
|
3771
|
+
declare function selectMinTax(lots: readonly Lot[], qty: number, ctx: {
|
|
3772
|
+
price: number;
|
|
3773
|
+
asOf: Date;
|
|
3774
|
+
rates: TaxRates;
|
|
3775
|
+
}): LotSlice[];
|
|
3776
|
+
|
|
3777
|
+
/**
|
|
3778
|
+
* Maximum capital-loss deduction against ordinary income per IRS §1211(b).
|
|
3779
|
+
* In a given tax year, net capital losses above `ORDINARY_OFFSET_CAP` are
|
|
3780
|
+
* carried forward to future years rather than deducted immediately.
|
|
3781
|
+
*/
|
|
3782
|
+
declare const ORDINARY_OFFSET_CAP = 3000;
|
|
3783
|
+
/**
|
|
3784
|
+
* Year-level summary of taxable income across all categories.
|
|
3785
|
+
*
|
|
3786
|
+
* - `shortTermGains` / `longTermGains`: sum of positive `gain` values from
|
|
3787
|
+
* capital-gain events in each term bucket.
|
|
3788
|
+
* - `shortTermLosses` / `longTermLosses`: sum of |negative `gain`| values
|
|
3789
|
+
* (stored as **positive magnitudes**) from capital-gain events.
|
|
3790
|
+
* - `qualifiedDividends`: qualified dividend income (taxed at LT rate).
|
|
3791
|
+
* - `ordinaryDividends`: non-qualified dividend income (taxed at ST rate).
|
|
3792
|
+
* - `interestIncome`: interest income (taxed at ST rate).
|
|
3793
|
+
*
|
|
3794
|
+
* Capital losses **never** offset `qualifiedDividends` or `ordinaryDividends`.
|
|
3795
|
+
* The cross-offset logic in {@link crossOffset} operates only on the capital-
|
|
3796
|
+
* gain buckets; dividend/interest income is added post-offset at full value.
|
|
3797
|
+
*/
|
|
3798
|
+
type TaxableIncome = {
|
|
3799
|
+
shortTermGains: number;
|
|
3800
|
+
/** Positive magnitude of short-term capital losses. */
|
|
3801
|
+
shortTermLosses: number;
|
|
3802
|
+
longTermGains: number;
|
|
3803
|
+
/** Positive magnitude of long-term capital losses. */
|
|
3804
|
+
longTermLosses: number;
|
|
3805
|
+
qualifiedDividends: number;
|
|
3806
|
+
ordinaryDividends: number;
|
|
3807
|
+
interestIncome: number;
|
|
3808
|
+
};
|
|
3809
|
+
/**
|
|
3810
|
+
* Partitions `events` into short-term and long-term capital-gain buckets.
|
|
3811
|
+
*
|
|
3812
|
+
* Events with `incomeKind !== 'capital-gain'` (dividends, interest) are
|
|
3813
|
+
* excluded entirely — they are not subject to the capital-gain offset logic.
|
|
3814
|
+
*
|
|
3815
|
+
* @param events - Flat array of {@link RealizedEvent}s for a single year or
|
|
3816
|
+
* for the full history (caller selects the relevant slice).
|
|
3817
|
+
* @returns `{ short, long }` — two arrays of capital-gain events by term.
|
|
3818
|
+
*/
|
|
3819
|
+
declare function bucketByTerm(events: readonly RealizedEvent[]): {
|
|
3820
|
+
short: RealizedEvent[];
|
|
3821
|
+
long: RealizedEvent[];
|
|
3822
|
+
};
|
|
3823
|
+
/**
|
|
3824
|
+
* Nets gains and losses within a single bucket (all-short or all-long).
|
|
3825
|
+
*
|
|
3826
|
+
* Events with `gain >= 0` contribute to `gains`; events with `gain < 0`
|
|
3827
|
+
* contribute to `losses` as a **positive magnitude**.
|
|
3828
|
+
*
|
|
3829
|
+
* @param events - Capital-gain events for one term bucket.
|
|
3830
|
+
* @returns `{ gains, losses, net }` where `net = gains - losses`.
|
|
3831
|
+
*/
|
|
3832
|
+
declare function netWithinBucket(events: readonly RealizedEvent[]): {
|
|
3833
|
+
gains: number;
|
|
3834
|
+
losses: number;
|
|
3835
|
+
net: number;
|
|
3836
|
+
};
|
|
3837
|
+
/**
|
|
3838
|
+
* Applies IRS capital-gain cross-offset rules between short-term and long-term nets.
|
|
3839
|
+
*
|
|
3840
|
+
* Rules (in order of precedence):
|
|
3841
|
+
* 1. **Both non-negative**: no offset; return each net unchanged.
|
|
3842
|
+
* 2. **Both negative**: combine losses; apply up to `ORDINARY_OFFSET_CAP` ($3,000)
|
|
3843
|
+
* against ordinary income; remainder becomes `carryForward`.
|
|
3844
|
+
* 3. **Opposite signs, combined ≥ 0**: the loss bucket fully absorbs into the gain
|
|
3845
|
+
* bucket; the residual stays in the gain bucket's term (`taxableShort` if
|
|
3846
|
+
* `netShort > 0`, else `taxableLong`). No ordinary offset or carry-forward.
|
|
3847
|
+
* 4. **Opposite signs, combined < 0**: net loss after cross-offset;
|
|
3848
|
+
* up to `ORDINARY_OFFSET_CAP` deducted against ordinary income; remainder
|
|
3849
|
+
* becomes `carryForward`.
|
|
3850
|
+
*
|
|
3851
|
+
* **Important:** `ordinaryOffset` and `carryForward` apply only to capital
|
|
3852
|
+
* losses. Dividend and interest income is never offset by capital losses.
|
|
3853
|
+
*
|
|
3854
|
+
* @param netShort - Net short-term capital gain (negative = loss).
|
|
3855
|
+
* @param netLong - Net long-term capital gain (negative = loss).
|
|
3856
|
+
* @returns `{ taxableShort, taxableLong, ordinaryOffset, carryForward }`.
|
|
3857
|
+
*/
|
|
3858
|
+
declare function crossOffset(netShort: number, netLong: number): {
|
|
3859
|
+
taxableShort: number;
|
|
3860
|
+
taxableLong: number;
|
|
3861
|
+
ordinaryOffset: number;
|
|
3862
|
+
carryForward: number;
|
|
3863
|
+
};
|
|
3864
|
+
/**
|
|
3865
|
+
* Aggregates {@link RealizedEvent}s by UTC calendar year into a
|
|
3866
|
+
* {@link TaxableIncome} map.
|
|
3867
|
+
*
|
|
3868
|
+
* Keyed by `closeDate.getUTCFullYear()`. Each event is routed:
|
|
3869
|
+
* - `capital-gain`: bucketed into `shortTermGains`/`shortTermLosses` (ST) or
|
|
3870
|
+
* `longTermGains`/`longTermLosses` (LT) by `termType` and sign of `gain`.
|
|
3871
|
+
* Losses are stored as **positive magnitudes**.
|
|
3872
|
+
* - `qualified-dividend`: adds `proceeds` to `qualifiedDividends`.
|
|
3873
|
+
* - `ordinary-dividend`: adds `proceeds` to `ordinaryDividends`.
|
|
3874
|
+
* - `interest`: adds `proceeds` to `interestIncome`.
|
|
3875
|
+
*
|
|
3876
|
+
* Year boundaries use **UTC**. Backtests are unambiguous (daily bars are
|
|
3877
|
+
* UTC-midnight-anchored). Live-mode callers should normalize `closeDate` to the
|
|
3878
|
+
* tax jurisdiction's local time before passing events here if they need
|
|
3879
|
+
* calendar-year precision around year-end — e.g. a US fill on Dec 31 evening
|
|
3880
|
+
* Eastern has a UTC `closeDate` of Jan 1, which belongs to the *prior* US tax
|
|
3881
|
+
* year but would otherwise be counted in the next year.
|
|
3882
|
+
*
|
|
3883
|
+
* @param events - Full sequence of realized events (multiple years OK).
|
|
3884
|
+
* @returns `Map<year, TaxableIncome>` with one entry per UTC calendar year.
|
|
3885
|
+
*/
|
|
3886
|
+
declare function aggregateByYear(events: readonly RealizedEvent[]): Map<number, TaxableIncome>;
|
|
3887
|
+
/**
|
|
3888
|
+
* Computes the tax bill for a single year's {@link TaxableIncome}.
|
|
3889
|
+
*
|
|
3890
|
+
* Steps:
|
|
3891
|
+
* 1. Net each capital-gain bucket: `netShort = shortTermGains - shortTermLosses`,
|
|
3892
|
+
* `netLong = longTermGains - longTermLosses`.
|
|
3893
|
+
* 2. Apply {@link crossOffset} to get `taxableShort`, `taxableLong`,
|
|
3894
|
+
* `ordinaryOffset`, and `carryForward`.
|
|
3895
|
+
* 3. `ordinaryPortion = (taxableShort + ordinaryDividends + interestIncome) * shortTerm`.
|
|
3896
|
+
* 4. `ltPortion = (taxableLong + qualifiedDividends) * longTerm`.
|
|
3897
|
+
* 5. `total = ordinaryPortion + ltPortion`.
|
|
3898
|
+
*
|
|
3899
|
+
* **Critical invariant:** capital losses do **not** offset `qualifiedDividends`.
|
|
3900
|
+
* Qualified dividends are added to the LT pool *after* cross-offset, at their
|
|
3901
|
+
* full value, so a LT capital loss that wipes out `taxableLong` to zero still
|
|
3902
|
+
* leaves the qualified dividend income fully taxable at the LT rate.
|
|
3903
|
+
*
|
|
3904
|
+
* `carryForward` is surfaced as a return field for the caller to track across
|
|
3905
|
+
* years; this function does **not** consume carry-forward from prior years
|
|
3906
|
+
* (cross-year carry is V3 work).
|
|
3907
|
+
*
|
|
3908
|
+
* Note: the `ordinaryOffset` produced by {@link crossOffset} (the up-to-$3,000
|
|
3909
|
+
* §1211(b) capital-loss deduction against ordinary income) is intentionally not
|
|
3910
|
+
* surfaced here. This function models only the tax on capital income; that
|
|
3911
|
+
* deduction applies against wage/business income outside this module's scope.
|
|
3912
|
+
*
|
|
3913
|
+
* @param income - Year-level taxable income, as produced by {@link aggregateByYear}.
|
|
3914
|
+
* @param rates - `{ shortTerm, longTerm }` tax rates as decimals (e.g. `0.37`).
|
|
3915
|
+
* @returns `{ total, breakdown: { ordinaryPortion, ltPortion, carryForward } }`.
|
|
3916
|
+
*/
|
|
3917
|
+
declare function computeTaxBill(income: TaxableIncome, rates: TaxRates): {
|
|
3918
|
+
total: number;
|
|
3919
|
+
breakdown: {
|
|
3920
|
+
ordinaryPortion: number;
|
|
3921
|
+
ltPortion: number;
|
|
3922
|
+
carryForward: number;
|
|
3923
|
+
};
|
|
3924
|
+
};
|
|
3925
|
+
|
|
3926
|
+
type index_LotSlice = LotSlice;
|
|
3927
|
+
declare const index_ORDINARY_OFFSET_CAP: typeof ORDINARY_OFFSET_CAP;
|
|
3928
|
+
type index_RealizeResult = RealizeResult;
|
|
3929
|
+
type index_TaxRates = TaxRates;
|
|
3930
|
+
type index_TaxableIncome = TaxableIncome;
|
|
3931
|
+
declare const index_aggregateByYear: typeof aggregateByYear;
|
|
3932
|
+
declare const index_bucketByTerm: typeof bucketByTerm;
|
|
3933
|
+
declare const index_computeTaxBill: typeof computeTaxBill;
|
|
3934
|
+
declare const index_crossOffset: typeof crossOffset;
|
|
3935
|
+
declare const index_holdingPeriodDays: typeof holdingPeriodDays;
|
|
3936
|
+
declare const index_isLongTerm: typeof isLongTerm;
|
|
3937
|
+
declare const index_netWithinBucket: typeof netWithinBucket;
|
|
3938
|
+
declare const index_realize: typeof realize;
|
|
3939
|
+
declare const index_selectFIFO: typeof selectFIFO;
|
|
3940
|
+
declare const index_selectHIFO: typeof selectHIFO;
|
|
3941
|
+
declare const index_selectLIFO: typeof selectLIFO;
|
|
3942
|
+
declare const index_selectMinTax: typeof selectMinTax;
|
|
3598
3943
|
declare namespace index {
|
|
3599
|
-
export { type
|
|
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 };
|
|
3600
3945
|
}
|
|
3601
3946
|
|
|
3602
3947
|
/**
|
|
@@ -3712,4 +4057,4 @@ declare function applyOrders(portfolio: Portfolio, orders: ReadonlyArray<Order>)
|
|
|
3712
4057
|
*/
|
|
3713
4058
|
declare function positionsByAsset(portfolio: Portfolio): Position[];
|
|
3714
4059
|
|
|
3715
|
-
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 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 MacroAsset, MemoryFeatureCache, NYSEExchangeCalendar, type NextOpenFn, type OpenOrder, type Order, type PollingSchedule, type PollingStreamOptions, type Portfolio, type Position, type PositionId, type PriceMap, type Quote, type QuoteFeed, 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 TimeOfDay, type Tolerance, type WithStreamingSyntheticsOptions, applyFills, applyOrders, barsToSeries, collectBars, defineFeature, drawdown, ema, evaluateFeatureSpecs, evaluateRuleTree, index as features, fromSpec, getCalendar, getFeatureCompute, isRebalanceDay, paramsHash, periodKey, pollingStreamFromHistorical, positionsByAsset, reconcile, returnSeries, rsi, runBacktest, runLive, seriesAt, sma, index$
|
|
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 };
|