@wicklib/pro 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +3 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -15
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -46,7 +46,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
46
46
|
// package.json
|
|
47
47
|
var package_default = {
|
|
48
48
|
name: "@wicklib/pro",
|
|
49
|
-
version: "0.
|
|
49
|
+
version: "0.13.0",
|
|
50
50
|
description: "Wicklib commercial add-on",
|
|
51
51
|
license: "SEE LICENSE IN LICENSE",
|
|
52
52
|
type: "module",
|
|
@@ -83,7 +83,7 @@ var package_default = {
|
|
|
83
83
|
directory: "packages/pro"
|
|
84
84
|
},
|
|
85
85
|
peerDependencies: {
|
|
86
|
-
"@wicklib/core": "^0.
|
|
86
|
+
"@wicklib/core": "^0.13.0"
|
|
87
87
|
},
|
|
88
88
|
scripts: {
|
|
89
89
|
build: "tsup",
|
|
@@ -814,8 +814,6 @@ function clamp(value, min, max) {
|
|
|
814
814
|
var PRO_FEATURES = [
|
|
815
815
|
"orderflow",
|
|
816
816
|
"volume-profile",
|
|
817
|
-
"panes",
|
|
818
|
-
"layouts",
|
|
819
817
|
"strategy",
|
|
820
818
|
"alerts",
|
|
821
819
|
"script-functions"
|
|
@@ -826,22 +824,12 @@ var PRO_CORE_FEATURES = PRO_FEATURES;
|
|
|
826
824
|
var NAMES = {
|
|
827
825
|
orderflow: "Orderflow",
|
|
828
826
|
"volume-profile": "Volume Profile",
|
|
829
|
-
panes: "Panes",
|
|
830
|
-
layouts: "Layouts",
|
|
831
827
|
strategy: "Strategy",
|
|
832
828
|
alerts: "Alerts",
|
|
833
829
|
"script-functions": "Script Functions"
|
|
834
830
|
};
|
|
835
831
|
var PRO_EXTENSIONS = Object.freeze(
|
|
836
|
-
[
|
|
837
|
-
"orderflow",
|
|
838
|
-
"volume-profile",
|
|
839
|
-
"panes",
|
|
840
|
-
"layouts",
|
|
841
|
-
"strategy",
|
|
842
|
-
"alerts",
|
|
843
|
-
"script-functions"
|
|
844
|
-
].map(
|
|
832
|
+
["orderflow", "volume-profile", "strategy", "alerts", "script-functions"].map(
|
|
845
833
|
(feature) => Object.freeze({
|
|
846
834
|
kind: "feature",
|
|
847
835
|
feature,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../package.json","../src/version.ts","../src/script/backtest.ts","../src/strategy/backtest.ts","../src/alerts/engine.ts","../src/analytics/absorption.ts","../src/analytics/depth.ts","../src/analytics/orderflow.ts","../src/analytics/volume-profile.ts","../src/analytics/volume-profile-overlay.ts","../src/features.ts","../src/extensions.ts","../src/license/verify.ts"],"sourcesContent":["/**\n * Wicklib Pro public API.\n *\n * The package is published to npm under the Wicklib Commercial License; its source\n * repository is private.\n */\n\nexport { PRO_VERSION } from \"./version\";\nexport { runScriptBacktest } from \"./script/backtest\";\nexport type {\n CompiledScriptLike,\n ScriptAlertEvent,\n ScriptBacktestOptions,\n ScriptBacktestResult,\n ScriptRunResult,\n} from \"./script/backtest\";\nexport { runBacktest } from \"./strategy/backtest\";\nexport type {\n BacktestFill,\n BacktestOptions,\n BacktestResult,\n EquityPoint,\n StrategyContext,\n StrategyFunction,\n StrategyTarget,\n} from \"./strategy/backtest\";\nexport { AlertEngine, evaluateAlerts } from \"./alerts/engine\";\nexport type {\n AlertDirection,\n AlertPriceSource,\n AlertTrigger,\n PriceAlertRule,\n} from \"./alerts/engine\";\nexport { detectAbsorption } from \"./analytics/absorption\";\nexport type { AbsorptionEvent, AbsorptionOptions } from \"./analytics/absorption\";\nexport { DepthAggregator, computeDepth } from \"./analytics/depth\";\nexport type {\n DepthBar,\n DepthLevel,\n DepthLevelBar,\n DepthOptions,\n DepthSnapshot,\n} from \"./analytics/depth\";\nexport { FootprintAggregator, computeFootprint } from \"./analytics/orderflow\";\nexport type {\n FootprintBar,\n FootprintLevel,\n FootprintOptions,\n TradeSide,\n TradeTick,\n} from \"./analytics/orderflow\";\nexport { addVolumeProfileOverlay } from \"./analytics/volume-profile-overlay\";\nexport type {\n VolumeProfileOverlay,\n VolumeProfileOverlayColors,\n VolumeProfileOverlayOptions,\n} from \"./analytics/volume-profile-overlay\";\nexport { computeVolumeProfile } from \"./analytics/volume-profile\";\nexport type {\n VolumeProfile,\n VolumeProfileBin,\n VolumeProfileDistribution,\n VolumeProfileOptions,\n} from \"./analytics/volume-profile\";\nexport { PRO_CORE_FEATURES, PRO_FEATURES } from \"./features\";\nexport type { ProFeature } from \"./features\";\nexport * from \"./extensions\";\nexport * from \"./license/verify\";\n\nimport { assertFeature, type Feature, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Returns true when the active license grants a pro feature.\n */\nexport function hasProFeature(context: LicenseContext, feature: Feature): boolean {\n return context.hasFeature(feature);\n}\n\n/**\n * Throws `WickError(\"LICENSE_REQUIRED\")` when a pro feature is not granted.\n */\nexport function assertProFeature(context: LicenseContext, feature: Feature): void {\n assertFeature(context, feature);\n}\n","{\n \"name\": \"@wicklib/pro\",\n \"version\": \"0.11.0\",\n \"description\": \"Wicklib commercial add-on\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"type\": \"module\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/wicklib/wicklib-pro.git\",\n \"directory\": \"packages/pro\"\n },\n \"peerDependencies\": {\n \"@wicklib/core\": \"^0.11.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"devDependencies\": {\n \"tsup\": \"^9.0.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^5.0.5\"\n }\n}\n","import packageJson from \"../package.json\";\n\n/**\n * Semantic version of the installed pro package.\n */\nexport const PRO_VERSION: string = packageJson.version;\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\nimport {\n runBacktest,\n type BacktestOptions,\n type BacktestResult,\n type StrategyTarget,\n} from \"../strategy/backtest\";\n\n/**\n * One alert emitted by a script, including the bar it belongs to.\n */\nexport interface ScriptAlertEvent {\n time: number;\n barIndex: number;\n message: string;\n}\n\n/**\n * Output required from a compiled script replay.\n *\n * This is structurally compatible with `@wicklib/script`'s `CompiledScript`, without making\n * Pro depend on the script package at runtime.\n */\nexport interface ScriptRunResult {\n plots: Readonly<Record<string, ReadonlyArray<number | null>>>;\n alerts: ReadonlyArray<string>;\n alertEvents?: ReadonlyArray<ScriptAlertEvent>;\n}\n\n/**\n * Minimal compiled-script contract accepted by the adapter.\n */\nexport interface CompiledScriptLike {\n replay(bars: readonly OhlcData[]): Promise<ScriptRunResult>;\n}\n\n/**\n * Options for a script-driven backtest.\n */\nexport interface ScriptBacktestOptions extends BacktestOptions {\n /** Plot id whose values are target positions: -1 short, 0 flat, 1 long, null hold. */\n signalPlot: string;\n}\n\n/**\n * Backtest result plus script alerts.\n */\nexport interface ScriptBacktestResult extends BacktestResult {\n alerts: readonly ScriptAlertEvent[];\n}\n\n/**\n * Runs a compiled script, maps one plot to target positions, and backtests the result.\n *\n * The script must emit positions on the configured plot. Alerts are returned with their\n * source bar so the host can deliver or persist them. Requires the `strategy` feature.\n */\nexport async function runScriptBacktest(\n context: LicenseContext,\n script: CompiledScriptLike,\n bars: readonly OhlcData[],\n options: ScriptBacktestOptions,\n): Promise<ScriptBacktestResult> {\n assertFeature(context, \"strategy\");\n\n if (!script || typeof script.replay !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script adapter requires a replay function\");\n }\n if (typeof options.signalPlot !== \"string\" || options.signalPlot.trim() === \"\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script signalPlot must be a non-empty string\");\n }\n\n const result = await script.replay(bars);\n const values = result?.plots?.[options.signalPlot];\n if (!Array.isArray(values)) {\n throw new WickError(\"INVALID_DATA\", `Script plot not found: ${options.signalPlot}`);\n }\n if (values.length !== bars.length) {\n throw new WickError(\"INVALID_DATA\", \"Script signal plot length must match the bar count\");\n }\n if (result.alerts.length > 0 && !result.alertEvents) {\n throw new WickError(\"INVALID_DATA\", \"Script alerts are missing their bar events\");\n }\n\n const alerts = (result.alertEvents ?? []).map((event) => validateAlert(event));\n const backtest = runBacktest(\n context,\n bars,\n ({ index }): StrategyTarget | undefined => {\n const value = values[index];\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value !== -1 && value !== 0 && value !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Script signal must be -1, 0, 1, or null\");\n }\n return value;\n },\n options,\n );\n\n return { ...backtest, alerts };\n}\n\nfunction validateAlert(event: ScriptAlertEvent): ScriptAlertEvent {\n if (\n !event ||\n !Number.isFinite(event.time) ||\n !Number.isInteger(event.barIndex) ||\n event.barIndex < 0 ||\n typeof event.message !== \"string\"\n ) {\n throw new WickError(\"INVALID_DATA\", \"Invalid script alert event\");\n }\n return { time: event.time, barIndex: event.barIndex, message: event.message };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Target position for a strategy.\n *\n * -1 = fully short\n * 0 = flat\n * 1 = fully long\n */\nexport type StrategyTarget = -1 | 0 | 1;\n\n/**\n * Context passed to a strategy once per closed bar.\n */\nexport interface StrategyContext {\n readonly bar: OhlcData;\n readonly index: number;\n readonly position: StrategyTarget;\n readonly cash: number;\n readonly units: number;\n readonly equity: number;\n}\n\n/**\n * Strategy callback. Return a target to schedule a fill at the next bar open, or\n * `undefined`/`null` to hold the current target.\n */\nexport type StrategyFunction = (context: StrategyContext) => StrategyTarget | null | undefined;\n\n/**\n * Backtest configuration.\n */\nexport interface BacktestOptions {\n /** Starting cash. Required and positive. */\n initialCapital: number;\n /** Fractional fee charged on absolute traded notional. Defaults to 0. */\n feeRate?: number;\n /** Fractional slippage applied against the fill. Defaults to 0. */\n slippage?: number;\n}\n\n/**\n * One executed target change.\n */\nexport interface BacktestFill {\n time: number;\n side: \"buy\" | \"sell\";\n price: number;\n quantity: number;\n fee: number;\n}\n\n/**\n * One marked-to-market equity point.\n */\nexport interface EquityPoint {\n time: number;\n cash: number;\n units: number;\n position: StrategyTarget;\n price: number;\n equity: number;\n}\n\n/**\n * Deterministic strategy backtest result.\n */\nexport interface BacktestResult {\n initialCapital: number;\n finalEquity: number;\n returnPercent: number;\n maxDrawdown: number;\n fills: readonly BacktestFill[];\n equity: readonly EquityPoint[];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<BacktestOptions, \"initialCapital\">> = {\n feeRate: 0,\n slippage: 0,\n};\n\n/**\n * Runs a target-position strategy against closed bars.\n *\n * Signals are evaluated on bar close and filled at the next bar open, preventing\n * lookahead. Position sizing is fully invested at the fill price; leverage is not added.\n * Requires the `strategy` license feature.\n */\nexport function runBacktest(\n context: LicenseContext,\n bars: readonly OhlcData[],\n strategy: StrategyFunction,\n options: BacktestOptions,\n): BacktestResult {\n assertFeature(context, \"strategy\");\n\n const initialCapital = options.initialCapital;\n const feeRate = options.feeRate ?? DEFAULT_OPTIONS.feeRate;\n const slippage = options.slippage ?? DEFAULT_OPTIONS.slippage;\n if (!Number.isFinite(initialCapital) || initialCapital <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest initialCapital must be positive\");\n }\n if (!Number.isFinite(feeRate) || feeRate < 0 || feeRate >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest feeRate must be in [0, 1)\");\n }\n if (!Number.isFinite(slippage) || slippage < 0 || slippage >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest slippage must be in [0, 1)\");\n }\n if (typeof strategy !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest strategy must be a function\");\n }\n\n let cash = initialCapital;\n let units = 0;\n let position: StrategyTarget = 0;\n let pending: StrategyTarget | null = null;\n let previousTime = Number.NEGATIVE_INFINITY;\n const fills: BacktestFill[] = [];\n const equity: EquityPoint[] = [];\n let peak = initialCapital;\n let maxDrawdown = 0;\n\n for (let index = 0; index < bars.length; index += 1) {\n const bar = bars[index]!;\n if (\n !Number.isFinite(bar.time) ||\n bar.time <= previousTime ||\n !Number.isFinite(bar.open) ||\n !Number.isFinite(bar.close) ||\n !Number.isFinite(bar.high) ||\n !Number.isFinite(bar.low)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Backtest bars require ascending finite OHLC values\");\n }\n previousTime = bar.time;\n\n if (pending !== null && pending !== position) {\n const side: \"buy\" | \"sell\" = pending > position ? \"buy\" : \"sell\";\n const price = side === \"buy\" ? bar.open * (1 + slippage) : bar.open * (1 - slippage);\n const equityAtFill = cash + units * price;\n const desiredUnits = (pending * equityAtFill) / price;\n const quantity = desiredUnits - units;\n const fee = Math.abs(quantity * price) * feeRate;\n cash -= quantity * price + fee;\n units = desiredUnits;\n position = pending;\n if (quantity !== 0) {\n fills.push({ time: bar.time, side, price, quantity, fee });\n }\n pending = null;\n }\n\n const markedEquity = cash + units * bar.close;\n peak = Math.max(peak, markedEquity);\n if (peak > 0) {\n maxDrawdown = Math.max(maxDrawdown, (peak - markedEquity) / peak);\n }\n equity.push({\n time: bar.time,\n cash,\n units,\n position,\n price: bar.close,\n equity: markedEquity,\n });\n\n const signal = strategy({\n bar,\n index,\n position,\n cash,\n units,\n equity: markedEquity,\n });\n if (signal !== undefined && signal !== null) {\n if (signal !== -1 && signal !== 0 && signal !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Strategy target must be -1, 0, or 1\");\n }\n pending = signal;\n }\n }\n\n const finalEquity = equity.at(-1)?.equity ?? initialCapital;\n return {\n initialCapital,\n finalEquity,\n returnPercent: ((finalEquity - initialCapital) / initialCapital) * 100,\n maxDrawdown,\n fills,\n equity,\n };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Price field used by a price alert.\n */\nexport type AlertPriceSource = \"close\" | \"high\" | \"low\";\n\n/**\n * Price alert direction.\n *\n * `cross` reports the side that was crossed.\n */\nexport type AlertDirection = \"above\" | \"below\" | \"cross\";\n\n/**\n * A serializable price alert rule.\n */\nexport interface PriceAlertRule {\n readonly id: string;\n readonly price: number;\n readonly direction: AlertDirection;\n /** Defaults to close. */\n readonly source?: AlertPriceSource;\n}\n\n/**\n * A triggered alert.\n */\nexport interface AlertTrigger {\n readonly ruleId: string;\n readonly time: number;\n readonly direction: \"above\" | \"below\";\n readonly price: number;\n readonly value: number;\n readonly bar: OhlcData;\n}\n\nconst SOURCES = new Set<AlertPriceSource>([\"close\", \"high\", \"low\"]);\n\n/**\n * Deterministic, offline alert evaluator for streaming bars.\n *\n * The first bar initializes state and never triggers. Subsequent bars trigger only on a\n * transition so a rule does not fire repeatedly while it remains true.\n */\nexport class AlertEngine {\n private readonly rules: readonly PriceAlertRule[];\n private readonly previous = new Map<string, number>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, rules: readonly PriceAlertRule[]) {\n assertFeature(context, \"alerts\");\n const ids = new Set<string>();\n for (const rule of rules) {\n if (\n !rule ||\n typeof rule.id !== \"string\" ||\n rule.id.trim() === \"\" ||\n !Number.isFinite(rule.price) ||\n (rule.direction !== \"above\" && rule.direction !== \"below\" && rule.direction !== \"cross\") ||\n (rule.source !== undefined && !SOURCES.has(rule.source))\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Invalid price alert rule\");\n }\n if (ids.has(rule.id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Duplicate alert rule id: ${rule.id}`);\n }\n ids.add(rule.id);\n }\n this.rules = rules.map((rule) => ({ ...rule }));\n }\n\n /**\n * Consumes one closed bar and returns the alerts triggered by that bar.\n */\n update(bar: OhlcData): readonly AlertTrigger[] {\n if (!Number.isFinite(bar.time)) {\n throw new WickError(\"INVALID_DATA\", \"Alert bar requires a finite time\");\n }\n if (bar.time <= this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Alert bars must have increasing times\");\n }\n this.lastTime = bar.time;\n\n const triggers: AlertTrigger[] = [];\n for (const rule of this.rules) {\n const source = rule.source ?? \"close\";\n const value = source === \"close\" ? bar.close : source === \"high\" ? bar.high : bar.low;\n const previous = this.previous.get(rule.id);\n if (previous !== undefined) {\n if (rule.direction === \"above\" && previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (rule.direction === \"below\" && previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n } else if (rule.direction === \"cross\") {\n if (previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n }\n }\n }\n this.previous.set(rule.id, value);\n }\n\n return triggers;\n }\n\n /**\n * Clears previous values so the next bar initializes state again.\n */\n reset(): void {\n this.previous.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Evaluates a batch of closed bars through the same streaming alert path.\n */\nexport function evaluateAlerts(\n context: LicenseContext,\n rules: readonly PriceAlertRule[],\n bars: readonly OhlcData[],\n): readonly AlertTrigger[] {\n const engine = new AlertEngine(context, rules);\n const triggers: AlertTrigger[] = [];\n for (const bar of bars) {\n triggers.push(...engine.update(bar));\n }\n return triggers;\n}\n\nfunction trigger(\n rule: PriceAlertRule,\n bar: OhlcData,\n value: number,\n direction: \"above\" | \"below\",\n): AlertTrigger {\n return {\n ruleId: rule.id,\n time: bar.time,\n direction,\n price: rule.price,\n value,\n bar,\n };\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\nimport { DepthAggregator, type DepthSnapshot } from \"./depth\";\nimport { FootprintAggregator, type TradeTick, type TradeSide } from \"./orderflow\";\n\n/**\n * Options for absorption detection.\n */\nexport interface AbsorptionOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Aggressive volume must reach passive size × this ratio. Defaults to 2. */\n absorptionRatio?: number;\n}\n\n/**\n * A detected absorption event.\n */\nexport interface AbsorptionEvent {\n /** Bucket start time in milliseconds. */\n time: number;\n priceLow: number;\n priceHigh: number;\n /** Aggressor side that was absorbed. */\n side: TradeSide;\n /** Aggressive trade volume in the bucket and level. */\n aggressiveVolume: number;\n /** Passive book size at the level when the bucket completed. */\n passiveVolume: number;\n /** aggressiveVolume / passiveVolume. */\n ratio: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_ABSORPTION_RATIO = 2;\n\n/**\n * Detects aggressive volume absorbed by passive L2 liquidity.\n *\n * For each footprint bucket and price level:\n * - aggressive buys are compared with ask depth\n * - aggressive sells are compared with bid depth\n *\n * A level is reported when aggressive volume is at least the configured multiple of the\n * passive size. Requires the `orderflow` license feature.\n */\nexport function detectAbsorption(\n context: LicenseContext,\n trades: readonly TradeTick[],\n snapshots: readonly DepthSnapshot[],\n options: AbsorptionOptions,\n): readonly AbsorptionEvent[] {\n assertFeature(context, \"orderflow\");\n\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const absorptionRatio = options.absorptionRatio ?? DEFAULT_ABSORPTION_RATIO;\n const priceStep = options.priceStep;\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption bucketMs must be a positive integer\");\n }\n if (!Number.isFinite(absorptionRatio) || absorptionRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption ratio must be at least 1\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption priceStep must be a positive number\");\n }\n\n const footprints = new FootprintAggregator(context, {\n bucketMs,\n priceStep,\n });\n for (const trade of [...trades].sort((first, second) => first.time - second.time)) {\n footprints.push(trade);\n }\n\n const depth = new DepthAggregator(context, { priceStep });\n for (const snapshot of [...snapshots].sort((first, second) => first.time - second.time)) {\n depth.push(snapshot);\n }\n\n const events: AbsorptionEvent[] = [];\n for (const bar of footprints.getBars()) {\n const book = depth.latest(bar.time + bucketMs - 1);\n if (!book) {\n continue;\n }\n const depthByPrice = new Map(book.levels.map((level) => [level.priceLow, level]));\n for (const level of bar.levels) {\n const depthLevel = depthByPrice.get(level.priceLow);\n if (!depthLevel) {\n continue;\n }\n const candidates: Array<{\n side: TradeSide;\n aggressive: number;\n passive: number;\n }> = [\n { side: \"buy\", aggressive: level.buyVolume, passive: depthLevel.askSize },\n { side: \"sell\", aggressive: level.sellVolume, passive: depthLevel.bidSize },\n ];\n for (const candidate of candidates) {\n if (candidate.passive <= 0 || candidate.aggressive <= 0) {\n continue;\n }\n const ratio = candidate.aggressive / candidate.passive;\n if (ratio >= absorptionRatio) {\n events.push({\n time: bar.time,\n priceLow: level.priceLow,\n priceHigh: level.priceHigh,\n side: candidate.side,\n aggressiveVolume: candidate.aggressive,\n passiveVolume: candidate.passive,\n ratio,\n });\n }\n }\n }\n }\n\n return events;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * One side of a Level-2 depth snapshot.\n */\nexport interface DepthLevel {\n price: number;\n size: number;\n}\n\n/**\n * A full bid/ask book snapshot at a point in time.\n */\nexport interface DepthSnapshot {\n /** Unix timestamp in milliseconds. */\n time: number;\n bids: readonly DepthLevel[];\n asks: readonly DepthLevel[];\n}\n\n/**\n * Aggregated bid/ask liquidity by price bucket.\n */\nexport interface DepthLevelBar {\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n}\n\n/**\n * Aggregated depth for one snapshot.\n */\nexport interface DepthBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n levels: readonly DepthLevelBar[];\n}\n\n/**\n * Options for depth aggregation.\n */\nexport interface DepthOptions {\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies total book pressure as imbalanced. Defaults to 2. */\n imbalanceRatio?: number;\n}\n\nconst DEFAULT_IMBALANCE_RATIO = 2;\n\n/**\n * Incremental L2 depth aggregator.\n *\n * Snapshots are complete books, so newer snapshots replace the current view rather than\n * accumulate. Non-decreasing timestamps are enforced.\n */\nexport class DepthAggregator {\n private readonly options: Required<DepthOptions>;\n private readonly bars = new Map<number, DepthBar>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: DepthOptions) {\n assertFeature(context, \"orderflow\");\n if (\n options.priceStep === undefined ||\n !Number.isFinite(options.priceStep) ||\n options.priceStep <= 0\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth priceStep must be a positive number\");\n }\n const ratio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n if (!Number.isFinite(ratio) || ratio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth imbalanceRatio must be at least 1\");\n }\n this.options = { priceStep: options.priceStep, imbalanceRatio: ratio };\n }\n\n /**\n * Adds or replaces one complete snapshot and returns its aggregated bar.\n */\n push(snapshot: DepthSnapshot): DepthBar {\n if (\n !Number.isFinite(snapshot.time) ||\n !Array.isArray(snapshot.bids) ||\n !Array.isArray(snapshot.asks)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots require finite time, bids, and asks\");\n }\n if (snapshot.time < this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots must be in non-decreasing time order\");\n }\n this.lastTime = snapshot.time;\n\n const levels = new Map<number, { bid: number; ask: number }>();\n for (const [side, entries] of [\n [\"bid\", snapshot.bids],\n [\"ask\", snapshot.asks],\n ] as const) {\n for (const entry of entries) {\n if (!Number.isFinite(entry.price) || !Number.isFinite(entry.size) || entry.size < 0) {\n throw new WickError(\n \"INVALID_DATA\",\n \"Depth levels require finite price and non-negative size\",\n );\n }\n const price = Math.floor(entry.price / this.options.priceStep) * this.options.priceStep;\n let level = levels.get(price);\n if (!level) {\n level = { bid: 0, ask: 0 };\n levels.set(price, level);\n }\n if (side === \"bid\") level.bid += entry.size;\n else level.ask += entry.size;\n }\n }\n\n let bidSize = 0;\n let askSize = 0;\n const sortedLevels: DepthLevelBar[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, level]) => {\n bidSize += level.bid;\n askSize += level.ask;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n bidSize: level.bid,\n askSize: level.ask,\n totalSize: level.bid + level.ask,\n delta: level.bid - level.ask,\n imbalance: imbalanceOf(level.bid, level.ask, this.options.imbalanceRatio),\n };\n });\n\n const bar: DepthBar = {\n time: snapshot.time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n bidSize,\n askSize,\n totalSize: bidSize + askSize,\n delta: bidSize - askSize,\n imbalance: imbalanceOf(bidSize, askSize, this.options.imbalanceRatio),\n levels: sortedLevels,\n };\n this.bars.set(snapshot.time, bar);\n return bar;\n }\n\n /**\n * Returns the latest snapshot at or before a time.\n */\n latest(time = Number.POSITIVE_INFINITY): DepthBar | null {\n const eligible = [...this.bars.values()]\n .filter((bar) => bar.time <= time)\n .sort((first, second) => first.time - second.time);\n return eligible.at(-1) ?? null;\n }\n\n /**\n * Returns all snapshots in ascending time order.\n */\n getBars(): readonly DepthBar[] {\n return [...this.bars.values()].sort((first, second) => first.time - second.time);\n }\n\n /**\n * Clears all snapshots and the streaming order guard.\n */\n reset(): void {\n this.bars.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Aggregates a batch of complete L2 book snapshots.\n *\n * Requires the `orderflow` license feature.\n */\nexport function computeDepth(\n context: LicenseContext,\n snapshots: readonly DepthSnapshot[],\n options: DepthOptions,\n): readonly DepthBar[] {\n const aggregator = new DepthAggregator(context, options);\n for (const snapshot of snapshots) {\n aggregator.push(snapshot);\n }\n return aggregator.getBars();\n}\n\nfunction imbalanceOf(bid: number, ask: number, ratio: number): \"bid\" | \"ask\" | null {\n if (bid === 0 && ask === 0) return null;\n if (ask === 0) return \"bid\";\n if (bid === 0) return \"ask\";\n if (bid >= ask * ratio) return \"bid\";\n if (ask >= bid * ratio) return \"ask\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Aggressor side of a trade tick.\n */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/**\n * Minimal trade tick accepted by the orderflow aggregator.\n */\nexport interface TradeTick {\n /** Unix timestamp in milliseconds. */\n time: number;\n price: number;\n size: number;\n side: TradeSide;\n}\n\n/**\n * Orderflow aggregation options.\n */\nexport interface FootprintOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies a level as imbalanced. Defaults to 3. */\n imbalanceRatio?: number;\n}\n\n/**\n * One price level in a footprint bar.\n */\nexport interface FootprintLevel {\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n imbalance: TradeSide | null;\n}\n\n/**\n * Aggregated footprint for one time bucket.\n */\nexport interface FootprintBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n levels: readonly FootprintLevel[];\n}\n\ninterface ResolvedOptions {\n bucketMs: number;\n priceStep: number;\n imbalanceRatio: number;\n}\n\ninterface LevelVolumes {\n buy: number;\n sell: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_IMBALANCE_RATIO = 3;\n\n/**\n * Incremental trade-tick footprint aggregator.\n *\n * Trades must arrive in non-decreasing time order. Ticks in the same bucket update the\n * same bar, so streaming and batch aggregation share the same code path.\n */\nexport class FootprintAggregator {\n private readonly options: ResolvedOptions;\n private readonly levels = new Map<number, Map<number, LevelVolumes>>();\n private lastTradeTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: FootprintOptions) {\n assertFeature(context, \"orderflow\");\n this.options = resolveOptions(options);\n }\n\n /**\n * Adds one trade and returns the updated bar for its time bucket.\n */\n push(trade: TradeTick): FootprintBar {\n this.validateTrade(trade);\n if (trade.time < this.lastTradeTime) {\n throw new WickError(\"INVALID_DATA\", \"Streaming trades must be in non-decreasing time order\");\n }\n this.lastTradeTime = trade.time;\n\n const time = Math.floor(trade.time / this.options.bucketMs) * this.options.bucketMs;\n const price = Math.floor(trade.price / this.options.priceStep) * this.options.priceStep;\n let levels = this.levels.get(time);\n if (!levels) {\n levels = new Map();\n this.levels.set(time, levels);\n }\n let level = levels.get(price);\n if (!level) {\n level = { buy: 0, sell: 0 };\n levels.set(price, level);\n }\n if (trade.side === \"buy\") level.buy += trade.size;\n else level.sell += trade.size;\n\n return this.buildBar(time)!;\n }\n\n /**\n * Adds multiple trades in input order.\n */\n pushMany(trades: readonly TradeTick[]): readonly FootprintBar[] {\n for (const trade of trades) {\n this.push(trade);\n }\n return this.getBars();\n }\n\n /**\n * Returns a bar by bucket start time, or any time inside that bucket.\n */\n getBar(time: number): FootprintBar | null {\n const bucket = Math.floor(time / this.options.bucketMs) * this.options.bucketMs;\n return this.buildBar(bucket);\n }\n\n /**\n * Returns all completed/current buckets in ascending time order.\n */\n getBars(): readonly FootprintBar[] {\n return [...this.levels.keys()]\n .sort((first, second) => first - second)\n .map((time) => this.buildBar(time))\n .filter((bar): bar is FootprintBar => bar !== null);\n }\n\n /**\n * Clears all trades and resets the streaming order guard.\n */\n reset(): void {\n this.levels.clear();\n this.lastTradeTime = Number.NEGATIVE_INFINITY;\n }\n\n private buildBar(time: number): FootprintBar | null {\n const levels = this.levels.get(time);\n if (!levels) {\n return null;\n }\n\n let buyVolume = 0;\n let sellVolume = 0;\n const sortedLevels: FootprintLevel[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, volumes]) => {\n buyVolume += volumes.buy;\n sellVolume += volumes.sell;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n buyVolume: volumes.buy,\n sellVolume: volumes.sell,\n totalVolume: volumes.buy + volumes.sell,\n delta: volumes.buy - volumes.sell,\n imbalance: imbalanceOf(volumes.buy, volumes.sell, this.options.imbalanceRatio),\n };\n });\n\n return {\n time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n buyVolume,\n sellVolume,\n totalVolume: buyVolume + sellVolume,\n delta: buyVolume - sellVolume,\n levels: sortedLevels,\n };\n }\n\n private validateTrade(trade: TradeTick): void {\n if (\n !Number.isFinite(trade.time) ||\n !Number.isFinite(trade.price) ||\n !Number.isFinite(trade.size) ||\n trade.size <= 0 ||\n trade.price < 0 ||\n (trade.side !== \"buy\" && trade.side !== \"sell\")\n ) {\n throw new WickError(\"INVALID_DATA\", \"Trade ticks require finite time, price, size, and side\");\n }\n }\n}\n\n/**\n * Aggregates trade ticks into bid/ask footprint bars with delta and imbalance.\n *\n * Requires the `orderflow` license feature. Trades are sorted by time before aggregation.\n */\nexport function computeFootprint(\n context: LicenseContext,\n trades: readonly TradeTick[],\n options: FootprintOptions,\n): readonly FootprintBar[] {\n const aggregator = new FootprintAggregator(context, options);\n return aggregator.pushMany([...trades].sort((first, second) => first.time - second.time));\n}\n\nfunction resolveOptions(options: FootprintOptions): ResolvedOptions {\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const priceStep = options.priceStep;\n const imbalanceRatio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint bucketMs must be a positive integer\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint priceStep must be a positive number\");\n }\n if (!Number.isFinite(imbalanceRatio) || imbalanceRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint imbalanceRatio must be at least 1\");\n }\n return { bucketMs, priceStep, imbalanceRatio };\n}\n\nfunction imbalanceOf(buy: number, sell: number, ratio: number): TradeSide | null {\n if (buy === 0 && sell === 0) return null;\n if (sell === 0) return \"buy\";\n if (buy === 0) return \"sell\";\n if (buy >= sell * ratio) return \"buy\";\n if (sell >= buy * ratio) return \"sell\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Volume distribution model.\n *\n * `uniform` spreads each bar's volume evenly across its price range. `close` assigns the\n * whole bar volume to the bin containing the close.\n */\nexport type VolumeProfileDistribution = \"uniform\" | \"close\";\n\n/**\n * Options for {@link computeVolumeProfile}.\n */\nexport interface VolumeProfileOptions {\n /** Number of equal-width price bins. Defaults to 24. */\n bins?: number;\n /** Fixed price range. Defaults to the bars' low/high span. */\n priceRange?: { min: number; max: number };\n /** Fraction of total volume covered by the value area. Defaults to 0.7. */\n valueArea?: number;\n /** Volume distribution model. Defaults to uniform. */\n distribution?: VolumeProfileDistribution;\n}\n\n/**\n * One price bucket in a volume profile.\n */\nexport interface VolumeProfileBin {\n index: number;\n priceLow: number;\n priceHigh: number;\n priceMid: number;\n volume: number;\n}\n\n/**\n * Computed volume profile.\n */\nexport interface VolumeProfile {\n bins: readonly VolumeProfileBin[];\n range: { min: number; max: number };\n totalVolume: number;\n /** Point of control, or null when there is no volume. */\n poc: VolumeProfileBin | null;\n valueArea: {\n low: number;\n high: number;\n volume: number;\n } | null;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<VolumeProfileOptions, \"priceRange\">> = {\n bins: 24,\n valueArea: 0.7,\n distribution: \"uniform\",\n};\n\n/**\n * Computes a deterministic volume profile from OHLCV bars.\n *\n * Requires the `volume-profile` license feature. Bars without a finite positive volume are\n * ignored. Throws `WickError(\"INVALID_DATA\")` when no usable volume remains.\n */\nexport function computeVolumeProfile(\n context: LicenseContext,\n bars: readonly OhlcData[],\n options: VolumeProfileOptions = {},\n): VolumeProfile {\n assertFeature(context, \"volume-profile\");\n\n const binCount = options.bins ?? DEFAULT_OPTIONS.bins;\n const valueAreaFraction = options.valueArea ?? DEFAULT_OPTIONS.valueArea;\n const distribution = options.distribution ?? DEFAULT_OPTIONS.distribution;\n\n if (!Number.isInteger(binCount) || binCount <= 0 || binCount > 2_000) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile bins must be between 1 and 2000\");\n }\n if (!Number.isFinite(valueAreaFraction) || valueAreaFraction <= 0 || valueAreaFraction > 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile valueArea must be in (0, 1]\");\n }\n\n let min: number;\n let max: number;\n if (options.priceRange) {\n min = options.priceRange.min;\n max = options.priceRange.max;\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile priceRange must have max > min\");\n }\n } else {\n min = Number.POSITIVE_INFINITY;\n max = Number.NEGATIVE_INFINITY;\n for (const bar of bars) {\n if (!Number.isFinite(bar.volume) || bar.volume! <= 0) continue;\n min = Math.min(min, bar.low);\n max = Math.max(max, bar.high);\n }\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n if (max <= min) {\n max = min + 1;\n }\n }\n\n const width = (max - min) / binCount;\n const volumes = new Array<number>(binCount).fill(0);\n\n for (const bar of bars) {\n const volume = bar.volume;\n if (!Number.isFinite(volume) || volume === undefined || volume <= 0) continue;\n if (distribution === \"close\") {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const low = Math.max(bar.low, min);\n const high = Math.min(bar.high, max);\n if (high <= low) {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const first = clampIndex(Math.floor((low - min) / width), binCount);\n const last = clampIndex(Math.floor((high - min) / width), binCount);\n let assigned = 0;\n for (let index = first; index <= last; index += 1) {\n const binLow = min + index * width;\n const binHigh = index === binCount - 1 ? max : binLow + width;\n const overlap = Math.max(0, Math.min(high, binHigh) - Math.max(low, binLow));\n const part = index === last ? volume - assigned : (volume * overlap) / (high - low);\n volumes[index]! += part;\n assigned += part;\n }\n }\n\n const totalVolume = volumes.reduce((sum, value) => sum + value, 0);\n if (!(totalVolume > 0)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n\n const bins: VolumeProfileBin[] = volumes.map((volume, index) => ({\n index,\n priceLow: min + index * width,\n priceHigh: index === binCount - 1 ? max : min + (index + 1) * width,\n priceMid: min + (index + 0.5) * width,\n volume,\n }));\n\n let pocIndex = 0;\n for (let index = 1; index < bins.length; index += 1) {\n if (bins[index]!.volume > bins[pocIndex]!.volume) {\n pocIndex = index;\n }\n }\n\n const target = totalVolume * valueAreaFraction;\n let lowIndex = pocIndex;\n let highIndex = pocIndex;\n let valueVolume = bins[pocIndex]!.volume;\n\n while (valueVolume < target && (lowIndex > 0 || highIndex < bins.length - 1)) {\n const lower = lowIndex > 0 ? bins[lowIndex - 1]!.volume : -1;\n const upper = highIndex < bins.length - 1 ? bins[highIndex + 1]!.volume : -1;\n if (upper > lower) {\n highIndex += 1;\n valueVolume += bins[highIndex]!.volume;\n } else {\n lowIndex -= 1;\n valueVolume += bins[lowIndex]!.volume;\n }\n }\n\n return {\n bins,\n range: { min, max },\n totalVolume,\n poc: bins[pocIndex] ?? null,\n valueArea: {\n low: bins[lowIndex]!.priceLow,\n high: bins[highIndex]!.priceHigh,\n volume: valueVolume,\n },\n };\n}\n\nfunction clampIndex(value: number, count: number): number {\n return Math.max(0, Math.min(count - 1, value));\n}\n","import type { ChartApi, ChartOverlayApi, LicenseContext, OhlcData } from \"@wicklib/core\";\n\nimport {\n computeVolumeProfile,\n type VolumeProfile,\n type VolumeProfileOptions,\n} from \"./volume-profile\";\n\n/**\n * Colors used by the volume-profile overlay.\n */\nexport interface VolumeProfileOverlayColors {\n bar: string;\n valueArea: string;\n poc: string;\n}\n\n/**\n * Options for {@link addVolumeProfileOverlay}.\n */\nexport interface VolumeProfileOverlayOptions extends VolumeProfileOptions {\n /** Overlay id. Defaults to a unique pro id. */\n id?: string;\n /** Pane to draw in. Defaults to the main pane. */\n paneId?: string;\n /** Histogram side. Defaults to the left side. */\n side?: \"left\" | \"right\";\n /** Histogram width as a fraction of the pane plot width. Defaults to 0.22. */\n widthRatio?: number;\n colors?: Partial<VolumeProfileOverlayColors>;\n}\n\n/**\n * Live volume-profile overlay.\n */\nexport interface VolumeProfileOverlay extends ChartOverlayApi {\n readonly profile: VolumeProfile;\n}\n\nconst DEFAULT_COLORS: VolumeProfileOverlayColors = {\n bar: \"#2962ff\",\n valueArea: \"#2962ff\",\n poc: \"#f0b90b\",\n};\n\nlet overlayCounter = 0;\n\n/**\n * Computes a volume profile and adds it to a chart as a clipped pane overlay.\n *\n * Requires the `volume-profile` license feature.\n */\nexport function addVolumeProfileOverlay(\n context: LicenseContext,\n chart: ChartApi,\n bars: readonly OhlcData[],\n options: VolumeProfileOverlayOptions = {},\n): VolumeProfileOverlay {\n const profile = computeVolumeProfile(context, bars, options);\n overlayCounter += 1;\n const id = options.id ?? `com.wicklib.volume-profile-${overlayCounter}`;\n const side = options.side ?? \"left\";\n const widthRatio = clamp(options.widthRatio ?? 0.22, 0.02, 0.9);\n const colors = { ...DEFAULT_COLORS, ...options.colors };\n const maxVolume = Math.max(0, ...profile.bins.map((bin) => bin.volume));\n const valueArea = profile.valueArea;\n\n const overlay = chart.addOverlay({\n id,\n ...(options.paneId ? { paneId: options.paneId } : {}),\n draw(canvas, frame) {\n if (maxVolume <= 0) {\n return;\n }\n const maxWidth = frame.plot.width * widthRatio;\n for (const bin of profile.bins) {\n if (bin.volume <= 0) {\n continue;\n }\n const top = frame.priceToY(bin.priceHigh);\n const bottom = frame.priceToY(bin.priceLow);\n const height = Math.max(1, Math.abs(bottom - top));\n const width = (bin.volume / maxVolume) * maxWidth;\n const x = side === \"left\" ? frame.plot.left : frame.plot.right - width;\n const inValueArea =\n valueArea !== null && bin.priceMid >= valueArea.low && bin.priceMid <= valueArea.high;\n const isPoc = profile.poc?.index === bin.index;\n canvas.globalAlpha = isPoc ? 0.55 : inValueArea ? 0.4 : 0.22;\n canvas.fillStyle = isPoc ? colors.poc : inValueArea ? colors.valueArea : colors.bar;\n canvas.fillRect(x, Math.min(top, bottom), width, height);\n }\n canvas.globalAlpha = 1;\n },\n });\n\n return {\n id: overlay.id,\n paneId: overlay.paneId,\n requestRender: overlay.requestRender,\n remove: overlay.remove,\n profile,\n };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n","import type { Feature } from \"@wicklib/core\";\n\n/**\n * Features shipped in the commercial tier.\n */\nexport const PRO_FEATURES = [\n \"orderflow\",\n \"volume-profile\",\n \"panes\",\n \"layouts\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n] as const;\n\n/**\n * A feature name provided by the commercial tier.\n */\nexport type ProFeature = (typeof PRO_FEATURES)[number];\n\n/**\n * Core feature tokens covered by the pro feature list.\n */\nexport const PRO_CORE_FEATURES: readonly Feature[] = PRO_FEATURES;\n","import type { LicenseContext, WickExtension } from \"@wicklib/core\";\n\nimport type { ProFeature } from \"./features\";\nimport { PRO_VERSION } from \"./version\";\n\n/**\n * Extension descriptor for a commercial feature.\n */\nexport interface ProExtension extends WickExtension {\n readonly kind: \"feature\";\n readonly feature: ProFeature;\n}\n\nconst NAMES: Record<ProFeature, string> = {\n orderflow: \"Orderflow\",\n \"volume-profile\": \"Volume Profile\",\n panes: \"Panes\",\n layouts: \"Layouts\",\n strategy: \"Strategy\",\n alerts: \"Alerts\",\n \"script-functions\": \"Script Functions\",\n};\n\n/**\n * Capability descriptors for the commercial feature set.\n *\n * Hosts pass the granted descriptors through `ChartOptions.extensions`. Individual\n * analytics register their runtime behavior separately.\n */\nexport const PRO_EXTENSIONS: readonly ProExtension[] = Object.freeze(\n (\n [\n \"orderflow\",\n \"volume-profile\",\n \"panes\",\n \"layouts\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n ] as const\n ).map((feature) =>\n Object.freeze({\n kind: \"feature\" as const,\n feature,\n meta: Object.freeze({\n id: `com.wicklib.${feature}`,\n name: NAMES[feature],\n version: PRO_VERSION,\n license: \"pro\" as const,\n }),\n }),\n ),\n);\n\n/**\n * Returns the feature descriptors granted by a license context.\n */\nexport function getProExtensions(context: LicenseContext): readonly ProExtension[] {\n return PRO_EXTENSIONS.filter((extension) => context.hasFeature(extension.feature));\n}\n","import type { Feature, LicenseContext } from \"@wicklib/core\";\n\n/**\n * Decoded payload of a Wicklib license token.\n *\n * Tokens are Ed25519-signed and verified offline. `exp` is seconds since the Unix\n * epoch. `kid` selects the embedded public key.\n */\nexport interface LicenseTokenPayload {\n product: string;\n plan: string;\n seats: number;\n domains: string[];\n exp: number;\n features: Feature[];\n kid: string;\n}\n\n/**\n * Options for creating a license context.\n */\nexport interface LicenseVerifierOptions {\n /** Public keys indexed by `kid`, encoded as base64url raw Ed25519 keys. */\n publicKeys: Readonly<Record<string, string>>;\n /** Clock override for deterministic tests. Returns seconds since the epoch. */\n now?: () => number;\n /** Origin the license is being used from, if domain locking is enabled. */\n domain?: string;\n /** Expected product id. Defaults to wicklib-pro. */\n product?: string;\n}\n\n/**\n * Machine-readable license failure codes.\n */\nexport type LicenseErrorCode =\n | \"CRYPTO_UNAVAILABLE\"\n | \"INVALID_TOKEN\"\n | \"UNSUPPORTED_ALGORITHM\"\n | \"UNKNOWN_KID\"\n | \"INVALID_PAYLOAD\"\n | \"EXPIRED\"\n | \"WRONG_PRODUCT\"\n | \"DOMAIN_REQUIRED\"\n | \"DOMAIN_NOT_ALLOWED\"\n | \"SIGNATURE_INVALID\";\n\n/**\n * Typed license verification failure.\n */\nexport class LicenseError extends Error {\n readonly code: LicenseErrorCode;\n\n constructor(code: LicenseErrorCode, message: string) {\n super(message);\n this.name = \"LicenseError\";\n this.code = code;\n }\n}\n\ninterface LicenseHeader {\n alg: string;\n typ?: string;\n kid?: string;\n}\n\n/**\n * Verifies an Ed25519 license token and returns the feature context used by pro\n * extensions.\n *\n * Verification is fully offline. No network or telemetry calls are made.\n */\nexport async function createLicenseContext(\n token: string,\n options: LicenseVerifierOptions,\n): Promise<LicenseContext> {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token must have three segments\");\n }\n\n const [headerPart, payloadPart, signaturePart] = parts as [string, string, string];\n const header = decodeJson<LicenseHeader>(headerPart, \"INVALID_TOKEN\");\n if (header.alg !== \"Ed25519\") {\n throw new LicenseError(\n \"UNSUPPORTED_ALGORITHM\",\n `Unsupported license algorithm: ${header.alg}`,\n );\n }\n\n const payload = decodeJson<LicenseTokenPayload>(payloadPart, \"INVALID_PAYLOAD\");\n validatePayload(payload);\n\n if (header.kid && header.kid !== payload.kid) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License header and payload kid do not match\");\n }\n\n const publicKey = options.publicKeys[payload.kid];\n if (!publicKey) {\n throw new LicenseError(\"UNKNOWN_KID\", `Unknown license key id: ${payload.kid}`);\n }\n\n const product = options.product ?? \"wicklib-pro\";\n if (payload.product !== product) {\n throw new LicenseError(\n \"WRONG_PRODUCT\",\n `License is for ${payload.product}, expected ${product}`,\n );\n }\n\n const now = options.now?.() ?? Math.floor(Date.now() / 1_000);\n if (payload.exp <= now) {\n throw new LicenseError(\"EXPIRED\", \"License has expired\");\n }\n\n if (payload.domains.length > 0) {\n if (!options.domain) {\n throw new LicenseError(\"DOMAIN_REQUIRED\", \"This license requires a domain\");\n }\n if (!domainAllowed(payload.domains, options.domain)) {\n throw new LicenseError(\n \"DOMAIN_NOT_ALLOWED\",\n `Domain is not covered by the license: ${options.domain}`,\n );\n }\n }\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new LicenseError(\"CRYPTO_UNAVAILABLE\", \"Web Crypto is not available\");\n }\n\n let key: CryptoKey;\n try {\n const raw = base64UrlDecode(publicKey);\n key = await subtle.importKey(\"raw\", raw, { name: \"Ed25519\" }, false, [\"verify\"]);\n } catch (error) {\n throw new LicenseError(\n \"INVALID_PAYLOAD\",\n error instanceof Error ? `Invalid license public key: ${error.message}` : \"Invalid license public key\",\n );\n }\n\n let valid = false;\n try {\n valid = await subtle.verify(\n { name: \"Ed25519\" },\n key,\n base64UrlDecode(signaturePart),\n new TextEncoder().encode(`${headerPart}.${payloadPart}`),\n );\n } catch (error) {\n throw new LicenseError(\n \"SIGNATURE_INVALID\",\n error instanceof Error ? `Signature verification failed: ${error.message}` : \"Signature verification failed\",\n );\n }\n\n if (!valid) {\n throw new LicenseError(\"SIGNATURE_INVALID\", \"License signature is invalid\");\n }\n\n const granted = new Set<Feature>(payload.features);\n return { hasFeature: (feature) => granted.has(feature) };\n}\n\nfunction validatePayload(payload: LicenseTokenPayload): void {\n if (\n !payload ||\n typeof payload.product !== \"string\" ||\n typeof payload.plan !== \"string\" ||\n typeof payload.kid !== \"string\" ||\n payload.kid.length === 0 ||\n !Number.isFinite(payload.exp) ||\n !Number.isInteger(payload.seats) ||\n payload.seats < 1 ||\n !Array.isArray(payload.domains) ||\n payload.domains.some((domain) => typeof domain !== \"string\") ||\n !Array.isArray(payload.features) ||\n payload.features.some((feature) => typeof feature !== \"string\")\n ) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License payload is invalid\");\n }\n}\n\nfunction domainAllowed(domains: readonly string[], host: string): boolean {\n const normalized = normalizeDomain(host);\n return domains.some(\n (domain) => domain === \"*\" || normalizeDomain(domain) === normalized,\n );\n}\n\nfunction normalizeDomain(value: string): string {\n try {\n const url = new URL(value.includes(\"://\") ? value : `https://${value}`);\n return url.hostname.toLowerCase();\n } catch {\n return value.toLowerCase();\n }\n}\n\nfunction decodeJson<T>(value: string, code: LicenseErrorCode): T {\n try {\n return JSON.parse(new TextDecoder().decode(base64UrlDecode(value))) as T;\n } catch {\n throw new LicenseError(code, \"License token contains invalid base64url or JSON\");\n }\n}\n\nfunction base64UrlDecode(value: string): Uint8Array<ArrayBuffer> {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, \"=\");\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n } catch {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token contains invalid base64url\");\n }\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core","import_core","DEFAULT_IMBALANCE_RATIO","imbalanceOf","DEFAULT_BUCKET_MS","import_core","DEFAULT_OPTIONS","import_core"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../package.json","../src/version.ts","../src/script/backtest.ts","../src/strategy/backtest.ts","../src/alerts/engine.ts","../src/analytics/absorption.ts","../src/analytics/depth.ts","../src/analytics/orderflow.ts","../src/analytics/volume-profile.ts","../src/analytics/volume-profile-overlay.ts","../src/features.ts","../src/extensions.ts","../src/license/verify.ts"],"sourcesContent":["/**\n * Wicklib Pro public API.\n *\n * The package is published to npm under the Wicklib Commercial License; its source\n * repository is private.\n */\n\nexport { PRO_VERSION } from \"./version\";\nexport { runScriptBacktest } from \"./script/backtest\";\nexport type {\n CompiledScriptLike,\n ScriptAlertEvent,\n ScriptBacktestOptions,\n ScriptBacktestResult,\n ScriptRunResult,\n} from \"./script/backtest\";\nexport { runBacktest } from \"./strategy/backtest\";\nexport type {\n BacktestFill,\n BacktestOptions,\n BacktestResult,\n EquityPoint,\n StrategyContext,\n StrategyFunction,\n StrategyTarget,\n} from \"./strategy/backtest\";\nexport { AlertEngine, evaluateAlerts } from \"./alerts/engine\";\nexport type {\n AlertDirection,\n AlertPriceSource,\n AlertTrigger,\n PriceAlertRule,\n} from \"./alerts/engine\";\nexport { detectAbsorption } from \"./analytics/absorption\";\nexport type { AbsorptionEvent, AbsorptionOptions } from \"./analytics/absorption\";\nexport { DepthAggregator, computeDepth } from \"./analytics/depth\";\nexport type {\n DepthBar,\n DepthLevel,\n DepthLevelBar,\n DepthOptions,\n DepthSnapshot,\n} from \"./analytics/depth\";\nexport { FootprintAggregator, computeFootprint } from \"./analytics/orderflow\";\nexport type {\n FootprintBar,\n FootprintLevel,\n FootprintOptions,\n TradeSide,\n TradeTick,\n} from \"./analytics/orderflow\";\nexport { addVolumeProfileOverlay } from \"./analytics/volume-profile-overlay\";\nexport type {\n VolumeProfileOverlay,\n VolumeProfileOverlayColors,\n VolumeProfileOverlayOptions,\n} from \"./analytics/volume-profile-overlay\";\nexport { computeVolumeProfile } from \"./analytics/volume-profile\";\nexport type {\n VolumeProfile,\n VolumeProfileBin,\n VolumeProfileDistribution,\n VolumeProfileOptions,\n} from \"./analytics/volume-profile\";\nexport { PRO_CORE_FEATURES, PRO_FEATURES } from \"./features\";\nexport type { ProFeature } from \"./features\";\nexport * from \"./extensions\";\nexport * from \"./license/verify\";\n\nimport { assertFeature, type Feature, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Returns true when the active license grants a pro feature.\n */\nexport function hasProFeature(context: LicenseContext, feature: Feature): boolean {\n return context.hasFeature(feature);\n}\n\n/**\n * Throws `WickError(\"LICENSE_REQUIRED\")` when a pro feature is not granted.\n */\nexport function assertProFeature(context: LicenseContext, feature: Feature): void {\n assertFeature(context, feature);\n}\n","{\n \"name\": \"@wicklib/pro\",\n \"version\": \"0.13.0\",\n \"description\": \"Wicklib commercial add-on\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"type\": \"module\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/wicklib/wicklib-pro.git\",\n \"directory\": \"packages/pro\"\n },\n \"peerDependencies\": {\n \"@wicklib/core\": \"^0.13.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"devDependencies\": {\n \"tsup\": \"^9.0.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^5.0.5\"\n }\n}\n","import packageJson from \"../package.json\";\n\n/**\n * Semantic version of the installed pro package.\n */\nexport const PRO_VERSION: string = packageJson.version;\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\nimport {\n runBacktest,\n type BacktestOptions,\n type BacktestResult,\n type StrategyTarget,\n} from \"../strategy/backtest\";\n\n/**\n * One alert emitted by a script, including the bar it belongs to.\n */\nexport interface ScriptAlertEvent {\n time: number;\n barIndex: number;\n message: string;\n}\n\n/**\n * Output required from a compiled script replay.\n *\n * This is structurally compatible with `@wicklib/script`'s `CompiledScript`, without making\n * Pro depend on the script package at runtime.\n */\nexport interface ScriptRunResult {\n plots: Readonly<Record<string, ReadonlyArray<number | null>>>;\n alerts: ReadonlyArray<string>;\n alertEvents?: ReadonlyArray<ScriptAlertEvent>;\n}\n\n/**\n * Minimal compiled-script contract accepted by the adapter.\n */\nexport interface CompiledScriptLike {\n replay(bars: readonly OhlcData[]): Promise<ScriptRunResult>;\n}\n\n/**\n * Options for a script-driven backtest.\n */\nexport interface ScriptBacktestOptions extends BacktestOptions {\n /** Plot id whose values are target positions: -1 short, 0 flat, 1 long, null hold. */\n signalPlot: string;\n}\n\n/**\n * Backtest result plus script alerts.\n */\nexport interface ScriptBacktestResult extends BacktestResult {\n alerts: readonly ScriptAlertEvent[];\n}\n\n/**\n * Runs a compiled script, maps one plot to target positions, and backtests the result.\n *\n * The script must emit positions on the configured plot. Alerts are returned with their\n * source bar so the host can deliver or persist them. Requires the `strategy` feature.\n */\nexport async function runScriptBacktest(\n context: LicenseContext,\n script: CompiledScriptLike,\n bars: readonly OhlcData[],\n options: ScriptBacktestOptions,\n): Promise<ScriptBacktestResult> {\n assertFeature(context, \"strategy\");\n\n if (!script || typeof script.replay !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script adapter requires a replay function\");\n }\n if (typeof options.signalPlot !== \"string\" || options.signalPlot.trim() === \"\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script signalPlot must be a non-empty string\");\n }\n\n const result = await script.replay(bars);\n const values = result?.plots?.[options.signalPlot];\n if (!Array.isArray(values)) {\n throw new WickError(\"INVALID_DATA\", `Script plot not found: ${options.signalPlot}`);\n }\n if (values.length !== bars.length) {\n throw new WickError(\"INVALID_DATA\", \"Script signal plot length must match the bar count\");\n }\n if (result.alerts.length > 0 && !result.alertEvents) {\n throw new WickError(\"INVALID_DATA\", \"Script alerts are missing their bar events\");\n }\n\n const alerts = (result.alertEvents ?? []).map((event) => validateAlert(event));\n const backtest = runBacktest(\n context,\n bars,\n ({ index }): StrategyTarget | undefined => {\n const value = values[index];\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value !== -1 && value !== 0 && value !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Script signal must be -1, 0, 1, or null\");\n }\n return value;\n },\n options,\n );\n\n return { ...backtest, alerts };\n}\n\nfunction validateAlert(event: ScriptAlertEvent): ScriptAlertEvent {\n if (\n !event ||\n !Number.isFinite(event.time) ||\n !Number.isInteger(event.barIndex) ||\n event.barIndex < 0 ||\n typeof event.message !== \"string\"\n ) {\n throw new WickError(\"INVALID_DATA\", \"Invalid script alert event\");\n }\n return { time: event.time, barIndex: event.barIndex, message: event.message };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Target position for a strategy.\n *\n * -1 = fully short\n * 0 = flat\n * 1 = fully long\n */\nexport type StrategyTarget = -1 | 0 | 1;\n\n/**\n * Context passed to a strategy once per closed bar.\n */\nexport interface StrategyContext {\n readonly bar: OhlcData;\n readonly index: number;\n readonly position: StrategyTarget;\n readonly cash: number;\n readonly units: number;\n readonly equity: number;\n}\n\n/**\n * Strategy callback. Return a target to schedule a fill at the next bar open, or\n * `undefined`/`null` to hold the current target.\n */\nexport type StrategyFunction = (context: StrategyContext) => StrategyTarget | null | undefined;\n\n/**\n * Backtest configuration.\n */\nexport interface BacktestOptions {\n /** Starting cash. Required and positive. */\n initialCapital: number;\n /** Fractional fee charged on absolute traded notional. Defaults to 0. */\n feeRate?: number;\n /** Fractional slippage applied against the fill. Defaults to 0. */\n slippage?: number;\n}\n\n/**\n * One executed target change.\n */\nexport interface BacktestFill {\n time: number;\n side: \"buy\" | \"sell\";\n price: number;\n quantity: number;\n fee: number;\n}\n\n/**\n * One marked-to-market equity point.\n */\nexport interface EquityPoint {\n time: number;\n cash: number;\n units: number;\n position: StrategyTarget;\n price: number;\n equity: number;\n}\n\n/**\n * Deterministic strategy backtest result.\n */\nexport interface BacktestResult {\n initialCapital: number;\n finalEquity: number;\n returnPercent: number;\n maxDrawdown: number;\n fills: readonly BacktestFill[];\n equity: readonly EquityPoint[];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<BacktestOptions, \"initialCapital\">> = {\n feeRate: 0,\n slippage: 0,\n};\n\n/**\n * Runs a target-position strategy against closed bars.\n *\n * Signals are evaluated on bar close and filled at the next bar open, preventing\n * lookahead. Position sizing is fully invested at the fill price; leverage is not added.\n * Requires the `strategy` license feature.\n */\nexport function runBacktest(\n context: LicenseContext,\n bars: readonly OhlcData[],\n strategy: StrategyFunction,\n options: BacktestOptions,\n): BacktestResult {\n assertFeature(context, \"strategy\");\n\n const initialCapital = options.initialCapital;\n const feeRate = options.feeRate ?? DEFAULT_OPTIONS.feeRate;\n const slippage = options.slippage ?? DEFAULT_OPTIONS.slippage;\n if (!Number.isFinite(initialCapital) || initialCapital <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest initialCapital must be positive\");\n }\n if (!Number.isFinite(feeRate) || feeRate < 0 || feeRate >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest feeRate must be in [0, 1)\");\n }\n if (!Number.isFinite(slippage) || slippage < 0 || slippage >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest slippage must be in [0, 1)\");\n }\n if (typeof strategy !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest strategy must be a function\");\n }\n\n let cash = initialCapital;\n let units = 0;\n let position: StrategyTarget = 0;\n let pending: StrategyTarget | null = null;\n let previousTime = Number.NEGATIVE_INFINITY;\n const fills: BacktestFill[] = [];\n const equity: EquityPoint[] = [];\n let peak = initialCapital;\n let maxDrawdown = 0;\n\n for (let index = 0; index < bars.length; index += 1) {\n const bar = bars[index]!;\n if (\n !Number.isFinite(bar.time) ||\n bar.time <= previousTime ||\n !Number.isFinite(bar.open) ||\n !Number.isFinite(bar.close) ||\n !Number.isFinite(bar.high) ||\n !Number.isFinite(bar.low)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Backtest bars require ascending finite OHLC values\");\n }\n previousTime = bar.time;\n\n if (pending !== null && pending !== position) {\n const side: \"buy\" | \"sell\" = pending > position ? \"buy\" : \"sell\";\n const price = side === \"buy\" ? bar.open * (1 + slippage) : bar.open * (1 - slippage);\n const equityAtFill = cash + units * price;\n const desiredUnits = (pending * equityAtFill) / price;\n const quantity = desiredUnits - units;\n const fee = Math.abs(quantity * price) * feeRate;\n cash -= quantity * price + fee;\n units = desiredUnits;\n position = pending;\n if (quantity !== 0) {\n fills.push({ time: bar.time, side, price, quantity, fee });\n }\n pending = null;\n }\n\n const markedEquity = cash + units * bar.close;\n peak = Math.max(peak, markedEquity);\n if (peak > 0) {\n maxDrawdown = Math.max(maxDrawdown, (peak - markedEquity) / peak);\n }\n equity.push({\n time: bar.time,\n cash,\n units,\n position,\n price: bar.close,\n equity: markedEquity,\n });\n\n const signal = strategy({\n bar,\n index,\n position,\n cash,\n units,\n equity: markedEquity,\n });\n if (signal !== undefined && signal !== null) {\n if (signal !== -1 && signal !== 0 && signal !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Strategy target must be -1, 0, or 1\");\n }\n pending = signal;\n }\n }\n\n const finalEquity = equity.at(-1)?.equity ?? initialCapital;\n return {\n initialCapital,\n finalEquity,\n returnPercent: ((finalEquity - initialCapital) / initialCapital) * 100,\n maxDrawdown,\n fills,\n equity,\n };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Price field used by a price alert.\n */\nexport type AlertPriceSource = \"close\" | \"high\" | \"low\";\n\n/**\n * Price alert direction.\n *\n * `cross` reports the side that was crossed.\n */\nexport type AlertDirection = \"above\" | \"below\" | \"cross\";\n\n/**\n * A serializable price alert rule.\n */\nexport interface PriceAlertRule {\n readonly id: string;\n readonly price: number;\n readonly direction: AlertDirection;\n /** Defaults to close. */\n readonly source?: AlertPriceSource;\n}\n\n/**\n * A triggered alert.\n */\nexport interface AlertTrigger {\n readonly ruleId: string;\n readonly time: number;\n readonly direction: \"above\" | \"below\";\n readonly price: number;\n readonly value: number;\n readonly bar: OhlcData;\n}\n\nconst SOURCES = new Set<AlertPriceSource>([\"close\", \"high\", \"low\"]);\n\n/**\n * Deterministic, offline alert evaluator for streaming bars.\n *\n * The first bar initializes state and never triggers. Subsequent bars trigger only on a\n * transition so a rule does not fire repeatedly while it remains true.\n */\nexport class AlertEngine {\n private readonly rules: readonly PriceAlertRule[];\n private readonly previous = new Map<string, number>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, rules: readonly PriceAlertRule[]) {\n assertFeature(context, \"alerts\");\n const ids = new Set<string>();\n for (const rule of rules) {\n if (\n !rule ||\n typeof rule.id !== \"string\" ||\n rule.id.trim() === \"\" ||\n !Number.isFinite(rule.price) ||\n (rule.direction !== \"above\" && rule.direction !== \"below\" && rule.direction !== \"cross\") ||\n (rule.source !== undefined && !SOURCES.has(rule.source))\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Invalid price alert rule\");\n }\n if (ids.has(rule.id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Duplicate alert rule id: ${rule.id}`);\n }\n ids.add(rule.id);\n }\n this.rules = rules.map((rule) => ({ ...rule }));\n }\n\n /**\n * Consumes one closed bar and returns the alerts triggered by that bar.\n */\n update(bar: OhlcData): readonly AlertTrigger[] {\n if (!Number.isFinite(bar.time)) {\n throw new WickError(\"INVALID_DATA\", \"Alert bar requires a finite time\");\n }\n if (bar.time <= this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Alert bars must have increasing times\");\n }\n this.lastTime = bar.time;\n\n const triggers: AlertTrigger[] = [];\n for (const rule of this.rules) {\n const source = rule.source ?? \"close\";\n const value = source === \"close\" ? bar.close : source === \"high\" ? bar.high : bar.low;\n const previous = this.previous.get(rule.id);\n if (previous !== undefined) {\n if (rule.direction === \"above\" && previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (rule.direction === \"below\" && previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n } else if (rule.direction === \"cross\") {\n if (previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n }\n }\n }\n this.previous.set(rule.id, value);\n }\n\n return triggers;\n }\n\n /**\n * Clears previous values so the next bar initializes state again.\n */\n reset(): void {\n this.previous.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Evaluates a batch of closed bars through the same streaming alert path.\n */\nexport function evaluateAlerts(\n context: LicenseContext,\n rules: readonly PriceAlertRule[],\n bars: readonly OhlcData[],\n): readonly AlertTrigger[] {\n const engine = new AlertEngine(context, rules);\n const triggers: AlertTrigger[] = [];\n for (const bar of bars) {\n triggers.push(...engine.update(bar));\n }\n return triggers;\n}\n\nfunction trigger(\n rule: PriceAlertRule,\n bar: OhlcData,\n value: number,\n direction: \"above\" | \"below\",\n): AlertTrigger {\n return {\n ruleId: rule.id,\n time: bar.time,\n direction,\n price: rule.price,\n value,\n bar,\n };\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\nimport { DepthAggregator, type DepthSnapshot } from \"./depth\";\nimport { FootprintAggregator, type TradeTick, type TradeSide } from \"./orderflow\";\n\n/**\n * Options for absorption detection.\n */\nexport interface AbsorptionOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Aggressive volume must reach passive size × this ratio. Defaults to 2. */\n absorptionRatio?: number;\n}\n\n/**\n * A detected absorption event.\n */\nexport interface AbsorptionEvent {\n /** Bucket start time in milliseconds. */\n time: number;\n priceLow: number;\n priceHigh: number;\n /** Aggressor side that was absorbed. */\n side: TradeSide;\n /** Aggressive trade volume in the bucket and level. */\n aggressiveVolume: number;\n /** Passive book size at the level when the bucket completed. */\n passiveVolume: number;\n /** aggressiveVolume / passiveVolume. */\n ratio: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_ABSORPTION_RATIO = 2;\n\n/**\n * Detects aggressive volume absorbed by passive L2 liquidity.\n *\n * For each footprint bucket and price level:\n * - aggressive buys are compared with ask depth\n * - aggressive sells are compared with bid depth\n *\n * A level is reported when aggressive volume is at least the configured multiple of the\n * passive size. Requires the `orderflow` license feature.\n */\nexport function detectAbsorption(\n context: LicenseContext,\n trades: readonly TradeTick[],\n snapshots: readonly DepthSnapshot[],\n options: AbsorptionOptions,\n): readonly AbsorptionEvent[] {\n assertFeature(context, \"orderflow\");\n\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const absorptionRatio = options.absorptionRatio ?? DEFAULT_ABSORPTION_RATIO;\n const priceStep = options.priceStep;\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption bucketMs must be a positive integer\");\n }\n if (!Number.isFinite(absorptionRatio) || absorptionRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption ratio must be at least 1\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption priceStep must be a positive number\");\n }\n\n const footprints = new FootprintAggregator(context, {\n bucketMs,\n priceStep,\n });\n for (const trade of [...trades].sort((first, second) => first.time - second.time)) {\n footprints.push(trade);\n }\n\n const depth = new DepthAggregator(context, { priceStep });\n for (const snapshot of [...snapshots].sort((first, second) => first.time - second.time)) {\n depth.push(snapshot);\n }\n\n const events: AbsorptionEvent[] = [];\n for (const bar of footprints.getBars()) {\n const book = depth.latest(bar.time + bucketMs - 1);\n if (!book) {\n continue;\n }\n const depthByPrice = new Map(book.levels.map((level) => [level.priceLow, level]));\n for (const level of bar.levels) {\n const depthLevel = depthByPrice.get(level.priceLow);\n if (!depthLevel) {\n continue;\n }\n const candidates: Array<{\n side: TradeSide;\n aggressive: number;\n passive: number;\n }> = [\n { side: \"buy\", aggressive: level.buyVolume, passive: depthLevel.askSize },\n { side: \"sell\", aggressive: level.sellVolume, passive: depthLevel.bidSize },\n ];\n for (const candidate of candidates) {\n if (candidate.passive <= 0 || candidate.aggressive <= 0) {\n continue;\n }\n const ratio = candidate.aggressive / candidate.passive;\n if (ratio >= absorptionRatio) {\n events.push({\n time: bar.time,\n priceLow: level.priceLow,\n priceHigh: level.priceHigh,\n side: candidate.side,\n aggressiveVolume: candidate.aggressive,\n passiveVolume: candidate.passive,\n ratio,\n });\n }\n }\n }\n }\n\n return events;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * One side of a Level-2 depth snapshot.\n */\nexport interface DepthLevel {\n price: number;\n size: number;\n}\n\n/**\n * A full bid/ask book snapshot at a point in time.\n */\nexport interface DepthSnapshot {\n /** Unix timestamp in milliseconds. */\n time: number;\n bids: readonly DepthLevel[];\n asks: readonly DepthLevel[];\n}\n\n/**\n * Aggregated bid/ask liquidity by price bucket.\n */\nexport interface DepthLevelBar {\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n}\n\n/**\n * Aggregated depth for one snapshot.\n */\nexport interface DepthBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n levels: readonly DepthLevelBar[];\n}\n\n/**\n * Options for depth aggregation.\n */\nexport interface DepthOptions {\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies total book pressure as imbalanced. Defaults to 2. */\n imbalanceRatio?: number;\n}\n\nconst DEFAULT_IMBALANCE_RATIO = 2;\n\n/**\n * Incremental L2 depth aggregator.\n *\n * Snapshots are complete books, so newer snapshots replace the current view rather than\n * accumulate. Non-decreasing timestamps are enforced.\n */\nexport class DepthAggregator {\n private readonly options: Required<DepthOptions>;\n private readonly bars = new Map<number, DepthBar>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: DepthOptions) {\n assertFeature(context, \"orderflow\");\n if (\n options.priceStep === undefined ||\n !Number.isFinite(options.priceStep) ||\n options.priceStep <= 0\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth priceStep must be a positive number\");\n }\n const ratio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n if (!Number.isFinite(ratio) || ratio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth imbalanceRatio must be at least 1\");\n }\n this.options = { priceStep: options.priceStep, imbalanceRatio: ratio };\n }\n\n /**\n * Adds or replaces one complete snapshot and returns its aggregated bar.\n */\n push(snapshot: DepthSnapshot): DepthBar {\n if (\n !Number.isFinite(snapshot.time) ||\n !Array.isArray(snapshot.bids) ||\n !Array.isArray(snapshot.asks)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots require finite time, bids, and asks\");\n }\n if (snapshot.time < this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots must be in non-decreasing time order\");\n }\n this.lastTime = snapshot.time;\n\n const levels = new Map<number, { bid: number; ask: number }>();\n for (const [side, entries] of [\n [\"bid\", snapshot.bids],\n [\"ask\", snapshot.asks],\n ] as const) {\n for (const entry of entries) {\n if (!Number.isFinite(entry.price) || !Number.isFinite(entry.size) || entry.size < 0) {\n throw new WickError(\n \"INVALID_DATA\",\n \"Depth levels require finite price and non-negative size\",\n );\n }\n const price = Math.floor(entry.price / this.options.priceStep) * this.options.priceStep;\n let level = levels.get(price);\n if (!level) {\n level = { bid: 0, ask: 0 };\n levels.set(price, level);\n }\n if (side === \"bid\") level.bid += entry.size;\n else level.ask += entry.size;\n }\n }\n\n let bidSize = 0;\n let askSize = 0;\n const sortedLevels: DepthLevelBar[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, level]) => {\n bidSize += level.bid;\n askSize += level.ask;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n bidSize: level.bid,\n askSize: level.ask,\n totalSize: level.bid + level.ask,\n delta: level.bid - level.ask,\n imbalance: imbalanceOf(level.bid, level.ask, this.options.imbalanceRatio),\n };\n });\n\n const bar: DepthBar = {\n time: snapshot.time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n bidSize,\n askSize,\n totalSize: bidSize + askSize,\n delta: bidSize - askSize,\n imbalance: imbalanceOf(bidSize, askSize, this.options.imbalanceRatio),\n levels: sortedLevels,\n };\n this.bars.set(snapshot.time, bar);\n return bar;\n }\n\n /**\n * Returns the latest snapshot at or before a time.\n */\n latest(time = Number.POSITIVE_INFINITY): DepthBar | null {\n const eligible = [...this.bars.values()]\n .filter((bar) => bar.time <= time)\n .sort((first, second) => first.time - second.time);\n return eligible.at(-1) ?? null;\n }\n\n /**\n * Returns all snapshots in ascending time order.\n */\n getBars(): readonly DepthBar[] {\n return [...this.bars.values()].sort((first, second) => first.time - second.time);\n }\n\n /**\n * Clears all snapshots and the streaming order guard.\n */\n reset(): void {\n this.bars.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Aggregates a batch of complete L2 book snapshots.\n *\n * Requires the `orderflow` license feature.\n */\nexport function computeDepth(\n context: LicenseContext,\n snapshots: readonly DepthSnapshot[],\n options: DepthOptions,\n): readonly DepthBar[] {\n const aggregator = new DepthAggregator(context, options);\n for (const snapshot of snapshots) {\n aggregator.push(snapshot);\n }\n return aggregator.getBars();\n}\n\nfunction imbalanceOf(bid: number, ask: number, ratio: number): \"bid\" | \"ask\" | null {\n if (bid === 0 && ask === 0) return null;\n if (ask === 0) return \"bid\";\n if (bid === 0) return \"ask\";\n if (bid >= ask * ratio) return \"bid\";\n if (ask >= bid * ratio) return \"ask\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Aggressor side of a trade tick.\n */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/**\n * Minimal trade tick accepted by the orderflow aggregator.\n */\nexport interface TradeTick {\n /** Unix timestamp in milliseconds. */\n time: number;\n price: number;\n size: number;\n side: TradeSide;\n}\n\n/**\n * Orderflow aggregation options.\n */\nexport interface FootprintOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies a level as imbalanced. Defaults to 3. */\n imbalanceRatio?: number;\n}\n\n/**\n * One price level in a footprint bar.\n */\nexport interface FootprintLevel {\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n imbalance: TradeSide | null;\n}\n\n/**\n * Aggregated footprint for one time bucket.\n */\nexport interface FootprintBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n levels: readonly FootprintLevel[];\n}\n\ninterface ResolvedOptions {\n bucketMs: number;\n priceStep: number;\n imbalanceRatio: number;\n}\n\ninterface LevelVolumes {\n buy: number;\n sell: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_IMBALANCE_RATIO = 3;\n\n/**\n * Incremental trade-tick footprint aggregator.\n *\n * Trades must arrive in non-decreasing time order. Ticks in the same bucket update the\n * same bar, so streaming and batch aggregation share the same code path.\n */\nexport class FootprintAggregator {\n private readonly options: ResolvedOptions;\n private readonly levels = new Map<number, Map<number, LevelVolumes>>();\n private lastTradeTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: FootprintOptions) {\n assertFeature(context, \"orderflow\");\n this.options = resolveOptions(options);\n }\n\n /**\n * Adds one trade and returns the updated bar for its time bucket.\n */\n push(trade: TradeTick): FootprintBar {\n this.validateTrade(trade);\n if (trade.time < this.lastTradeTime) {\n throw new WickError(\"INVALID_DATA\", \"Streaming trades must be in non-decreasing time order\");\n }\n this.lastTradeTime = trade.time;\n\n const time = Math.floor(trade.time / this.options.bucketMs) * this.options.bucketMs;\n const price = Math.floor(trade.price / this.options.priceStep) * this.options.priceStep;\n let levels = this.levels.get(time);\n if (!levels) {\n levels = new Map();\n this.levels.set(time, levels);\n }\n let level = levels.get(price);\n if (!level) {\n level = { buy: 0, sell: 0 };\n levels.set(price, level);\n }\n if (trade.side === \"buy\") level.buy += trade.size;\n else level.sell += trade.size;\n\n return this.buildBar(time)!;\n }\n\n /**\n * Adds multiple trades in input order.\n */\n pushMany(trades: readonly TradeTick[]): readonly FootprintBar[] {\n for (const trade of trades) {\n this.push(trade);\n }\n return this.getBars();\n }\n\n /**\n * Returns a bar by bucket start time, or any time inside that bucket.\n */\n getBar(time: number): FootprintBar | null {\n const bucket = Math.floor(time / this.options.bucketMs) * this.options.bucketMs;\n return this.buildBar(bucket);\n }\n\n /**\n * Returns all completed/current buckets in ascending time order.\n */\n getBars(): readonly FootprintBar[] {\n return [...this.levels.keys()]\n .sort((first, second) => first - second)\n .map((time) => this.buildBar(time))\n .filter((bar): bar is FootprintBar => bar !== null);\n }\n\n /**\n * Clears all trades and resets the streaming order guard.\n */\n reset(): void {\n this.levels.clear();\n this.lastTradeTime = Number.NEGATIVE_INFINITY;\n }\n\n private buildBar(time: number): FootprintBar | null {\n const levels = this.levels.get(time);\n if (!levels) {\n return null;\n }\n\n let buyVolume = 0;\n let sellVolume = 0;\n const sortedLevels: FootprintLevel[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, volumes]) => {\n buyVolume += volumes.buy;\n sellVolume += volumes.sell;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n buyVolume: volumes.buy,\n sellVolume: volumes.sell,\n totalVolume: volumes.buy + volumes.sell,\n delta: volumes.buy - volumes.sell,\n imbalance: imbalanceOf(volumes.buy, volumes.sell, this.options.imbalanceRatio),\n };\n });\n\n return {\n time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n buyVolume,\n sellVolume,\n totalVolume: buyVolume + sellVolume,\n delta: buyVolume - sellVolume,\n levels: sortedLevels,\n };\n }\n\n private validateTrade(trade: TradeTick): void {\n if (\n !Number.isFinite(trade.time) ||\n !Number.isFinite(trade.price) ||\n !Number.isFinite(trade.size) ||\n trade.size <= 0 ||\n trade.price < 0 ||\n (trade.side !== \"buy\" && trade.side !== \"sell\")\n ) {\n throw new WickError(\"INVALID_DATA\", \"Trade ticks require finite time, price, size, and side\");\n }\n }\n}\n\n/**\n * Aggregates trade ticks into bid/ask footprint bars with delta and imbalance.\n *\n * Requires the `orderflow` license feature. Trades are sorted by time before aggregation.\n */\nexport function computeFootprint(\n context: LicenseContext,\n trades: readonly TradeTick[],\n options: FootprintOptions,\n): readonly FootprintBar[] {\n const aggregator = new FootprintAggregator(context, options);\n return aggregator.pushMany([...trades].sort((first, second) => first.time - second.time));\n}\n\nfunction resolveOptions(options: FootprintOptions): ResolvedOptions {\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const priceStep = options.priceStep;\n const imbalanceRatio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint bucketMs must be a positive integer\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint priceStep must be a positive number\");\n }\n if (!Number.isFinite(imbalanceRatio) || imbalanceRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint imbalanceRatio must be at least 1\");\n }\n return { bucketMs, priceStep, imbalanceRatio };\n}\n\nfunction imbalanceOf(buy: number, sell: number, ratio: number): TradeSide | null {\n if (buy === 0 && sell === 0) return null;\n if (sell === 0) return \"buy\";\n if (buy === 0) return \"sell\";\n if (buy >= sell * ratio) return \"buy\";\n if (sell >= buy * ratio) return \"sell\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Volume distribution model.\n *\n * `uniform` spreads each bar's volume evenly across its price range. `close` assigns the\n * whole bar volume to the bin containing the close.\n */\nexport type VolumeProfileDistribution = \"uniform\" | \"close\";\n\n/**\n * Options for {@link computeVolumeProfile}.\n */\nexport interface VolumeProfileOptions {\n /** Number of equal-width price bins. Defaults to 24. */\n bins?: number;\n /** Fixed price range. Defaults to the bars' low/high span. */\n priceRange?: { min: number; max: number };\n /** Fraction of total volume covered by the value area. Defaults to 0.7. */\n valueArea?: number;\n /** Volume distribution model. Defaults to uniform. */\n distribution?: VolumeProfileDistribution;\n}\n\n/**\n * One price bucket in a volume profile.\n */\nexport interface VolumeProfileBin {\n index: number;\n priceLow: number;\n priceHigh: number;\n priceMid: number;\n volume: number;\n}\n\n/**\n * Computed volume profile.\n */\nexport interface VolumeProfile {\n bins: readonly VolumeProfileBin[];\n range: { min: number; max: number };\n totalVolume: number;\n /** Point of control, or null when there is no volume. */\n poc: VolumeProfileBin | null;\n valueArea: {\n low: number;\n high: number;\n volume: number;\n } | null;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<VolumeProfileOptions, \"priceRange\">> = {\n bins: 24,\n valueArea: 0.7,\n distribution: \"uniform\",\n};\n\n/**\n * Computes a deterministic volume profile from OHLCV bars.\n *\n * Requires the `volume-profile` license feature. Bars without a finite positive volume are\n * ignored. Throws `WickError(\"INVALID_DATA\")` when no usable volume remains.\n */\nexport function computeVolumeProfile(\n context: LicenseContext,\n bars: readonly OhlcData[],\n options: VolumeProfileOptions = {},\n): VolumeProfile {\n assertFeature(context, \"volume-profile\");\n\n const binCount = options.bins ?? DEFAULT_OPTIONS.bins;\n const valueAreaFraction = options.valueArea ?? DEFAULT_OPTIONS.valueArea;\n const distribution = options.distribution ?? DEFAULT_OPTIONS.distribution;\n\n if (!Number.isInteger(binCount) || binCount <= 0 || binCount > 2_000) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile bins must be between 1 and 2000\");\n }\n if (!Number.isFinite(valueAreaFraction) || valueAreaFraction <= 0 || valueAreaFraction > 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile valueArea must be in (0, 1]\");\n }\n\n let min: number;\n let max: number;\n if (options.priceRange) {\n min = options.priceRange.min;\n max = options.priceRange.max;\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile priceRange must have max > min\");\n }\n } else {\n min = Number.POSITIVE_INFINITY;\n max = Number.NEGATIVE_INFINITY;\n for (const bar of bars) {\n if (!Number.isFinite(bar.volume) || bar.volume! <= 0) continue;\n min = Math.min(min, bar.low);\n max = Math.max(max, bar.high);\n }\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n if (max <= min) {\n max = min + 1;\n }\n }\n\n const width = (max - min) / binCount;\n const volumes = new Array<number>(binCount).fill(0);\n\n for (const bar of bars) {\n const volume = bar.volume;\n if (!Number.isFinite(volume) || volume === undefined || volume <= 0) continue;\n if (distribution === \"close\") {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const low = Math.max(bar.low, min);\n const high = Math.min(bar.high, max);\n if (high <= low) {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const first = clampIndex(Math.floor((low - min) / width), binCount);\n const last = clampIndex(Math.floor((high - min) / width), binCount);\n let assigned = 0;\n for (let index = first; index <= last; index += 1) {\n const binLow = min + index * width;\n const binHigh = index === binCount - 1 ? max : binLow + width;\n const overlap = Math.max(0, Math.min(high, binHigh) - Math.max(low, binLow));\n const part = index === last ? volume - assigned : (volume * overlap) / (high - low);\n volumes[index]! += part;\n assigned += part;\n }\n }\n\n const totalVolume = volumes.reduce((sum, value) => sum + value, 0);\n if (!(totalVolume > 0)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n\n const bins: VolumeProfileBin[] = volumes.map((volume, index) => ({\n index,\n priceLow: min + index * width,\n priceHigh: index === binCount - 1 ? max : min + (index + 1) * width,\n priceMid: min + (index + 0.5) * width,\n volume,\n }));\n\n let pocIndex = 0;\n for (let index = 1; index < bins.length; index += 1) {\n if (bins[index]!.volume > bins[pocIndex]!.volume) {\n pocIndex = index;\n }\n }\n\n const target = totalVolume * valueAreaFraction;\n let lowIndex = pocIndex;\n let highIndex = pocIndex;\n let valueVolume = bins[pocIndex]!.volume;\n\n while (valueVolume < target && (lowIndex > 0 || highIndex < bins.length - 1)) {\n const lower = lowIndex > 0 ? bins[lowIndex - 1]!.volume : -1;\n const upper = highIndex < bins.length - 1 ? bins[highIndex + 1]!.volume : -1;\n if (upper > lower) {\n highIndex += 1;\n valueVolume += bins[highIndex]!.volume;\n } else {\n lowIndex -= 1;\n valueVolume += bins[lowIndex]!.volume;\n }\n }\n\n return {\n bins,\n range: { min, max },\n totalVolume,\n poc: bins[pocIndex] ?? null,\n valueArea: {\n low: bins[lowIndex]!.priceLow,\n high: bins[highIndex]!.priceHigh,\n volume: valueVolume,\n },\n };\n}\n\nfunction clampIndex(value: number, count: number): number {\n return Math.max(0, Math.min(count - 1, value));\n}\n","import type { ChartApi, ChartOverlayApi, LicenseContext, OhlcData } from \"@wicklib/core\";\n\nimport {\n computeVolumeProfile,\n type VolumeProfile,\n type VolumeProfileOptions,\n} from \"./volume-profile\";\n\n/**\n * Colors used by the volume-profile overlay.\n */\nexport interface VolumeProfileOverlayColors {\n bar: string;\n valueArea: string;\n poc: string;\n}\n\n/**\n * Options for {@link addVolumeProfileOverlay}.\n */\nexport interface VolumeProfileOverlayOptions extends VolumeProfileOptions {\n /** Overlay id. Defaults to a unique pro id. */\n id?: string;\n /** Pane to draw in. Defaults to the main pane. */\n paneId?: string;\n /** Histogram side. Defaults to the left side. */\n side?: \"left\" | \"right\";\n /** Histogram width as a fraction of the pane plot width. Defaults to 0.22. */\n widthRatio?: number;\n colors?: Partial<VolumeProfileOverlayColors>;\n}\n\n/**\n * Live volume-profile overlay.\n */\nexport interface VolumeProfileOverlay extends ChartOverlayApi {\n readonly profile: VolumeProfile;\n}\n\nconst DEFAULT_COLORS: VolumeProfileOverlayColors = {\n bar: \"#2962ff\",\n valueArea: \"#2962ff\",\n poc: \"#f0b90b\",\n};\n\nlet overlayCounter = 0;\n\n/**\n * Computes a volume profile and adds it to a chart as a clipped pane overlay.\n *\n * Requires the `volume-profile` license feature.\n */\nexport function addVolumeProfileOverlay(\n context: LicenseContext,\n chart: ChartApi,\n bars: readonly OhlcData[],\n options: VolumeProfileOverlayOptions = {},\n): VolumeProfileOverlay {\n const profile = computeVolumeProfile(context, bars, options);\n overlayCounter += 1;\n const id = options.id ?? `com.wicklib.volume-profile-${overlayCounter}`;\n const side = options.side ?? \"left\";\n const widthRatio = clamp(options.widthRatio ?? 0.22, 0.02, 0.9);\n const colors = { ...DEFAULT_COLORS, ...options.colors };\n const maxVolume = Math.max(0, ...profile.bins.map((bin) => bin.volume));\n const valueArea = profile.valueArea;\n\n const overlay = chart.addOverlay({\n id,\n ...(options.paneId ? { paneId: options.paneId } : {}),\n draw(canvas, frame) {\n if (maxVolume <= 0) {\n return;\n }\n const maxWidth = frame.plot.width * widthRatio;\n for (const bin of profile.bins) {\n if (bin.volume <= 0) {\n continue;\n }\n const top = frame.priceToY(bin.priceHigh);\n const bottom = frame.priceToY(bin.priceLow);\n const height = Math.max(1, Math.abs(bottom - top));\n const width = (bin.volume / maxVolume) * maxWidth;\n const x = side === \"left\" ? frame.plot.left : frame.plot.right - width;\n const inValueArea =\n valueArea !== null && bin.priceMid >= valueArea.low && bin.priceMid <= valueArea.high;\n const isPoc = profile.poc?.index === bin.index;\n canvas.globalAlpha = isPoc ? 0.55 : inValueArea ? 0.4 : 0.22;\n canvas.fillStyle = isPoc ? colors.poc : inValueArea ? colors.valueArea : colors.bar;\n canvas.fillRect(x, Math.min(top, bottom), width, height);\n }\n canvas.globalAlpha = 1;\n },\n });\n\n return {\n id: overlay.id,\n paneId: overlay.paneId,\n requestRender: overlay.requestRender,\n remove: overlay.remove,\n profile,\n };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n","import type { Feature } from \"@wicklib/core\";\n\n/**\n * Features shipped in the commercial tier.\n */\nexport const PRO_FEATURES = [\n \"orderflow\",\n \"volume-profile\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n] as const;\n\n/**\n * A feature name provided by the commercial tier.\n */\nexport type ProFeature = (typeof PRO_FEATURES)[number];\n\n/**\n * Core feature tokens covered by the pro feature list.\n */\nexport const PRO_CORE_FEATURES: readonly Feature[] = PRO_FEATURES;\n","import type { LicenseContext, WickExtension } from \"@wicklib/core\";\n\nimport type { ProFeature } from \"./features\";\nimport { PRO_VERSION } from \"./version\";\n\n/**\n * Extension descriptor for a commercial feature.\n */\nexport interface ProExtension extends WickExtension {\n readonly kind: \"feature\";\n readonly feature: ProFeature;\n}\n\nconst NAMES: Record<ProFeature, string> = {\n orderflow: \"Orderflow\",\n \"volume-profile\": \"Volume Profile\",\n strategy: \"Strategy\",\n alerts: \"Alerts\",\n \"script-functions\": \"Script Functions\",\n};\n\n/**\n * Capability descriptors for the commercial feature set.\n *\n * Hosts pass the granted descriptors through `ChartOptions.extensions`. Individual\n * analytics register their runtime behavior separately.\n */\nexport const PRO_EXTENSIONS: readonly ProExtension[] = Object.freeze(\n ([\"orderflow\", \"volume-profile\", \"strategy\", \"alerts\", \"script-functions\"] as const).map(\n (feature) =>\n Object.freeze({\n kind: \"feature\" as const,\n feature,\n meta: Object.freeze({\n id: `com.wicklib.${feature}`,\n name: NAMES[feature],\n version: PRO_VERSION,\n license: \"pro\" as const,\n }),\n }),\n ),\n);\n\n/**\n * Returns the feature descriptors granted by a license context.\n */\nexport function getProExtensions(context: LicenseContext): readonly ProExtension[] {\n return PRO_EXTENSIONS.filter((extension) => context.hasFeature(extension.feature));\n}\n","import type { Feature, LicenseContext } from \"@wicklib/core\";\n\n/**\n * Decoded payload of a Wicklib license token.\n *\n * Tokens are Ed25519-signed and verified offline. `exp` is seconds since the Unix\n * epoch. `kid` selects the embedded public key.\n */\nexport interface LicenseTokenPayload {\n product: string;\n plan: string;\n seats: number;\n domains: string[];\n exp: number;\n features: Feature[];\n kid: string;\n}\n\n/**\n * Options for creating a license context.\n */\nexport interface LicenseVerifierOptions {\n /** Public keys indexed by `kid`, encoded as base64url raw Ed25519 keys. */\n publicKeys: Readonly<Record<string, string>>;\n /** Clock override for deterministic tests. Returns seconds since the epoch. */\n now?: () => number;\n /** Origin the license is being used from, if domain locking is enabled. */\n domain?: string;\n /** Expected product id. Defaults to wicklib-pro. */\n product?: string;\n}\n\n/**\n * Machine-readable license failure codes.\n */\nexport type LicenseErrorCode =\n | \"CRYPTO_UNAVAILABLE\"\n | \"INVALID_TOKEN\"\n | \"UNSUPPORTED_ALGORITHM\"\n | \"UNKNOWN_KID\"\n | \"INVALID_PAYLOAD\"\n | \"EXPIRED\"\n | \"WRONG_PRODUCT\"\n | \"DOMAIN_REQUIRED\"\n | \"DOMAIN_NOT_ALLOWED\"\n | \"SIGNATURE_INVALID\";\n\n/**\n * Typed license verification failure.\n */\nexport class LicenseError extends Error {\n readonly code: LicenseErrorCode;\n\n constructor(code: LicenseErrorCode, message: string) {\n super(message);\n this.name = \"LicenseError\";\n this.code = code;\n }\n}\n\ninterface LicenseHeader {\n alg: string;\n typ?: string;\n kid?: string;\n}\n\n/**\n * Verifies an Ed25519 license token and returns the feature context used by pro\n * extensions.\n *\n * Verification is fully offline. No network or telemetry calls are made.\n */\nexport async function createLicenseContext(\n token: string,\n options: LicenseVerifierOptions,\n): Promise<LicenseContext> {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token must have three segments\");\n }\n\n const [headerPart, payloadPart, signaturePart] = parts as [string, string, string];\n const header = decodeJson<LicenseHeader>(headerPart, \"INVALID_TOKEN\");\n if (header.alg !== \"Ed25519\") {\n throw new LicenseError(\n \"UNSUPPORTED_ALGORITHM\",\n `Unsupported license algorithm: ${header.alg}`,\n );\n }\n\n const payload = decodeJson<LicenseTokenPayload>(payloadPart, \"INVALID_PAYLOAD\");\n validatePayload(payload);\n\n if (header.kid && header.kid !== payload.kid) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License header and payload kid do not match\");\n }\n\n const publicKey = options.publicKeys[payload.kid];\n if (!publicKey) {\n throw new LicenseError(\"UNKNOWN_KID\", `Unknown license key id: ${payload.kid}`);\n }\n\n const product = options.product ?? \"wicklib-pro\";\n if (payload.product !== product) {\n throw new LicenseError(\n \"WRONG_PRODUCT\",\n `License is for ${payload.product}, expected ${product}`,\n );\n }\n\n const now = options.now?.() ?? Math.floor(Date.now() / 1_000);\n if (payload.exp <= now) {\n throw new LicenseError(\"EXPIRED\", \"License has expired\");\n }\n\n if (payload.domains.length > 0) {\n if (!options.domain) {\n throw new LicenseError(\"DOMAIN_REQUIRED\", \"This license requires a domain\");\n }\n if (!domainAllowed(payload.domains, options.domain)) {\n throw new LicenseError(\n \"DOMAIN_NOT_ALLOWED\",\n `Domain is not covered by the license: ${options.domain}`,\n );\n }\n }\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new LicenseError(\"CRYPTO_UNAVAILABLE\", \"Web Crypto is not available\");\n }\n\n let key: CryptoKey;\n try {\n const raw = base64UrlDecode(publicKey);\n key = await subtle.importKey(\"raw\", raw, { name: \"Ed25519\" }, false, [\"verify\"]);\n } catch (error) {\n throw new LicenseError(\n \"INVALID_PAYLOAD\",\n error instanceof Error ? `Invalid license public key: ${error.message}` : \"Invalid license public key\",\n );\n }\n\n let valid = false;\n try {\n valid = await subtle.verify(\n { name: \"Ed25519\" },\n key,\n base64UrlDecode(signaturePart),\n new TextEncoder().encode(`${headerPart}.${payloadPart}`),\n );\n } catch (error) {\n throw new LicenseError(\n \"SIGNATURE_INVALID\",\n error instanceof Error ? `Signature verification failed: ${error.message}` : \"Signature verification failed\",\n );\n }\n\n if (!valid) {\n throw new LicenseError(\"SIGNATURE_INVALID\", \"License signature is invalid\");\n }\n\n const granted = new Set<Feature>(payload.features);\n return { hasFeature: (feature) => granted.has(feature) };\n}\n\nfunction validatePayload(payload: LicenseTokenPayload): void {\n if (\n !payload ||\n typeof payload.product !== \"string\" ||\n typeof payload.plan !== \"string\" ||\n typeof payload.kid !== \"string\" ||\n payload.kid.length === 0 ||\n !Number.isFinite(payload.exp) ||\n !Number.isInteger(payload.seats) ||\n payload.seats < 1 ||\n !Array.isArray(payload.domains) ||\n payload.domains.some((domain) => typeof domain !== \"string\") ||\n !Array.isArray(payload.features) ||\n payload.features.some((feature) => typeof feature !== \"string\")\n ) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License payload is invalid\");\n }\n}\n\nfunction domainAllowed(domains: readonly string[], host: string): boolean {\n const normalized = normalizeDomain(host);\n return domains.some(\n (domain) => domain === \"*\" || normalizeDomain(domain) === normalized,\n );\n}\n\nfunction normalizeDomain(value: string): string {\n try {\n const url = new URL(value.includes(\"://\") ? value : `https://${value}`);\n return url.hostname.toLowerCase();\n } catch {\n return value.toLowerCase();\n }\n}\n\nfunction decodeJson<T>(value: string, code: LicenseErrorCode): T {\n try {\n return JSON.parse(new TextDecoder().decode(base64UrlDecode(value))) as T;\n } catch {\n throw new LicenseError(code, \"License token contains invalid base64url or JSON\");\n }\n}\n\nfunction base64UrlDecode(value: string): Uint8Array<ArrayBuffer> {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, \"=\");\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n } catch {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token contains invalid base64url\");\n }\n}\n"],"mappings":"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","names":["import_core","import_core","import_core","import_core","import_core","DEFAULT_IMBALANCE_RATIO","imbalanceOf","DEFAULT_BUCKET_MS","import_core","DEFAULT_OPTIONS","import_core"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -497,7 +497,7 @@ declare function addVolumeProfileOverlay(context: LicenseContext, chart: ChartAp
|
|
|
497
497
|
/**
|
|
498
498
|
* Features shipped in the commercial tier.
|
|
499
499
|
*/
|
|
500
|
-
declare const PRO_FEATURES: readonly ["orderflow", "volume-profile", "
|
|
500
|
+
declare const PRO_FEATURES: readonly ["orderflow", "volume-profile", "strategy", "alerts", "script-functions"];
|
|
501
501
|
/**
|
|
502
502
|
* A feature name provided by the commercial tier.
|
|
503
503
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -497,7 +497,7 @@ declare function addVolumeProfileOverlay(context: LicenseContext, chart: ChartAp
|
|
|
497
497
|
/**
|
|
498
498
|
* Features shipped in the commercial tier.
|
|
499
499
|
*/
|
|
500
|
-
declare const PRO_FEATURES: readonly ["orderflow", "volume-profile", "
|
|
500
|
+
declare const PRO_FEATURES: readonly ["orderflow", "volume-profile", "strategy", "alerts", "script-functions"];
|
|
501
501
|
/**
|
|
502
502
|
* A feature name provided by the commercial tier.
|
|
503
503
|
*/
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// package.json
|
|
2
2
|
var package_default = {
|
|
3
3
|
name: "@wicklib/pro",
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.13.0",
|
|
5
5
|
description: "Wicklib commercial add-on",
|
|
6
6
|
license: "SEE LICENSE IN LICENSE",
|
|
7
7
|
type: "module",
|
|
@@ -38,7 +38,7 @@ var package_default = {
|
|
|
38
38
|
directory: "packages/pro"
|
|
39
39
|
},
|
|
40
40
|
peerDependencies: {
|
|
41
|
-
"@wicklib/core": "^0.
|
|
41
|
+
"@wicklib/core": "^0.13.0"
|
|
42
42
|
},
|
|
43
43
|
scripts: {
|
|
44
44
|
build: "tsup",
|
|
@@ -769,8 +769,6 @@ function clamp(value, min, max) {
|
|
|
769
769
|
var PRO_FEATURES = [
|
|
770
770
|
"orderflow",
|
|
771
771
|
"volume-profile",
|
|
772
|
-
"panes",
|
|
773
|
-
"layouts",
|
|
774
772
|
"strategy",
|
|
775
773
|
"alerts",
|
|
776
774
|
"script-functions"
|
|
@@ -781,22 +779,12 @@ var PRO_CORE_FEATURES = PRO_FEATURES;
|
|
|
781
779
|
var NAMES = {
|
|
782
780
|
orderflow: "Orderflow",
|
|
783
781
|
"volume-profile": "Volume Profile",
|
|
784
|
-
panes: "Panes",
|
|
785
|
-
layouts: "Layouts",
|
|
786
782
|
strategy: "Strategy",
|
|
787
783
|
alerts: "Alerts",
|
|
788
784
|
"script-functions": "Script Functions"
|
|
789
785
|
};
|
|
790
786
|
var PRO_EXTENSIONS = Object.freeze(
|
|
791
|
-
[
|
|
792
|
-
"orderflow",
|
|
793
|
-
"volume-profile",
|
|
794
|
-
"panes",
|
|
795
|
-
"layouts",
|
|
796
|
-
"strategy",
|
|
797
|
-
"alerts",
|
|
798
|
-
"script-functions"
|
|
799
|
-
].map(
|
|
787
|
+
["orderflow", "volume-profile", "strategy", "alerts", "script-functions"].map(
|
|
800
788
|
(feature) => Object.freeze({
|
|
801
789
|
kind: "feature",
|
|
802
790
|
feature,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/version.ts","../src/script/backtest.ts","../src/strategy/backtest.ts","../src/alerts/engine.ts","../src/analytics/absorption.ts","../src/analytics/depth.ts","../src/analytics/orderflow.ts","../src/analytics/volume-profile.ts","../src/analytics/volume-profile-overlay.ts","../src/features.ts","../src/extensions.ts","../src/license/verify.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@wicklib/pro\",\n \"version\": \"0.11.0\",\n \"description\": \"Wicklib commercial add-on\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"type\": \"module\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/wicklib/wicklib-pro.git\",\n \"directory\": \"packages/pro\"\n },\n \"peerDependencies\": {\n \"@wicklib/core\": \"^0.11.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"devDependencies\": {\n \"tsup\": \"^9.0.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^5.0.5\"\n }\n}\n","import packageJson from \"../package.json\";\n\n/**\n * Semantic version of the installed pro package.\n */\nexport const PRO_VERSION: string = packageJson.version;\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\nimport {\n runBacktest,\n type BacktestOptions,\n type BacktestResult,\n type StrategyTarget,\n} from \"../strategy/backtest\";\n\n/**\n * One alert emitted by a script, including the bar it belongs to.\n */\nexport interface ScriptAlertEvent {\n time: number;\n barIndex: number;\n message: string;\n}\n\n/**\n * Output required from a compiled script replay.\n *\n * This is structurally compatible with `@wicklib/script`'s `CompiledScript`, without making\n * Pro depend on the script package at runtime.\n */\nexport interface ScriptRunResult {\n plots: Readonly<Record<string, ReadonlyArray<number | null>>>;\n alerts: ReadonlyArray<string>;\n alertEvents?: ReadonlyArray<ScriptAlertEvent>;\n}\n\n/**\n * Minimal compiled-script contract accepted by the adapter.\n */\nexport interface CompiledScriptLike {\n replay(bars: readonly OhlcData[]): Promise<ScriptRunResult>;\n}\n\n/**\n * Options for a script-driven backtest.\n */\nexport interface ScriptBacktestOptions extends BacktestOptions {\n /** Plot id whose values are target positions: -1 short, 0 flat, 1 long, null hold. */\n signalPlot: string;\n}\n\n/**\n * Backtest result plus script alerts.\n */\nexport interface ScriptBacktestResult extends BacktestResult {\n alerts: readonly ScriptAlertEvent[];\n}\n\n/**\n * Runs a compiled script, maps one plot to target positions, and backtests the result.\n *\n * The script must emit positions on the configured plot. Alerts are returned with their\n * source bar so the host can deliver or persist them. Requires the `strategy` feature.\n */\nexport async function runScriptBacktest(\n context: LicenseContext,\n script: CompiledScriptLike,\n bars: readonly OhlcData[],\n options: ScriptBacktestOptions,\n): Promise<ScriptBacktestResult> {\n assertFeature(context, \"strategy\");\n\n if (!script || typeof script.replay !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script adapter requires a replay function\");\n }\n if (typeof options.signalPlot !== \"string\" || options.signalPlot.trim() === \"\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script signalPlot must be a non-empty string\");\n }\n\n const result = await script.replay(bars);\n const values = result?.plots?.[options.signalPlot];\n if (!Array.isArray(values)) {\n throw new WickError(\"INVALID_DATA\", `Script plot not found: ${options.signalPlot}`);\n }\n if (values.length !== bars.length) {\n throw new WickError(\"INVALID_DATA\", \"Script signal plot length must match the bar count\");\n }\n if (result.alerts.length > 0 && !result.alertEvents) {\n throw new WickError(\"INVALID_DATA\", \"Script alerts are missing their bar events\");\n }\n\n const alerts = (result.alertEvents ?? []).map((event) => validateAlert(event));\n const backtest = runBacktest(\n context,\n bars,\n ({ index }): StrategyTarget | undefined => {\n const value = values[index];\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value !== -1 && value !== 0 && value !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Script signal must be -1, 0, 1, or null\");\n }\n return value;\n },\n options,\n );\n\n return { ...backtest, alerts };\n}\n\nfunction validateAlert(event: ScriptAlertEvent): ScriptAlertEvent {\n if (\n !event ||\n !Number.isFinite(event.time) ||\n !Number.isInteger(event.barIndex) ||\n event.barIndex < 0 ||\n typeof event.message !== \"string\"\n ) {\n throw new WickError(\"INVALID_DATA\", \"Invalid script alert event\");\n }\n return { time: event.time, barIndex: event.barIndex, message: event.message };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Target position for a strategy.\n *\n * -1 = fully short\n * 0 = flat\n * 1 = fully long\n */\nexport type StrategyTarget = -1 | 0 | 1;\n\n/**\n * Context passed to a strategy once per closed bar.\n */\nexport interface StrategyContext {\n readonly bar: OhlcData;\n readonly index: number;\n readonly position: StrategyTarget;\n readonly cash: number;\n readonly units: number;\n readonly equity: number;\n}\n\n/**\n * Strategy callback. Return a target to schedule a fill at the next bar open, or\n * `undefined`/`null` to hold the current target.\n */\nexport type StrategyFunction = (context: StrategyContext) => StrategyTarget | null | undefined;\n\n/**\n * Backtest configuration.\n */\nexport interface BacktestOptions {\n /** Starting cash. Required and positive. */\n initialCapital: number;\n /** Fractional fee charged on absolute traded notional. Defaults to 0. */\n feeRate?: number;\n /** Fractional slippage applied against the fill. Defaults to 0. */\n slippage?: number;\n}\n\n/**\n * One executed target change.\n */\nexport interface BacktestFill {\n time: number;\n side: \"buy\" | \"sell\";\n price: number;\n quantity: number;\n fee: number;\n}\n\n/**\n * One marked-to-market equity point.\n */\nexport interface EquityPoint {\n time: number;\n cash: number;\n units: number;\n position: StrategyTarget;\n price: number;\n equity: number;\n}\n\n/**\n * Deterministic strategy backtest result.\n */\nexport interface BacktestResult {\n initialCapital: number;\n finalEquity: number;\n returnPercent: number;\n maxDrawdown: number;\n fills: readonly BacktestFill[];\n equity: readonly EquityPoint[];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<BacktestOptions, \"initialCapital\">> = {\n feeRate: 0,\n slippage: 0,\n};\n\n/**\n * Runs a target-position strategy against closed bars.\n *\n * Signals are evaluated on bar close and filled at the next bar open, preventing\n * lookahead. Position sizing is fully invested at the fill price; leverage is not added.\n * Requires the `strategy` license feature.\n */\nexport function runBacktest(\n context: LicenseContext,\n bars: readonly OhlcData[],\n strategy: StrategyFunction,\n options: BacktestOptions,\n): BacktestResult {\n assertFeature(context, \"strategy\");\n\n const initialCapital = options.initialCapital;\n const feeRate = options.feeRate ?? DEFAULT_OPTIONS.feeRate;\n const slippage = options.slippage ?? DEFAULT_OPTIONS.slippage;\n if (!Number.isFinite(initialCapital) || initialCapital <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest initialCapital must be positive\");\n }\n if (!Number.isFinite(feeRate) || feeRate < 0 || feeRate >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest feeRate must be in [0, 1)\");\n }\n if (!Number.isFinite(slippage) || slippage < 0 || slippage >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest slippage must be in [0, 1)\");\n }\n if (typeof strategy !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest strategy must be a function\");\n }\n\n let cash = initialCapital;\n let units = 0;\n let position: StrategyTarget = 0;\n let pending: StrategyTarget | null = null;\n let previousTime = Number.NEGATIVE_INFINITY;\n const fills: BacktestFill[] = [];\n const equity: EquityPoint[] = [];\n let peak = initialCapital;\n let maxDrawdown = 0;\n\n for (let index = 0; index < bars.length; index += 1) {\n const bar = bars[index]!;\n if (\n !Number.isFinite(bar.time) ||\n bar.time <= previousTime ||\n !Number.isFinite(bar.open) ||\n !Number.isFinite(bar.close) ||\n !Number.isFinite(bar.high) ||\n !Number.isFinite(bar.low)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Backtest bars require ascending finite OHLC values\");\n }\n previousTime = bar.time;\n\n if (pending !== null && pending !== position) {\n const side: \"buy\" | \"sell\" = pending > position ? \"buy\" : \"sell\";\n const price = side === \"buy\" ? bar.open * (1 + slippage) : bar.open * (1 - slippage);\n const equityAtFill = cash + units * price;\n const desiredUnits = (pending * equityAtFill) / price;\n const quantity = desiredUnits - units;\n const fee = Math.abs(quantity * price) * feeRate;\n cash -= quantity * price + fee;\n units = desiredUnits;\n position = pending;\n if (quantity !== 0) {\n fills.push({ time: bar.time, side, price, quantity, fee });\n }\n pending = null;\n }\n\n const markedEquity = cash + units * bar.close;\n peak = Math.max(peak, markedEquity);\n if (peak > 0) {\n maxDrawdown = Math.max(maxDrawdown, (peak - markedEquity) / peak);\n }\n equity.push({\n time: bar.time,\n cash,\n units,\n position,\n price: bar.close,\n equity: markedEquity,\n });\n\n const signal = strategy({\n bar,\n index,\n position,\n cash,\n units,\n equity: markedEquity,\n });\n if (signal !== undefined && signal !== null) {\n if (signal !== -1 && signal !== 0 && signal !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Strategy target must be -1, 0, or 1\");\n }\n pending = signal;\n }\n }\n\n const finalEquity = equity.at(-1)?.equity ?? initialCapital;\n return {\n initialCapital,\n finalEquity,\n returnPercent: ((finalEquity - initialCapital) / initialCapital) * 100,\n maxDrawdown,\n fills,\n equity,\n };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Price field used by a price alert.\n */\nexport type AlertPriceSource = \"close\" | \"high\" | \"low\";\n\n/**\n * Price alert direction.\n *\n * `cross` reports the side that was crossed.\n */\nexport type AlertDirection = \"above\" | \"below\" | \"cross\";\n\n/**\n * A serializable price alert rule.\n */\nexport interface PriceAlertRule {\n readonly id: string;\n readonly price: number;\n readonly direction: AlertDirection;\n /** Defaults to close. */\n readonly source?: AlertPriceSource;\n}\n\n/**\n * A triggered alert.\n */\nexport interface AlertTrigger {\n readonly ruleId: string;\n readonly time: number;\n readonly direction: \"above\" | \"below\";\n readonly price: number;\n readonly value: number;\n readonly bar: OhlcData;\n}\n\nconst SOURCES = new Set<AlertPriceSource>([\"close\", \"high\", \"low\"]);\n\n/**\n * Deterministic, offline alert evaluator for streaming bars.\n *\n * The first bar initializes state and never triggers. Subsequent bars trigger only on a\n * transition so a rule does not fire repeatedly while it remains true.\n */\nexport class AlertEngine {\n private readonly rules: readonly PriceAlertRule[];\n private readonly previous = new Map<string, number>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, rules: readonly PriceAlertRule[]) {\n assertFeature(context, \"alerts\");\n const ids = new Set<string>();\n for (const rule of rules) {\n if (\n !rule ||\n typeof rule.id !== \"string\" ||\n rule.id.trim() === \"\" ||\n !Number.isFinite(rule.price) ||\n (rule.direction !== \"above\" && rule.direction !== \"below\" && rule.direction !== \"cross\") ||\n (rule.source !== undefined && !SOURCES.has(rule.source))\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Invalid price alert rule\");\n }\n if (ids.has(rule.id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Duplicate alert rule id: ${rule.id}`);\n }\n ids.add(rule.id);\n }\n this.rules = rules.map((rule) => ({ ...rule }));\n }\n\n /**\n * Consumes one closed bar and returns the alerts triggered by that bar.\n */\n update(bar: OhlcData): readonly AlertTrigger[] {\n if (!Number.isFinite(bar.time)) {\n throw new WickError(\"INVALID_DATA\", \"Alert bar requires a finite time\");\n }\n if (bar.time <= this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Alert bars must have increasing times\");\n }\n this.lastTime = bar.time;\n\n const triggers: AlertTrigger[] = [];\n for (const rule of this.rules) {\n const source = rule.source ?? \"close\";\n const value = source === \"close\" ? bar.close : source === \"high\" ? bar.high : bar.low;\n const previous = this.previous.get(rule.id);\n if (previous !== undefined) {\n if (rule.direction === \"above\" && previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (rule.direction === \"below\" && previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n } else if (rule.direction === \"cross\") {\n if (previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n }\n }\n }\n this.previous.set(rule.id, value);\n }\n\n return triggers;\n }\n\n /**\n * Clears previous values so the next bar initializes state again.\n */\n reset(): void {\n this.previous.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Evaluates a batch of closed bars through the same streaming alert path.\n */\nexport function evaluateAlerts(\n context: LicenseContext,\n rules: readonly PriceAlertRule[],\n bars: readonly OhlcData[],\n): readonly AlertTrigger[] {\n const engine = new AlertEngine(context, rules);\n const triggers: AlertTrigger[] = [];\n for (const bar of bars) {\n triggers.push(...engine.update(bar));\n }\n return triggers;\n}\n\nfunction trigger(\n rule: PriceAlertRule,\n bar: OhlcData,\n value: number,\n direction: \"above\" | \"below\",\n): AlertTrigger {\n return {\n ruleId: rule.id,\n time: bar.time,\n direction,\n price: rule.price,\n value,\n bar,\n };\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\nimport { DepthAggregator, type DepthSnapshot } from \"./depth\";\nimport { FootprintAggregator, type TradeTick, type TradeSide } from \"./orderflow\";\n\n/**\n * Options for absorption detection.\n */\nexport interface AbsorptionOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Aggressive volume must reach passive size × this ratio. Defaults to 2. */\n absorptionRatio?: number;\n}\n\n/**\n * A detected absorption event.\n */\nexport interface AbsorptionEvent {\n /** Bucket start time in milliseconds. */\n time: number;\n priceLow: number;\n priceHigh: number;\n /** Aggressor side that was absorbed. */\n side: TradeSide;\n /** Aggressive trade volume in the bucket and level. */\n aggressiveVolume: number;\n /** Passive book size at the level when the bucket completed. */\n passiveVolume: number;\n /** aggressiveVolume / passiveVolume. */\n ratio: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_ABSORPTION_RATIO = 2;\n\n/**\n * Detects aggressive volume absorbed by passive L2 liquidity.\n *\n * For each footprint bucket and price level:\n * - aggressive buys are compared with ask depth\n * - aggressive sells are compared with bid depth\n *\n * A level is reported when aggressive volume is at least the configured multiple of the\n * passive size. Requires the `orderflow` license feature.\n */\nexport function detectAbsorption(\n context: LicenseContext,\n trades: readonly TradeTick[],\n snapshots: readonly DepthSnapshot[],\n options: AbsorptionOptions,\n): readonly AbsorptionEvent[] {\n assertFeature(context, \"orderflow\");\n\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const absorptionRatio = options.absorptionRatio ?? DEFAULT_ABSORPTION_RATIO;\n const priceStep = options.priceStep;\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption bucketMs must be a positive integer\");\n }\n if (!Number.isFinite(absorptionRatio) || absorptionRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption ratio must be at least 1\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption priceStep must be a positive number\");\n }\n\n const footprints = new FootprintAggregator(context, {\n bucketMs,\n priceStep,\n });\n for (const trade of [...trades].sort((first, second) => first.time - second.time)) {\n footprints.push(trade);\n }\n\n const depth = new DepthAggregator(context, { priceStep });\n for (const snapshot of [...snapshots].sort((first, second) => first.time - second.time)) {\n depth.push(snapshot);\n }\n\n const events: AbsorptionEvent[] = [];\n for (const bar of footprints.getBars()) {\n const book = depth.latest(bar.time + bucketMs - 1);\n if (!book) {\n continue;\n }\n const depthByPrice = new Map(book.levels.map((level) => [level.priceLow, level]));\n for (const level of bar.levels) {\n const depthLevel = depthByPrice.get(level.priceLow);\n if (!depthLevel) {\n continue;\n }\n const candidates: Array<{\n side: TradeSide;\n aggressive: number;\n passive: number;\n }> = [\n { side: \"buy\", aggressive: level.buyVolume, passive: depthLevel.askSize },\n { side: \"sell\", aggressive: level.sellVolume, passive: depthLevel.bidSize },\n ];\n for (const candidate of candidates) {\n if (candidate.passive <= 0 || candidate.aggressive <= 0) {\n continue;\n }\n const ratio = candidate.aggressive / candidate.passive;\n if (ratio >= absorptionRatio) {\n events.push({\n time: bar.time,\n priceLow: level.priceLow,\n priceHigh: level.priceHigh,\n side: candidate.side,\n aggressiveVolume: candidate.aggressive,\n passiveVolume: candidate.passive,\n ratio,\n });\n }\n }\n }\n }\n\n return events;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * One side of a Level-2 depth snapshot.\n */\nexport interface DepthLevel {\n price: number;\n size: number;\n}\n\n/**\n * A full bid/ask book snapshot at a point in time.\n */\nexport interface DepthSnapshot {\n /** Unix timestamp in milliseconds. */\n time: number;\n bids: readonly DepthLevel[];\n asks: readonly DepthLevel[];\n}\n\n/**\n * Aggregated bid/ask liquidity by price bucket.\n */\nexport interface DepthLevelBar {\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n}\n\n/**\n * Aggregated depth for one snapshot.\n */\nexport interface DepthBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n levels: readonly DepthLevelBar[];\n}\n\n/**\n * Options for depth aggregation.\n */\nexport interface DepthOptions {\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies total book pressure as imbalanced. Defaults to 2. */\n imbalanceRatio?: number;\n}\n\nconst DEFAULT_IMBALANCE_RATIO = 2;\n\n/**\n * Incremental L2 depth aggregator.\n *\n * Snapshots are complete books, so newer snapshots replace the current view rather than\n * accumulate. Non-decreasing timestamps are enforced.\n */\nexport class DepthAggregator {\n private readonly options: Required<DepthOptions>;\n private readonly bars = new Map<number, DepthBar>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: DepthOptions) {\n assertFeature(context, \"orderflow\");\n if (\n options.priceStep === undefined ||\n !Number.isFinite(options.priceStep) ||\n options.priceStep <= 0\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth priceStep must be a positive number\");\n }\n const ratio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n if (!Number.isFinite(ratio) || ratio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth imbalanceRatio must be at least 1\");\n }\n this.options = { priceStep: options.priceStep, imbalanceRatio: ratio };\n }\n\n /**\n * Adds or replaces one complete snapshot and returns its aggregated bar.\n */\n push(snapshot: DepthSnapshot): DepthBar {\n if (\n !Number.isFinite(snapshot.time) ||\n !Array.isArray(snapshot.bids) ||\n !Array.isArray(snapshot.asks)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots require finite time, bids, and asks\");\n }\n if (snapshot.time < this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots must be in non-decreasing time order\");\n }\n this.lastTime = snapshot.time;\n\n const levels = new Map<number, { bid: number; ask: number }>();\n for (const [side, entries] of [\n [\"bid\", snapshot.bids],\n [\"ask\", snapshot.asks],\n ] as const) {\n for (const entry of entries) {\n if (!Number.isFinite(entry.price) || !Number.isFinite(entry.size) || entry.size < 0) {\n throw new WickError(\n \"INVALID_DATA\",\n \"Depth levels require finite price and non-negative size\",\n );\n }\n const price = Math.floor(entry.price / this.options.priceStep) * this.options.priceStep;\n let level = levels.get(price);\n if (!level) {\n level = { bid: 0, ask: 0 };\n levels.set(price, level);\n }\n if (side === \"bid\") level.bid += entry.size;\n else level.ask += entry.size;\n }\n }\n\n let bidSize = 0;\n let askSize = 0;\n const sortedLevels: DepthLevelBar[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, level]) => {\n bidSize += level.bid;\n askSize += level.ask;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n bidSize: level.bid,\n askSize: level.ask,\n totalSize: level.bid + level.ask,\n delta: level.bid - level.ask,\n imbalance: imbalanceOf(level.bid, level.ask, this.options.imbalanceRatio),\n };\n });\n\n const bar: DepthBar = {\n time: snapshot.time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n bidSize,\n askSize,\n totalSize: bidSize + askSize,\n delta: bidSize - askSize,\n imbalance: imbalanceOf(bidSize, askSize, this.options.imbalanceRatio),\n levels: sortedLevels,\n };\n this.bars.set(snapshot.time, bar);\n return bar;\n }\n\n /**\n * Returns the latest snapshot at or before a time.\n */\n latest(time = Number.POSITIVE_INFINITY): DepthBar | null {\n const eligible = [...this.bars.values()]\n .filter((bar) => bar.time <= time)\n .sort((first, second) => first.time - second.time);\n return eligible.at(-1) ?? null;\n }\n\n /**\n * Returns all snapshots in ascending time order.\n */\n getBars(): readonly DepthBar[] {\n return [...this.bars.values()].sort((first, second) => first.time - second.time);\n }\n\n /**\n * Clears all snapshots and the streaming order guard.\n */\n reset(): void {\n this.bars.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Aggregates a batch of complete L2 book snapshots.\n *\n * Requires the `orderflow` license feature.\n */\nexport function computeDepth(\n context: LicenseContext,\n snapshots: readonly DepthSnapshot[],\n options: DepthOptions,\n): readonly DepthBar[] {\n const aggregator = new DepthAggregator(context, options);\n for (const snapshot of snapshots) {\n aggregator.push(snapshot);\n }\n return aggregator.getBars();\n}\n\nfunction imbalanceOf(bid: number, ask: number, ratio: number): \"bid\" | \"ask\" | null {\n if (bid === 0 && ask === 0) return null;\n if (ask === 0) return \"bid\";\n if (bid === 0) return \"ask\";\n if (bid >= ask * ratio) return \"bid\";\n if (ask >= bid * ratio) return \"ask\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Aggressor side of a trade tick.\n */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/**\n * Minimal trade tick accepted by the orderflow aggregator.\n */\nexport interface TradeTick {\n /** Unix timestamp in milliseconds. */\n time: number;\n price: number;\n size: number;\n side: TradeSide;\n}\n\n/**\n * Orderflow aggregation options.\n */\nexport interface FootprintOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies a level as imbalanced. Defaults to 3. */\n imbalanceRatio?: number;\n}\n\n/**\n * One price level in a footprint bar.\n */\nexport interface FootprintLevel {\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n imbalance: TradeSide | null;\n}\n\n/**\n * Aggregated footprint for one time bucket.\n */\nexport interface FootprintBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n levels: readonly FootprintLevel[];\n}\n\ninterface ResolvedOptions {\n bucketMs: number;\n priceStep: number;\n imbalanceRatio: number;\n}\n\ninterface LevelVolumes {\n buy: number;\n sell: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_IMBALANCE_RATIO = 3;\n\n/**\n * Incremental trade-tick footprint aggregator.\n *\n * Trades must arrive in non-decreasing time order. Ticks in the same bucket update the\n * same bar, so streaming and batch aggregation share the same code path.\n */\nexport class FootprintAggregator {\n private readonly options: ResolvedOptions;\n private readonly levels = new Map<number, Map<number, LevelVolumes>>();\n private lastTradeTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: FootprintOptions) {\n assertFeature(context, \"orderflow\");\n this.options = resolveOptions(options);\n }\n\n /**\n * Adds one trade and returns the updated bar for its time bucket.\n */\n push(trade: TradeTick): FootprintBar {\n this.validateTrade(trade);\n if (trade.time < this.lastTradeTime) {\n throw new WickError(\"INVALID_DATA\", \"Streaming trades must be in non-decreasing time order\");\n }\n this.lastTradeTime = trade.time;\n\n const time = Math.floor(trade.time / this.options.bucketMs) * this.options.bucketMs;\n const price = Math.floor(trade.price / this.options.priceStep) * this.options.priceStep;\n let levels = this.levels.get(time);\n if (!levels) {\n levels = new Map();\n this.levels.set(time, levels);\n }\n let level = levels.get(price);\n if (!level) {\n level = { buy: 0, sell: 0 };\n levels.set(price, level);\n }\n if (trade.side === \"buy\") level.buy += trade.size;\n else level.sell += trade.size;\n\n return this.buildBar(time)!;\n }\n\n /**\n * Adds multiple trades in input order.\n */\n pushMany(trades: readonly TradeTick[]): readonly FootprintBar[] {\n for (const trade of trades) {\n this.push(trade);\n }\n return this.getBars();\n }\n\n /**\n * Returns a bar by bucket start time, or any time inside that bucket.\n */\n getBar(time: number): FootprintBar | null {\n const bucket = Math.floor(time / this.options.bucketMs) * this.options.bucketMs;\n return this.buildBar(bucket);\n }\n\n /**\n * Returns all completed/current buckets in ascending time order.\n */\n getBars(): readonly FootprintBar[] {\n return [...this.levels.keys()]\n .sort((first, second) => first - second)\n .map((time) => this.buildBar(time))\n .filter((bar): bar is FootprintBar => bar !== null);\n }\n\n /**\n * Clears all trades and resets the streaming order guard.\n */\n reset(): void {\n this.levels.clear();\n this.lastTradeTime = Number.NEGATIVE_INFINITY;\n }\n\n private buildBar(time: number): FootprintBar | null {\n const levels = this.levels.get(time);\n if (!levels) {\n return null;\n }\n\n let buyVolume = 0;\n let sellVolume = 0;\n const sortedLevels: FootprintLevel[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, volumes]) => {\n buyVolume += volumes.buy;\n sellVolume += volumes.sell;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n buyVolume: volumes.buy,\n sellVolume: volumes.sell,\n totalVolume: volumes.buy + volumes.sell,\n delta: volumes.buy - volumes.sell,\n imbalance: imbalanceOf(volumes.buy, volumes.sell, this.options.imbalanceRatio),\n };\n });\n\n return {\n time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n buyVolume,\n sellVolume,\n totalVolume: buyVolume + sellVolume,\n delta: buyVolume - sellVolume,\n levels: sortedLevels,\n };\n }\n\n private validateTrade(trade: TradeTick): void {\n if (\n !Number.isFinite(trade.time) ||\n !Number.isFinite(trade.price) ||\n !Number.isFinite(trade.size) ||\n trade.size <= 0 ||\n trade.price < 0 ||\n (trade.side !== \"buy\" && trade.side !== \"sell\")\n ) {\n throw new WickError(\"INVALID_DATA\", \"Trade ticks require finite time, price, size, and side\");\n }\n }\n}\n\n/**\n * Aggregates trade ticks into bid/ask footprint bars with delta and imbalance.\n *\n * Requires the `orderflow` license feature. Trades are sorted by time before aggregation.\n */\nexport function computeFootprint(\n context: LicenseContext,\n trades: readonly TradeTick[],\n options: FootprintOptions,\n): readonly FootprintBar[] {\n const aggregator = new FootprintAggregator(context, options);\n return aggregator.pushMany([...trades].sort((first, second) => first.time - second.time));\n}\n\nfunction resolveOptions(options: FootprintOptions): ResolvedOptions {\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const priceStep = options.priceStep;\n const imbalanceRatio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint bucketMs must be a positive integer\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint priceStep must be a positive number\");\n }\n if (!Number.isFinite(imbalanceRatio) || imbalanceRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint imbalanceRatio must be at least 1\");\n }\n return { bucketMs, priceStep, imbalanceRatio };\n}\n\nfunction imbalanceOf(buy: number, sell: number, ratio: number): TradeSide | null {\n if (buy === 0 && sell === 0) return null;\n if (sell === 0) return \"buy\";\n if (buy === 0) return \"sell\";\n if (buy >= sell * ratio) return \"buy\";\n if (sell >= buy * ratio) return \"sell\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Volume distribution model.\n *\n * `uniform` spreads each bar's volume evenly across its price range. `close` assigns the\n * whole bar volume to the bin containing the close.\n */\nexport type VolumeProfileDistribution = \"uniform\" | \"close\";\n\n/**\n * Options for {@link computeVolumeProfile}.\n */\nexport interface VolumeProfileOptions {\n /** Number of equal-width price bins. Defaults to 24. */\n bins?: number;\n /** Fixed price range. Defaults to the bars' low/high span. */\n priceRange?: { min: number; max: number };\n /** Fraction of total volume covered by the value area. Defaults to 0.7. */\n valueArea?: number;\n /** Volume distribution model. Defaults to uniform. */\n distribution?: VolumeProfileDistribution;\n}\n\n/**\n * One price bucket in a volume profile.\n */\nexport interface VolumeProfileBin {\n index: number;\n priceLow: number;\n priceHigh: number;\n priceMid: number;\n volume: number;\n}\n\n/**\n * Computed volume profile.\n */\nexport interface VolumeProfile {\n bins: readonly VolumeProfileBin[];\n range: { min: number; max: number };\n totalVolume: number;\n /** Point of control, or null when there is no volume. */\n poc: VolumeProfileBin | null;\n valueArea: {\n low: number;\n high: number;\n volume: number;\n } | null;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<VolumeProfileOptions, \"priceRange\">> = {\n bins: 24,\n valueArea: 0.7,\n distribution: \"uniform\",\n};\n\n/**\n * Computes a deterministic volume profile from OHLCV bars.\n *\n * Requires the `volume-profile` license feature. Bars without a finite positive volume are\n * ignored. Throws `WickError(\"INVALID_DATA\")` when no usable volume remains.\n */\nexport function computeVolumeProfile(\n context: LicenseContext,\n bars: readonly OhlcData[],\n options: VolumeProfileOptions = {},\n): VolumeProfile {\n assertFeature(context, \"volume-profile\");\n\n const binCount = options.bins ?? DEFAULT_OPTIONS.bins;\n const valueAreaFraction = options.valueArea ?? DEFAULT_OPTIONS.valueArea;\n const distribution = options.distribution ?? DEFAULT_OPTIONS.distribution;\n\n if (!Number.isInteger(binCount) || binCount <= 0 || binCount > 2_000) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile bins must be between 1 and 2000\");\n }\n if (!Number.isFinite(valueAreaFraction) || valueAreaFraction <= 0 || valueAreaFraction > 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile valueArea must be in (0, 1]\");\n }\n\n let min: number;\n let max: number;\n if (options.priceRange) {\n min = options.priceRange.min;\n max = options.priceRange.max;\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile priceRange must have max > min\");\n }\n } else {\n min = Number.POSITIVE_INFINITY;\n max = Number.NEGATIVE_INFINITY;\n for (const bar of bars) {\n if (!Number.isFinite(bar.volume) || bar.volume! <= 0) continue;\n min = Math.min(min, bar.low);\n max = Math.max(max, bar.high);\n }\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n if (max <= min) {\n max = min + 1;\n }\n }\n\n const width = (max - min) / binCount;\n const volumes = new Array<number>(binCount).fill(0);\n\n for (const bar of bars) {\n const volume = bar.volume;\n if (!Number.isFinite(volume) || volume === undefined || volume <= 0) continue;\n if (distribution === \"close\") {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const low = Math.max(bar.low, min);\n const high = Math.min(bar.high, max);\n if (high <= low) {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const first = clampIndex(Math.floor((low - min) / width), binCount);\n const last = clampIndex(Math.floor((high - min) / width), binCount);\n let assigned = 0;\n for (let index = first; index <= last; index += 1) {\n const binLow = min + index * width;\n const binHigh = index === binCount - 1 ? max : binLow + width;\n const overlap = Math.max(0, Math.min(high, binHigh) - Math.max(low, binLow));\n const part = index === last ? volume - assigned : (volume * overlap) / (high - low);\n volumes[index]! += part;\n assigned += part;\n }\n }\n\n const totalVolume = volumes.reduce((sum, value) => sum + value, 0);\n if (!(totalVolume > 0)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n\n const bins: VolumeProfileBin[] = volumes.map((volume, index) => ({\n index,\n priceLow: min + index * width,\n priceHigh: index === binCount - 1 ? max : min + (index + 1) * width,\n priceMid: min + (index + 0.5) * width,\n volume,\n }));\n\n let pocIndex = 0;\n for (let index = 1; index < bins.length; index += 1) {\n if (bins[index]!.volume > bins[pocIndex]!.volume) {\n pocIndex = index;\n }\n }\n\n const target = totalVolume * valueAreaFraction;\n let lowIndex = pocIndex;\n let highIndex = pocIndex;\n let valueVolume = bins[pocIndex]!.volume;\n\n while (valueVolume < target && (lowIndex > 0 || highIndex < bins.length - 1)) {\n const lower = lowIndex > 0 ? bins[lowIndex - 1]!.volume : -1;\n const upper = highIndex < bins.length - 1 ? bins[highIndex + 1]!.volume : -1;\n if (upper > lower) {\n highIndex += 1;\n valueVolume += bins[highIndex]!.volume;\n } else {\n lowIndex -= 1;\n valueVolume += bins[lowIndex]!.volume;\n }\n }\n\n return {\n bins,\n range: { min, max },\n totalVolume,\n poc: bins[pocIndex] ?? null,\n valueArea: {\n low: bins[lowIndex]!.priceLow,\n high: bins[highIndex]!.priceHigh,\n volume: valueVolume,\n },\n };\n}\n\nfunction clampIndex(value: number, count: number): number {\n return Math.max(0, Math.min(count - 1, value));\n}\n","import type { ChartApi, ChartOverlayApi, LicenseContext, OhlcData } from \"@wicklib/core\";\n\nimport {\n computeVolumeProfile,\n type VolumeProfile,\n type VolumeProfileOptions,\n} from \"./volume-profile\";\n\n/**\n * Colors used by the volume-profile overlay.\n */\nexport interface VolumeProfileOverlayColors {\n bar: string;\n valueArea: string;\n poc: string;\n}\n\n/**\n * Options for {@link addVolumeProfileOverlay}.\n */\nexport interface VolumeProfileOverlayOptions extends VolumeProfileOptions {\n /** Overlay id. Defaults to a unique pro id. */\n id?: string;\n /** Pane to draw in. Defaults to the main pane. */\n paneId?: string;\n /** Histogram side. Defaults to the left side. */\n side?: \"left\" | \"right\";\n /** Histogram width as a fraction of the pane plot width. Defaults to 0.22. */\n widthRatio?: number;\n colors?: Partial<VolumeProfileOverlayColors>;\n}\n\n/**\n * Live volume-profile overlay.\n */\nexport interface VolumeProfileOverlay extends ChartOverlayApi {\n readonly profile: VolumeProfile;\n}\n\nconst DEFAULT_COLORS: VolumeProfileOverlayColors = {\n bar: \"#2962ff\",\n valueArea: \"#2962ff\",\n poc: \"#f0b90b\",\n};\n\nlet overlayCounter = 0;\n\n/**\n * Computes a volume profile and adds it to a chart as a clipped pane overlay.\n *\n * Requires the `volume-profile` license feature.\n */\nexport function addVolumeProfileOverlay(\n context: LicenseContext,\n chart: ChartApi,\n bars: readonly OhlcData[],\n options: VolumeProfileOverlayOptions = {},\n): VolumeProfileOverlay {\n const profile = computeVolumeProfile(context, bars, options);\n overlayCounter += 1;\n const id = options.id ?? `com.wicklib.volume-profile-${overlayCounter}`;\n const side = options.side ?? \"left\";\n const widthRatio = clamp(options.widthRatio ?? 0.22, 0.02, 0.9);\n const colors = { ...DEFAULT_COLORS, ...options.colors };\n const maxVolume = Math.max(0, ...profile.bins.map((bin) => bin.volume));\n const valueArea = profile.valueArea;\n\n const overlay = chart.addOverlay({\n id,\n ...(options.paneId ? { paneId: options.paneId } : {}),\n draw(canvas, frame) {\n if (maxVolume <= 0) {\n return;\n }\n const maxWidth = frame.plot.width * widthRatio;\n for (const bin of profile.bins) {\n if (bin.volume <= 0) {\n continue;\n }\n const top = frame.priceToY(bin.priceHigh);\n const bottom = frame.priceToY(bin.priceLow);\n const height = Math.max(1, Math.abs(bottom - top));\n const width = (bin.volume / maxVolume) * maxWidth;\n const x = side === \"left\" ? frame.plot.left : frame.plot.right - width;\n const inValueArea =\n valueArea !== null && bin.priceMid >= valueArea.low && bin.priceMid <= valueArea.high;\n const isPoc = profile.poc?.index === bin.index;\n canvas.globalAlpha = isPoc ? 0.55 : inValueArea ? 0.4 : 0.22;\n canvas.fillStyle = isPoc ? colors.poc : inValueArea ? colors.valueArea : colors.bar;\n canvas.fillRect(x, Math.min(top, bottom), width, height);\n }\n canvas.globalAlpha = 1;\n },\n });\n\n return {\n id: overlay.id,\n paneId: overlay.paneId,\n requestRender: overlay.requestRender,\n remove: overlay.remove,\n profile,\n };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n","import type { Feature } from \"@wicklib/core\";\n\n/**\n * Features shipped in the commercial tier.\n */\nexport const PRO_FEATURES = [\n \"orderflow\",\n \"volume-profile\",\n \"panes\",\n \"layouts\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n] as const;\n\n/**\n * A feature name provided by the commercial tier.\n */\nexport type ProFeature = (typeof PRO_FEATURES)[number];\n\n/**\n * Core feature tokens covered by the pro feature list.\n */\nexport const PRO_CORE_FEATURES: readonly Feature[] = PRO_FEATURES;\n","import type { LicenseContext, WickExtension } from \"@wicklib/core\";\n\nimport type { ProFeature } from \"./features\";\nimport { PRO_VERSION } from \"./version\";\n\n/**\n * Extension descriptor for a commercial feature.\n */\nexport interface ProExtension extends WickExtension {\n readonly kind: \"feature\";\n readonly feature: ProFeature;\n}\n\nconst NAMES: Record<ProFeature, string> = {\n orderflow: \"Orderflow\",\n \"volume-profile\": \"Volume Profile\",\n panes: \"Panes\",\n layouts: \"Layouts\",\n strategy: \"Strategy\",\n alerts: \"Alerts\",\n \"script-functions\": \"Script Functions\",\n};\n\n/**\n * Capability descriptors for the commercial feature set.\n *\n * Hosts pass the granted descriptors through `ChartOptions.extensions`. Individual\n * analytics register their runtime behavior separately.\n */\nexport const PRO_EXTENSIONS: readonly ProExtension[] = Object.freeze(\n (\n [\n \"orderflow\",\n \"volume-profile\",\n \"panes\",\n \"layouts\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n ] as const\n ).map((feature) =>\n Object.freeze({\n kind: \"feature\" as const,\n feature,\n meta: Object.freeze({\n id: `com.wicklib.${feature}`,\n name: NAMES[feature],\n version: PRO_VERSION,\n license: \"pro\" as const,\n }),\n }),\n ),\n);\n\n/**\n * Returns the feature descriptors granted by a license context.\n */\nexport function getProExtensions(context: LicenseContext): readonly ProExtension[] {\n return PRO_EXTENSIONS.filter((extension) => context.hasFeature(extension.feature));\n}\n","import type { Feature, LicenseContext } from \"@wicklib/core\";\n\n/**\n * Decoded payload of a Wicklib license token.\n *\n * Tokens are Ed25519-signed and verified offline. `exp` is seconds since the Unix\n * epoch. `kid` selects the embedded public key.\n */\nexport interface LicenseTokenPayload {\n product: string;\n plan: string;\n seats: number;\n domains: string[];\n exp: number;\n features: Feature[];\n kid: string;\n}\n\n/**\n * Options for creating a license context.\n */\nexport interface LicenseVerifierOptions {\n /** Public keys indexed by `kid`, encoded as base64url raw Ed25519 keys. */\n publicKeys: Readonly<Record<string, string>>;\n /** Clock override for deterministic tests. Returns seconds since the epoch. */\n now?: () => number;\n /** Origin the license is being used from, if domain locking is enabled. */\n domain?: string;\n /** Expected product id. Defaults to wicklib-pro. */\n product?: string;\n}\n\n/**\n * Machine-readable license failure codes.\n */\nexport type LicenseErrorCode =\n | \"CRYPTO_UNAVAILABLE\"\n | \"INVALID_TOKEN\"\n | \"UNSUPPORTED_ALGORITHM\"\n | \"UNKNOWN_KID\"\n | \"INVALID_PAYLOAD\"\n | \"EXPIRED\"\n | \"WRONG_PRODUCT\"\n | \"DOMAIN_REQUIRED\"\n | \"DOMAIN_NOT_ALLOWED\"\n | \"SIGNATURE_INVALID\";\n\n/**\n * Typed license verification failure.\n */\nexport class LicenseError extends Error {\n readonly code: LicenseErrorCode;\n\n constructor(code: LicenseErrorCode, message: string) {\n super(message);\n this.name = \"LicenseError\";\n this.code = code;\n }\n}\n\ninterface LicenseHeader {\n alg: string;\n typ?: string;\n kid?: string;\n}\n\n/**\n * Verifies an Ed25519 license token and returns the feature context used by pro\n * extensions.\n *\n * Verification is fully offline. No network or telemetry calls are made.\n */\nexport async function createLicenseContext(\n token: string,\n options: LicenseVerifierOptions,\n): Promise<LicenseContext> {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token must have three segments\");\n }\n\n const [headerPart, payloadPart, signaturePart] = parts as [string, string, string];\n const header = decodeJson<LicenseHeader>(headerPart, \"INVALID_TOKEN\");\n if (header.alg !== \"Ed25519\") {\n throw new LicenseError(\n \"UNSUPPORTED_ALGORITHM\",\n `Unsupported license algorithm: ${header.alg}`,\n );\n }\n\n const payload = decodeJson<LicenseTokenPayload>(payloadPart, \"INVALID_PAYLOAD\");\n validatePayload(payload);\n\n if (header.kid && header.kid !== payload.kid) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License header and payload kid do not match\");\n }\n\n const publicKey = options.publicKeys[payload.kid];\n if (!publicKey) {\n throw new LicenseError(\"UNKNOWN_KID\", `Unknown license key id: ${payload.kid}`);\n }\n\n const product = options.product ?? \"wicklib-pro\";\n if (payload.product !== product) {\n throw new LicenseError(\n \"WRONG_PRODUCT\",\n `License is for ${payload.product}, expected ${product}`,\n );\n }\n\n const now = options.now?.() ?? Math.floor(Date.now() / 1_000);\n if (payload.exp <= now) {\n throw new LicenseError(\"EXPIRED\", \"License has expired\");\n }\n\n if (payload.domains.length > 0) {\n if (!options.domain) {\n throw new LicenseError(\"DOMAIN_REQUIRED\", \"This license requires a domain\");\n }\n if (!domainAllowed(payload.domains, options.domain)) {\n throw new LicenseError(\n \"DOMAIN_NOT_ALLOWED\",\n `Domain is not covered by the license: ${options.domain}`,\n );\n }\n }\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new LicenseError(\"CRYPTO_UNAVAILABLE\", \"Web Crypto is not available\");\n }\n\n let key: CryptoKey;\n try {\n const raw = base64UrlDecode(publicKey);\n key = await subtle.importKey(\"raw\", raw, { name: \"Ed25519\" }, false, [\"verify\"]);\n } catch (error) {\n throw new LicenseError(\n \"INVALID_PAYLOAD\",\n error instanceof Error ? `Invalid license public key: ${error.message}` : \"Invalid license public key\",\n );\n }\n\n let valid = false;\n try {\n valid = await subtle.verify(\n { name: \"Ed25519\" },\n key,\n base64UrlDecode(signaturePart),\n new TextEncoder().encode(`${headerPart}.${payloadPart}`),\n );\n } catch (error) {\n throw new LicenseError(\n \"SIGNATURE_INVALID\",\n error instanceof Error ? `Signature verification failed: ${error.message}` : \"Signature verification failed\",\n );\n }\n\n if (!valid) {\n throw new LicenseError(\"SIGNATURE_INVALID\", \"License signature is invalid\");\n }\n\n const granted = new Set<Feature>(payload.features);\n return { hasFeature: (feature) => granted.has(feature) };\n}\n\nfunction validatePayload(payload: LicenseTokenPayload): void {\n if (\n !payload ||\n typeof payload.product !== \"string\" ||\n typeof payload.plan !== \"string\" ||\n typeof payload.kid !== \"string\" ||\n payload.kid.length === 0 ||\n !Number.isFinite(payload.exp) ||\n !Number.isInteger(payload.seats) ||\n payload.seats < 1 ||\n !Array.isArray(payload.domains) ||\n payload.domains.some((domain) => typeof domain !== \"string\") ||\n !Array.isArray(payload.features) ||\n payload.features.some((feature) => typeof feature !== \"string\")\n ) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License payload is invalid\");\n }\n}\n\nfunction domainAllowed(domains: readonly string[], host: string): boolean {\n const normalized = normalizeDomain(host);\n return domains.some(\n (domain) => domain === \"*\" || normalizeDomain(domain) === normalized,\n );\n}\n\nfunction normalizeDomain(value: string): string {\n try {\n const url = new URL(value.includes(\"://\") ? value : `https://${value}`);\n return url.hostname.toLowerCase();\n } catch {\n return value.toLowerCase();\n }\n}\n\nfunction decodeJson<T>(value: string, code: LicenseErrorCode): T {\n try {\n return JSON.parse(new TextDecoder().decode(base64UrlDecode(value))) as T;\n } catch {\n throw new LicenseError(code, \"License token contains invalid base64url or JSON\");\n }\n}\n\nfunction base64UrlDecode(value: string): Uint8Array<ArrayBuffer> {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, \"=\");\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n } catch {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token contains invalid base64url\");\n }\n}\n","/**\n * Wicklib Pro public API.\n *\n * The package is published to npm under the Wicklib Commercial License; its source\n * repository is private.\n */\n\nexport { PRO_VERSION } from \"./version\";\nexport { runScriptBacktest } from \"./script/backtest\";\nexport type {\n CompiledScriptLike,\n ScriptAlertEvent,\n ScriptBacktestOptions,\n ScriptBacktestResult,\n ScriptRunResult,\n} from \"./script/backtest\";\nexport { runBacktest } from \"./strategy/backtest\";\nexport type {\n BacktestFill,\n BacktestOptions,\n BacktestResult,\n EquityPoint,\n StrategyContext,\n StrategyFunction,\n StrategyTarget,\n} from \"./strategy/backtest\";\nexport { AlertEngine, evaluateAlerts } from \"./alerts/engine\";\nexport type {\n AlertDirection,\n AlertPriceSource,\n AlertTrigger,\n PriceAlertRule,\n} from \"./alerts/engine\";\nexport { detectAbsorption } from \"./analytics/absorption\";\nexport type { AbsorptionEvent, AbsorptionOptions } from \"./analytics/absorption\";\nexport { DepthAggregator, computeDepth } from \"./analytics/depth\";\nexport type {\n DepthBar,\n DepthLevel,\n DepthLevelBar,\n DepthOptions,\n DepthSnapshot,\n} from \"./analytics/depth\";\nexport { FootprintAggregator, computeFootprint } from \"./analytics/orderflow\";\nexport type {\n FootprintBar,\n FootprintLevel,\n FootprintOptions,\n TradeSide,\n TradeTick,\n} from \"./analytics/orderflow\";\nexport { addVolumeProfileOverlay } from \"./analytics/volume-profile-overlay\";\nexport type {\n VolumeProfileOverlay,\n VolumeProfileOverlayColors,\n VolumeProfileOverlayOptions,\n} from \"./analytics/volume-profile-overlay\";\nexport { computeVolumeProfile } from \"./analytics/volume-profile\";\nexport type {\n VolumeProfile,\n VolumeProfileBin,\n VolumeProfileDistribution,\n VolumeProfileOptions,\n} from \"./analytics/volume-profile\";\nexport { PRO_CORE_FEATURES, PRO_FEATURES } from \"./features\";\nexport type { ProFeature } from \"./features\";\nexport * from \"./extensions\";\nexport * from \"./license/verify\";\n\nimport { assertFeature, type Feature, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Returns true when the active license grants a pro feature.\n */\nexport function hasProFeature(context: LicenseContext, feature: Feature): boolean {\n return context.hasFeature(feature);\n}\n\n/**\n * Throws `WickError(\"LICENSE_REQUIRED\")` when a pro feature is not granted.\n */\nexport function assertProFeature(context: LicenseContext, feature: Feature): void {\n assertFeature(context, feature);\n}\n"],"mappings":"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","names":["assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","DEFAULT_IMBALANCE_RATIO","imbalanceOf","DEFAULT_BUCKET_MS","assertFeature","WickError","assertFeature","WickError","DEFAULT_OPTIONS","assertFeature"]}
|
|
1
|
+
{"version":3,"sources":["../package.json","../src/version.ts","../src/script/backtest.ts","../src/strategy/backtest.ts","../src/alerts/engine.ts","../src/analytics/absorption.ts","../src/analytics/depth.ts","../src/analytics/orderflow.ts","../src/analytics/volume-profile.ts","../src/analytics/volume-profile-overlay.ts","../src/features.ts","../src/extensions.ts","../src/license/verify.ts","../src/index.ts"],"sourcesContent":["{\n \"name\": \"@wicklib/pro\",\n \"version\": \"0.13.0\",\n \"description\": \"Wicklib commercial add-on\",\n \"license\": \"SEE LICENSE IN LICENSE\",\n \"type\": \"module\",\n \"sideEffects\": false,\n \"files\": [\n \"dist\",\n \"README.md\"\n ],\n \"main\": \"./dist/index.cjs\",\n \"module\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": {\n \"types\": \"./dist/index.d.ts\",\n \"default\": \"./dist/index.js\"\n },\n \"require\": {\n \"types\": \"./dist/index.d.cts\",\n \"default\": \"./dist/index.cjs\"\n }\n },\n \"./package.json\": \"./package.json\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24.0.0\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/wicklib/wicklib-pro.git\",\n \"directory\": \"packages/pro\"\n },\n \"peerDependencies\": {\n \"@wicklib/core\": \"^0.13.0\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"typecheck\": \"tsc --noEmit\",\n \"test\": \"vitest run\"\n },\n \"devDependencies\": {\n \"tsup\": \"^9.0.0\",\n \"typescript\": \"^5.9.3\",\n \"vitest\": \"^5.0.5\"\n }\n}\n","import packageJson from \"../package.json\";\n\n/**\n * Semantic version of the installed pro package.\n */\nexport const PRO_VERSION: string = packageJson.version;\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\nimport {\n runBacktest,\n type BacktestOptions,\n type BacktestResult,\n type StrategyTarget,\n} from \"../strategy/backtest\";\n\n/**\n * One alert emitted by a script, including the bar it belongs to.\n */\nexport interface ScriptAlertEvent {\n time: number;\n barIndex: number;\n message: string;\n}\n\n/**\n * Output required from a compiled script replay.\n *\n * This is structurally compatible with `@wicklib/script`'s `CompiledScript`, without making\n * Pro depend on the script package at runtime.\n */\nexport interface ScriptRunResult {\n plots: Readonly<Record<string, ReadonlyArray<number | null>>>;\n alerts: ReadonlyArray<string>;\n alertEvents?: ReadonlyArray<ScriptAlertEvent>;\n}\n\n/**\n * Minimal compiled-script contract accepted by the adapter.\n */\nexport interface CompiledScriptLike {\n replay(bars: readonly OhlcData[]): Promise<ScriptRunResult>;\n}\n\n/**\n * Options for a script-driven backtest.\n */\nexport interface ScriptBacktestOptions extends BacktestOptions {\n /** Plot id whose values are target positions: -1 short, 0 flat, 1 long, null hold. */\n signalPlot: string;\n}\n\n/**\n * Backtest result plus script alerts.\n */\nexport interface ScriptBacktestResult extends BacktestResult {\n alerts: readonly ScriptAlertEvent[];\n}\n\n/**\n * Runs a compiled script, maps one plot to target positions, and backtests the result.\n *\n * The script must emit positions on the configured plot. Alerts are returned with their\n * source bar so the host can deliver or persist them. Requires the `strategy` feature.\n */\nexport async function runScriptBacktest(\n context: LicenseContext,\n script: CompiledScriptLike,\n bars: readonly OhlcData[],\n options: ScriptBacktestOptions,\n): Promise<ScriptBacktestResult> {\n assertFeature(context, \"strategy\");\n\n if (!script || typeof script.replay !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script adapter requires a replay function\");\n }\n if (typeof options.signalPlot !== \"string\" || options.signalPlot.trim() === \"\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Script signalPlot must be a non-empty string\");\n }\n\n const result = await script.replay(bars);\n const values = result?.plots?.[options.signalPlot];\n if (!Array.isArray(values)) {\n throw new WickError(\"INVALID_DATA\", `Script plot not found: ${options.signalPlot}`);\n }\n if (values.length !== bars.length) {\n throw new WickError(\"INVALID_DATA\", \"Script signal plot length must match the bar count\");\n }\n if (result.alerts.length > 0 && !result.alertEvents) {\n throw new WickError(\"INVALID_DATA\", \"Script alerts are missing their bar events\");\n }\n\n const alerts = (result.alertEvents ?? []).map((event) => validateAlert(event));\n const backtest = runBacktest(\n context,\n bars,\n ({ index }): StrategyTarget | undefined => {\n const value = values[index];\n if (value === null || value === undefined) {\n return undefined;\n }\n if (value !== -1 && value !== 0 && value !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Script signal must be -1, 0, 1, or null\");\n }\n return value;\n },\n options,\n );\n\n return { ...backtest, alerts };\n}\n\nfunction validateAlert(event: ScriptAlertEvent): ScriptAlertEvent {\n if (\n !event ||\n !Number.isFinite(event.time) ||\n !Number.isInteger(event.barIndex) ||\n event.barIndex < 0 ||\n typeof event.message !== \"string\"\n ) {\n throw new WickError(\"INVALID_DATA\", \"Invalid script alert event\");\n }\n return { time: event.time, barIndex: event.barIndex, message: event.message };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Target position for a strategy.\n *\n * -1 = fully short\n * 0 = flat\n * 1 = fully long\n */\nexport type StrategyTarget = -1 | 0 | 1;\n\n/**\n * Context passed to a strategy once per closed bar.\n */\nexport interface StrategyContext {\n readonly bar: OhlcData;\n readonly index: number;\n readonly position: StrategyTarget;\n readonly cash: number;\n readonly units: number;\n readonly equity: number;\n}\n\n/**\n * Strategy callback. Return a target to schedule a fill at the next bar open, or\n * `undefined`/`null` to hold the current target.\n */\nexport type StrategyFunction = (context: StrategyContext) => StrategyTarget | null | undefined;\n\n/**\n * Backtest configuration.\n */\nexport interface BacktestOptions {\n /** Starting cash. Required and positive. */\n initialCapital: number;\n /** Fractional fee charged on absolute traded notional. Defaults to 0. */\n feeRate?: number;\n /** Fractional slippage applied against the fill. Defaults to 0. */\n slippage?: number;\n}\n\n/**\n * One executed target change.\n */\nexport interface BacktestFill {\n time: number;\n side: \"buy\" | \"sell\";\n price: number;\n quantity: number;\n fee: number;\n}\n\n/**\n * One marked-to-market equity point.\n */\nexport interface EquityPoint {\n time: number;\n cash: number;\n units: number;\n position: StrategyTarget;\n price: number;\n equity: number;\n}\n\n/**\n * Deterministic strategy backtest result.\n */\nexport interface BacktestResult {\n initialCapital: number;\n finalEquity: number;\n returnPercent: number;\n maxDrawdown: number;\n fills: readonly BacktestFill[];\n equity: readonly EquityPoint[];\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<BacktestOptions, \"initialCapital\">> = {\n feeRate: 0,\n slippage: 0,\n};\n\n/**\n * Runs a target-position strategy against closed bars.\n *\n * Signals are evaluated on bar close and filled at the next bar open, preventing\n * lookahead. Position sizing is fully invested at the fill price; leverage is not added.\n * Requires the `strategy` license feature.\n */\nexport function runBacktest(\n context: LicenseContext,\n bars: readonly OhlcData[],\n strategy: StrategyFunction,\n options: BacktestOptions,\n): BacktestResult {\n assertFeature(context, \"strategy\");\n\n const initialCapital = options.initialCapital;\n const feeRate = options.feeRate ?? DEFAULT_OPTIONS.feeRate;\n const slippage = options.slippage ?? DEFAULT_OPTIONS.slippage;\n if (!Number.isFinite(initialCapital) || initialCapital <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest initialCapital must be positive\");\n }\n if (!Number.isFinite(feeRate) || feeRate < 0 || feeRate >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest feeRate must be in [0, 1)\");\n }\n if (!Number.isFinite(slippage) || slippage < 0 || slippage >= 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest slippage must be in [0, 1)\");\n }\n if (typeof strategy !== \"function\") {\n throw new WickError(\"INVALID_ARGUMENT\", \"Backtest strategy must be a function\");\n }\n\n let cash = initialCapital;\n let units = 0;\n let position: StrategyTarget = 0;\n let pending: StrategyTarget | null = null;\n let previousTime = Number.NEGATIVE_INFINITY;\n const fills: BacktestFill[] = [];\n const equity: EquityPoint[] = [];\n let peak = initialCapital;\n let maxDrawdown = 0;\n\n for (let index = 0; index < bars.length; index += 1) {\n const bar = bars[index]!;\n if (\n !Number.isFinite(bar.time) ||\n bar.time <= previousTime ||\n !Number.isFinite(bar.open) ||\n !Number.isFinite(bar.close) ||\n !Number.isFinite(bar.high) ||\n !Number.isFinite(bar.low)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Backtest bars require ascending finite OHLC values\");\n }\n previousTime = bar.time;\n\n if (pending !== null && pending !== position) {\n const side: \"buy\" | \"sell\" = pending > position ? \"buy\" : \"sell\";\n const price = side === \"buy\" ? bar.open * (1 + slippage) : bar.open * (1 - slippage);\n const equityAtFill = cash + units * price;\n const desiredUnits = (pending * equityAtFill) / price;\n const quantity = desiredUnits - units;\n const fee = Math.abs(quantity * price) * feeRate;\n cash -= quantity * price + fee;\n units = desiredUnits;\n position = pending;\n if (quantity !== 0) {\n fills.push({ time: bar.time, side, price, quantity, fee });\n }\n pending = null;\n }\n\n const markedEquity = cash + units * bar.close;\n peak = Math.max(peak, markedEquity);\n if (peak > 0) {\n maxDrawdown = Math.max(maxDrawdown, (peak - markedEquity) / peak);\n }\n equity.push({\n time: bar.time,\n cash,\n units,\n position,\n price: bar.close,\n equity: markedEquity,\n });\n\n const signal = strategy({\n bar,\n index,\n position,\n cash,\n units,\n equity: markedEquity,\n });\n if (signal !== undefined && signal !== null) {\n if (signal !== -1 && signal !== 0 && signal !== 1) {\n throw new WickError(\"INVALID_DATA\", \"Strategy target must be -1, 0, or 1\");\n }\n pending = signal;\n }\n }\n\n const finalEquity = equity.at(-1)?.equity ?? initialCapital;\n return {\n initialCapital,\n finalEquity,\n returnPercent: ((finalEquity - initialCapital) / initialCapital) * 100,\n maxDrawdown,\n fills,\n equity,\n };\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Price field used by a price alert.\n */\nexport type AlertPriceSource = \"close\" | \"high\" | \"low\";\n\n/**\n * Price alert direction.\n *\n * `cross` reports the side that was crossed.\n */\nexport type AlertDirection = \"above\" | \"below\" | \"cross\";\n\n/**\n * A serializable price alert rule.\n */\nexport interface PriceAlertRule {\n readonly id: string;\n readonly price: number;\n readonly direction: AlertDirection;\n /** Defaults to close. */\n readonly source?: AlertPriceSource;\n}\n\n/**\n * A triggered alert.\n */\nexport interface AlertTrigger {\n readonly ruleId: string;\n readonly time: number;\n readonly direction: \"above\" | \"below\";\n readonly price: number;\n readonly value: number;\n readonly bar: OhlcData;\n}\n\nconst SOURCES = new Set<AlertPriceSource>([\"close\", \"high\", \"low\"]);\n\n/**\n * Deterministic, offline alert evaluator for streaming bars.\n *\n * The first bar initializes state and never triggers. Subsequent bars trigger only on a\n * transition so a rule does not fire repeatedly while it remains true.\n */\nexport class AlertEngine {\n private readonly rules: readonly PriceAlertRule[];\n private readonly previous = new Map<string, number>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, rules: readonly PriceAlertRule[]) {\n assertFeature(context, \"alerts\");\n const ids = new Set<string>();\n for (const rule of rules) {\n if (\n !rule ||\n typeof rule.id !== \"string\" ||\n rule.id.trim() === \"\" ||\n !Number.isFinite(rule.price) ||\n (rule.direction !== \"above\" && rule.direction !== \"below\" && rule.direction !== \"cross\") ||\n (rule.source !== undefined && !SOURCES.has(rule.source))\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Invalid price alert rule\");\n }\n if (ids.has(rule.id)) {\n throw new WickError(\"INVALID_ARGUMENT\", `Duplicate alert rule id: ${rule.id}`);\n }\n ids.add(rule.id);\n }\n this.rules = rules.map((rule) => ({ ...rule }));\n }\n\n /**\n * Consumes one closed bar and returns the alerts triggered by that bar.\n */\n update(bar: OhlcData): readonly AlertTrigger[] {\n if (!Number.isFinite(bar.time)) {\n throw new WickError(\"INVALID_DATA\", \"Alert bar requires a finite time\");\n }\n if (bar.time <= this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Alert bars must have increasing times\");\n }\n this.lastTime = bar.time;\n\n const triggers: AlertTrigger[] = [];\n for (const rule of this.rules) {\n const source = rule.source ?? \"close\";\n const value = source === \"close\" ? bar.close : source === \"high\" ? bar.high : bar.low;\n const previous = this.previous.get(rule.id);\n if (previous !== undefined) {\n if (rule.direction === \"above\" && previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (rule.direction === \"below\" && previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n } else if (rule.direction === \"cross\") {\n if (previous <= rule.price && value > rule.price) {\n triggers.push(trigger(rule, bar, value, \"above\"));\n } else if (previous >= rule.price && value < rule.price) {\n triggers.push(trigger(rule, bar, value, \"below\"));\n }\n }\n }\n this.previous.set(rule.id, value);\n }\n\n return triggers;\n }\n\n /**\n * Clears previous values so the next bar initializes state again.\n */\n reset(): void {\n this.previous.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Evaluates a batch of closed bars through the same streaming alert path.\n */\nexport function evaluateAlerts(\n context: LicenseContext,\n rules: readonly PriceAlertRule[],\n bars: readonly OhlcData[],\n): readonly AlertTrigger[] {\n const engine = new AlertEngine(context, rules);\n const triggers: AlertTrigger[] = [];\n for (const bar of bars) {\n triggers.push(...engine.update(bar));\n }\n return triggers;\n}\n\nfunction trigger(\n rule: PriceAlertRule,\n bar: OhlcData,\n value: number,\n direction: \"above\" | \"below\",\n): AlertTrigger {\n return {\n ruleId: rule.id,\n time: bar.time,\n direction,\n price: rule.price,\n value,\n bar,\n };\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\nimport { DepthAggregator, type DepthSnapshot } from \"./depth\";\nimport { FootprintAggregator, type TradeTick, type TradeSide } from \"./orderflow\";\n\n/**\n * Options for absorption detection.\n */\nexport interface AbsorptionOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Aggressive volume must reach passive size × this ratio. Defaults to 2. */\n absorptionRatio?: number;\n}\n\n/**\n * A detected absorption event.\n */\nexport interface AbsorptionEvent {\n /** Bucket start time in milliseconds. */\n time: number;\n priceLow: number;\n priceHigh: number;\n /** Aggressor side that was absorbed. */\n side: TradeSide;\n /** Aggressive trade volume in the bucket and level. */\n aggressiveVolume: number;\n /** Passive book size at the level when the bucket completed. */\n passiveVolume: number;\n /** aggressiveVolume / passiveVolume. */\n ratio: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_ABSORPTION_RATIO = 2;\n\n/**\n * Detects aggressive volume absorbed by passive L2 liquidity.\n *\n * For each footprint bucket and price level:\n * - aggressive buys are compared with ask depth\n * - aggressive sells are compared with bid depth\n *\n * A level is reported when aggressive volume is at least the configured multiple of the\n * passive size. Requires the `orderflow` license feature.\n */\nexport function detectAbsorption(\n context: LicenseContext,\n trades: readonly TradeTick[],\n snapshots: readonly DepthSnapshot[],\n options: AbsorptionOptions,\n): readonly AbsorptionEvent[] {\n assertFeature(context, \"orderflow\");\n\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const absorptionRatio = options.absorptionRatio ?? DEFAULT_ABSORPTION_RATIO;\n const priceStep = options.priceStep;\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption bucketMs must be a positive integer\");\n }\n if (!Number.isFinite(absorptionRatio) || absorptionRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption ratio must be at least 1\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Absorption priceStep must be a positive number\");\n }\n\n const footprints = new FootprintAggregator(context, {\n bucketMs,\n priceStep,\n });\n for (const trade of [...trades].sort((first, second) => first.time - second.time)) {\n footprints.push(trade);\n }\n\n const depth = new DepthAggregator(context, { priceStep });\n for (const snapshot of [...snapshots].sort((first, second) => first.time - second.time)) {\n depth.push(snapshot);\n }\n\n const events: AbsorptionEvent[] = [];\n for (const bar of footprints.getBars()) {\n const book = depth.latest(bar.time + bucketMs - 1);\n if (!book) {\n continue;\n }\n const depthByPrice = new Map(book.levels.map((level) => [level.priceLow, level]));\n for (const level of bar.levels) {\n const depthLevel = depthByPrice.get(level.priceLow);\n if (!depthLevel) {\n continue;\n }\n const candidates: Array<{\n side: TradeSide;\n aggressive: number;\n passive: number;\n }> = [\n { side: \"buy\", aggressive: level.buyVolume, passive: depthLevel.askSize },\n { side: \"sell\", aggressive: level.sellVolume, passive: depthLevel.bidSize },\n ];\n for (const candidate of candidates) {\n if (candidate.passive <= 0 || candidate.aggressive <= 0) {\n continue;\n }\n const ratio = candidate.aggressive / candidate.passive;\n if (ratio >= absorptionRatio) {\n events.push({\n time: bar.time,\n priceLow: level.priceLow,\n priceHigh: level.priceHigh,\n side: candidate.side,\n aggressiveVolume: candidate.aggressive,\n passiveVolume: candidate.passive,\n ratio,\n });\n }\n }\n }\n }\n\n return events;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * One side of a Level-2 depth snapshot.\n */\nexport interface DepthLevel {\n price: number;\n size: number;\n}\n\n/**\n * A full bid/ask book snapshot at a point in time.\n */\nexport interface DepthSnapshot {\n /** Unix timestamp in milliseconds. */\n time: number;\n bids: readonly DepthLevel[];\n asks: readonly DepthLevel[];\n}\n\n/**\n * Aggregated bid/ask liquidity by price bucket.\n */\nexport interface DepthLevelBar {\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n}\n\n/**\n * Aggregated depth for one snapshot.\n */\nexport interface DepthBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n bidSize: number;\n askSize: number;\n totalSize: number;\n delta: number;\n imbalance: \"bid\" | \"ask\" | null;\n levels: readonly DepthLevelBar[];\n}\n\n/**\n * Options for depth aggregation.\n */\nexport interface DepthOptions {\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies total book pressure as imbalanced. Defaults to 2. */\n imbalanceRatio?: number;\n}\n\nconst DEFAULT_IMBALANCE_RATIO = 2;\n\n/**\n * Incremental L2 depth aggregator.\n *\n * Snapshots are complete books, so newer snapshots replace the current view rather than\n * accumulate. Non-decreasing timestamps are enforced.\n */\nexport class DepthAggregator {\n private readonly options: Required<DepthOptions>;\n private readonly bars = new Map<number, DepthBar>();\n private lastTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: DepthOptions) {\n assertFeature(context, \"orderflow\");\n if (\n options.priceStep === undefined ||\n !Number.isFinite(options.priceStep) ||\n options.priceStep <= 0\n ) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth priceStep must be a positive number\");\n }\n const ratio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n if (!Number.isFinite(ratio) || ratio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Depth imbalanceRatio must be at least 1\");\n }\n this.options = { priceStep: options.priceStep, imbalanceRatio: ratio };\n }\n\n /**\n * Adds or replaces one complete snapshot and returns its aggregated bar.\n */\n push(snapshot: DepthSnapshot): DepthBar {\n if (\n !Number.isFinite(snapshot.time) ||\n !Array.isArray(snapshot.bids) ||\n !Array.isArray(snapshot.asks)\n ) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots require finite time, bids, and asks\");\n }\n if (snapshot.time < this.lastTime) {\n throw new WickError(\"INVALID_DATA\", \"Depth snapshots must be in non-decreasing time order\");\n }\n this.lastTime = snapshot.time;\n\n const levels = new Map<number, { bid: number; ask: number }>();\n for (const [side, entries] of [\n [\"bid\", snapshot.bids],\n [\"ask\", snapshot.asks],\n ] as const) {\n for (const entry of entries) {\n if (!Number.isFinite(entry.price) || !Number.isFinite(entry.size) || entry.size < 0) {\n throw new WickError(\n \"INVALID_DATA\",\n \"Depth levels require finite price and non-negative size\",\n );\n }\n const price = Math.floor(entry.price / this.options.priceStep) * this.options.priceStep;\n let level = levels.get(price);\n if (!level) {\n level = { bid: 0, ask: 0 };\n levels.set(price, level);\n }\n if (side === \"bid\") level.bid += entry.size;\n else level.ask += entry.size;\n }\n }\n\n let bidSize = 0;\n let askSize = 0;\n const sortedLevels: DepthLevelBar[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, level]) => {\n bidSize += level.bid;\n askSize += level.ask;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n bidSize: level.bid,\n askSize: level.ask,\n totalSize: level.bid + level.ask,\n delta: level.bid - level.ask,\n imbalance: imbalanceOf(level.bid, level.ask, this.options.imbalanceRatio),\n };\n });\n\n const bar: DepthBar = {\n time: snapshot.time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n bidSize,\n askSize,\n totalSize: bidSize + askSize,\n delta: bidSize - askSize,\n imbalance: imbalanceOf(bidSize, askSize, this.options.imbalanceRatio),\n levels: sortedLevels,\n };\n this.bars.set(snapshot.time, bar);\n return bar;\n }\n\n /**\n * Returns the latest snapshot at or before a time.\n */\n latest(time = Number.POSITIVE_INFINITY): DepthBar | null {\n const eligible = [...this.bars.values()]\n .filter((bar) => bar.time <= time)\n .sort((first, second) => first.time - second.time);\n return eligible.at(-1) ?? null;\n }\n\n /**\n * Returns all snapshots in ascending time order.\n */\n getBars(): readonly DepthBar[] {\n return [...this.bars.values()].sort((first, second) => first.time - second.time);\n }\n\n /**\n * Clears all snapshots and the streaming order guard.\n */\n reset(): void {\n this.bars.clear();\n this.lastTime = Number.NEGATIVE_INFINITY;\n }\n}\n\n/**\n * Aggregates a batch of complete L2 book snapshots.\n *\n * Requires the `orderflow` license feature.\n */\nexport function computeDepth(\n context: LicenseContext,\n snapshots: readonly DepthSnapshot[],\n options: DepthOptions,\n): readonly DepthBar[] {\n const aggregator = new DepthAggregator(context, options);\n for (const snapshot of snapshots) {\n aggregator.push(snapshot);\n }\n return aggregator.getBars();\n}\n\nfunction imbalanceOf(bid: number, ask: number, ratio: number): \"bid\" | \"ask\" | null {\n if (bid === 0 && ask === 0) return null;\n if (ask === 0) return \"bid\";\n if (bid === 0) return \"ask\";\n if (bid >= ask * ratio) return \"bid\";\n if (ask >= bid * ratio) return \"ask\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Aggressor side of a trade tick.\n */\nexport type TradeSide = \"buy\" | \"sell\";\n\n/**\n * Minimal trade tick accepted by the orderflow aggregator.\n */\nexport interface TradeTick {\n /** Unix timestamp in milliseconds. */\n time: number;\n price: number;\n size: number;\n side: TradeSide;\n}\n\n/**\n * Orderflow aggregation options.\n */\nexport interface FootprintOptions {\n /** Time bucket size in milliseconds. Defaults to one minute. */\n bucketMs?: number;\n /** Price bucket width. Required. */\n priceStep?: number;\n /** Ratio that qualifies a level as imbalanced. Defaults to 3. */\n imbalanceRatio?: number;\n}\n\n/**\n * One price level in a footprint bar.\n */\nexport interface FootprintLevel {\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n imbalance: TradeSide | null;\n}\n\n/**\n * Aggregated footprint for one time bucket.\n */\nexport interface FootprintBar {\n time: number;\n priceLow: number;\n priceHigh: number;\n buyVolume: number;\n sellVolume: number;\n totalVolume: number;\n delta: number;\n levels: readonly FootprintLevel[];\n}\n\ninterface ResolvedOptions {\n bucketMs: number;\n priceStep: number;\n imbalanceRatio: number;\n}\n\ninterface LevelVolumes {\n buy: number;\n sell: number;\n}\n\nconst DEFAULT_BUCKET_MS = 60_000;\nconst DEFAULT_IMBALANCE_RATIO = 3;\n\n/**\n * Incremental trade-tick footprint aggregator.\n *\n * Trades must arrive in non-decreasing time order. Ticks in the same bucket update the\n * same bar, so streaming and batch aggregation share the same code path.\n */\nexport class FootprintAggregator {\n private readonly options: ResolvedOptions;\n private readonly levels = new Map<number, Map<number, LevelVolumes>>();\n private lastTradeTime = Number.NEGATIVE_INFINITY;\n\n constructor(context: LicenseContext, options: FootprintOptions) {\n assertFeature(context, \"orderflow\");\n this.options = resolveOptions(options);\n }\n\n /**\n * Adds one trade and returns the updated bar for its time bucket.\n */\n push(trade: TradeTick): FootprintBar {\n this.validateTrade(trade);\n if (trade.time < this.lastTradeTime) {\n throw new WickError(\"INVALID_DATA\", \"Streaming trades must be in non-decreasing time order\");\n }\n this.lastTradeTime = trade.time;\n\n const time = Math.floor(trade.time / this.options.bucketMs) * this.options.bucketMs;\n const price = Math.floor(trade.price / this.options.priceStep) * this.options.priceStep;\n let levels = this.levels.get(time);\n if (!levels) {\n levels = new Map();\n this.levels.set(time, levels);\n }\n let level = levels.get(price);\n if (!level) {\n level = { buy: 0, sell: 0 };\n levels.set(price, level);\n }\n if (trade.side === \"buy\") level.buy += trade.size;\n else level.sell += trade.size;\n\n return this.buildBar(time)!;\n }\n\n /**\n * Adds multiple trades in input order.\n */\n pushMany(trades: readonly TradeTick[]): readonly FootprintBar[] {\n for (const trade of trades) {\n this.push(trade);\n }\n return this.getBars();\n }\n\n /**\n * Returns a bar by bucket start time, or any time inside that bucket.\n */\n getBar(time: number): FootprintBar | null {\n const bucket = Math.floor(time / this.options.bucketMs) * this.options.bucketMs;\n return this.buildBar(bucket);\n }\n\n /**\n * Returns all completed/current buckets in ascending time order.\n */\n getBars(): readonly FootprintBar[] {\n return [...this.levels.keys()]\n .sort((first, second) => first - second)\n .map((time) => this.buildBar(time))\n .filter((bar): bar is FootprintBar => bar !== null);\n }\n\n /**\n * Clears all trades and resets the streaming order guard.\n */\n reset(): void {\n this.levels.clear();\n this.lastTradeTime = Number.NEGATIVE_INFINITY;\n }\n\n private buildBar(time: number): FootprintBar | null {\n const levels = this.levels.get(time);\n if (!levels) {\n return null;\n }\n\n let buyVolume = 0;\n let sellVolume = 0;\n const sortedLevels: FootprintLevel[] = [...levels.entries()]\n .sort(([first], [second]) => first - second)\n .map(([priceLow, volumes]) => {\n buyVolume += volumes.buy;\n sellVolume += volumes.sell;\n return {\n priceLow,\n priceHigh: priceLow + this.options.priceStep,\n buyVolume: volumes.buy,\n sellVolume: volumes.sell,\n totalVolume: volumes.buy + volumes.sell,\n delta: volumes.buy - volumes.sell,\n imbalance: imbalanceOf(volumes.buy, volumes.sell, this.options.imbalanceRatio),\n };\n });\n\n return {\n time,\n priceLow: sortedLevels[0]?.priceLow ?? 0,\n priceHigh: sortedLevels.at(-1)?.priceHigh ?? 0,\n buyVolume,\n sellVolume,\n totalVolume: buyVolume + sellVolume,\n delta: buyVolume - sellVolume,\n levels: sortedLevels,\n };\n }\n\n private validateTrade(trade: TradeTick): void {\n if (\n !Number.isFinite(trade.time) ||\n !Number.isFinite(trade.price) ||\n !Number.isFinite(trade.size) ||\n trade.size <= 0 ||\n trade.price < 0 ||\n (trade.side !== \"buy\" && trade.side !== \"sell\")\n ) {\n throw new WickError(\"INVALID_DATA\", \"Trade ticks require finite time, price, size, and side\");\n }\n }\n}\n\n/**\n * Aggregates trade ticks into bid/ask footprint bars with delta and imbalance.\n *\n * Requires the `orderflow` license feature. Trades are sorted by time before aggregation.\n */\nexport function computeFootprint(\n context: LicenseContext,\n trades: readonly TradeTick[],\n options: FootprintOptions,\n): readonly FootprintBar[] {\n const aggregator = new FootprintAggregator(context, options);\n return aggregator.pushMany([...trades].sort((first, second) => first.time - second.time));\n}\n\nfunction resolveOptions(options: FootprintOptions): ResolvedOptions {\n const bucketMs = options.bucketMs ?? DEFAULT_BUCKET_MS;\n const priceStep = options.priceStep;\n const imbalanceRatio = options.imbalanceRatio ?? DEFAULT_IMBALANCE_RATIO;\n\n if (!Number.isInteger(bucketMs) || bucketMs <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint bucketMs must be a positive integer\");\n }\n if (priceStep === undefined || !Number.isFinite(priceStep) || priceStep <= 0) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint priceStep must be a positive number\");\n }\n if (!Number.isFinite(imbalanceRatio) || imbalanceRatio < 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Footprint imbalanceRatio must be at least 1\");\n }\n return { bucketMs, priceStep, imbalanceRatio };\n}\n\nfunction imbalanceOf(buy: number, sell: number, ratio: number): TradeSide | null {\n if (buy === 0 && sell === 0) return null;\n if (sell === 0) return \"buy\";\n if (buy === 0) return \"sell\";\n if (buy >= sell * ratio) return \"buy\";\n if (sell >= buy * ratio) return \"sell\";\n return null;\n}\n","import { assertFeature, WickError, type LicenseContext, type OhlcData } from \"@wicklib/core\";\n\n/**\n * Volume distribution model.\n *\n * `uniform` spreads each bar's volume evenly across its price range. `close` assigns the\n * whole bar volume to the bin containing the close.\n */\nexport type VolumeProfileDistribution = \"uniform\" | \"close\";\n\n/**\n * Options for {@link computeVolumeProfile}.\n */\nexport interface VolumeProfileOptions {\n /** Number of equal-width price bins. Defaults to 24. */\n bins?: number;\n /** Fixed price range. Defaults to the bars' low/high span. */\n priceRange?: { min: number; max: number };\n /** Fraction of total volume covered by the value area. Defaults to 0.7. */\n valueArea?: number;\n /** Volume distribution model. Defaults to uniform. */\n distribution?: VolumeProfileDistribution;\n}\n\n/**\n * One price bucket in a volume profile.\n */\nexport interface VolumeProfileBin {\n index: number;\n priceLow: number;\n priceHigh: number;\n priceMid: number;\n volume: number;\n}\n\n/**\n * Computed volume profile.\n */\nexport interface VolumeProfile {\n bins: readonly VolumeProfileBin[];\n range: { min: number; max: number };\n totalVolume: number;\n /** Point of control, or null when there is no volume. */\n poc: VolumeProfileBin | null;\n valueArea: {\n low: number;\n high: number;\n volume: number;\n } | null;\n}\n\nconst DEFAULT_OPTIONS: Required<Omit<VolumeProfileOptions, \"priceRange\">> = {\n bins: 24,\n valueArea: 0.7,\n distribution: \"uniform\",\n};\n\n/**\n * Computes a deterministic volume profile from OHLCV bars.\n *\n * Requires the `volume-profile` license feature. Bars without a finite positive volume are\n * ignored. Throws `WickError(\"INVALID_DATA\")` when no usable volume remains.\n */\nexport function computeVolumeProfile(\n context: LicenseContext,\n bars: readonly OhlcData[],\n options: VolumeProfileOptions = {},\n): VolumeProfile {\n assertFeature(context, \"volume-profile\");\n\n const binCount = options.bins ?? DEFAULT_OPTIONS.bins;\n const valueAreaFraction = options.valueArea ?? DEFAULT_OPTIONS.valueArea;\n const distribution = options.distribution ?? DEFAULT_OPTIONS.distribution;\n\n if (!Number.isInteger(binCount) || binCount <= 0 || binCount > 2_000) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile bins must be between 1 and 2000\");\n }\n if (!Number.isFinite(valueAreaFraction) || valueAreaFraction <= 0 || valueAreaFraction > 1) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile valueArea must be in (0, 1]\");\n }\n\n let min: number;\n let max: number;\n if (options.priceRange) {\n min = options.priceRange.min;\n max = options.priceRange.max;\n if (!Number.isFinite(min) || !Number.isFinite(max) || max <= min) {\n throw new WickError(\"INVALID_ARGUMENT\", \"Volume profile priceRange must have max > min\");\n }\n } else {\n min = Number.POSITIVE_INFINITY;\n max = Number.NEGATIVE_INFINITY;\n for (const bar of bars) {\n if (!Number.isFinite(bar.volume) || bar.volume! <= 0) continue;\n min = Math.min(min, bar.low);\n max = Math.max(max, bar.high);\n }\n if (!Number.isFinite(min) || !Number.isFinite(max)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n if (max <= min) {\n max = min + 1;\n }\n }\n\n const width = (max - min) / binCount;\n const volumes = new Array<number>(binCount).fill(0);\n\n for (const bar of bars) {\n const volume = bar.volume;\n if (!Number.isFinite(volume) || volume === undefined || volume <= 0) continue;\n if (distribution === \"close\") {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const low = Math.max(bar.low, min);\n const high = Math.min(bar.high, max);\n if (high <= low) {\n const index = clampIndex(Math.floor((bar.close - min) / width), binCount);\n volumes[index]! += volume;\n continue;\n }\n\n const first = clampIndex(Math.floor((low - min) / width), binCount);\n const last = clampIndex(Math.floor((high - min) / width), binCount);\n let assigned = 0;\n for (let index = first; index <= last; index += 1) {\n const binLow = min + index * width;\n const binHigh = index === binCount - 1 ? max : binLow + width;\n const overlap = Math.max(0, Math.min(high, binHigh) - Math.max(low, binLow));\n const part = index === last ? volume - assigned : (volume * overlap) / (high - low);\n volumes[index]! += part;\n assigned += part;\n }\n }\n\n const totalVolume = volumes.reduce((sum, value) => sum + value, 0);\n if (!(totalVolume > 0)) {\n throw new WickError(\"INVALID_DATA\", \"Volume profile requires bars with volume\");\n }\n\n const bins: VolumeProfileBin[] = volumes.map((volume, index) => ({\n index,\n priceLow: min + index * width,\n priceHigh: index === binCount - 1 ? max : min + (index + 1) * width,\n priceMid: min + (index + 0.5) * width,\n volume,\n }));\n\n let pocIndex = 0;\n for (let index = 1; index < bins.length; index += 1) {\n if (bins[index]!.volume > bins[pocIndex]!.volume) {\n pocIndex = index;\n }\n }\n\n const target = totalVolume * valueAreaFraction;\n let lowIndex = pocIndex;\n let highIndex = pocIndex;\n let valueVolume = bins[pocIndex]!.volume;\n\n while (valueVolume < target && (lowIndex > 0 || highIndex < bins.length - 1)) {\n const lower = lowIndex > 0 ? bins[lowIndex - 1]!.volume : -1;\n const upper = highIndex < bins.length - 1 ? bins[highIndex + 1]!.volume : -1;\n if (upper > lower) {\n highIndex += 1;\n valueVolume += bins[highIndex]!.volume;\n } else {\n lowIndex -= 1;\n valueVolume += bins[lowIndex]!.volume;\n }\n }\n\n return {\n bins,\n range: { min, max },\n totalVolume,\n poc: bins[pocIndex] ?? null,\n valueArea: {\n low: bins[lowIndex]!.priceLow,\n high: bins[highIndex]!.priceHigh,\n volume: valueVolume,\n },\n };\n}\n\nfunction clampIndex(value: number, count: number): number {\n return Math.max(0, Math.min(count - 1, value));\n}\n","import type { ChartApi, ChartOverlayApi, LicenseContext, OhlcData } from \"@wicklib/core\";\n\nimport {\n computeVolumeProfile,\n type VolumeProfile,\n type VolumeProfileOptions,\n} from \"./volume-profile\";\n\n/**\n * Colors used by the volume-profile overlay.\n */\nexport interface VolumeProfileOverlayColors {\n bar: string;\n valueArea: string;\n poc: string;\n}\n\n/**\n * Options for {@link addVolumeProfileOverlay}.\n */\nexport interface VolumeProfileOverlayOptions extends VolumeProfileOptions {\n /** Overlay id. Defaults to a unique pro id. */\n id?: string;\n /** Pane to draw in. Defaults to the main pane. */\n paneId?: string;\n /** Histogram side. Defaults to the left side. */\n side?: \"left\" | \"right\";\n /** Histogram width as a fraction of the pane plot width. Defaults to 0.22. */\n widthRatio?: number;\n colors?: Partial<VolumeProfileOverlayColors>;\n}\n\n/**\n * Live volume-profile overlay.\n */\nexport interface VolumeProfileOverlay extends ChartOverlayApi {\n readonly profile: VolumeProfile;\n}\n\nconst DEFAULT_COLORS: VolumeProfileOverlayColors = {\n bar: \"#2962ff\",\n valueArea: \"#2962ff\",\n poc: \"#f0b90b\",\n};\n\nlet overlayCounter = 0;\n\n/**\n * Computes a volume profile and adds it to a chart as a clipped pane overlay.\n *\n * Requires the `volume-profile` license feature.\n */\nexport function addVolumeProfileOverlay(\n context: LicenseContext,\n chart: ChartApi,\n bars: readonly OhlcData[],\n options: VolumeProfileOverlayOptions = {},\n): VolumeProfileOverlay {\n const profile = computeVolumeProfile(context, bars, options);\n overlayCounter += 1;\n const id = options.id ?? `com.wicklib.volume-profile-${overlayCounter}`;\n const side = options.side ?? \"left\";\n const widthRatio = clamp(options.widthRatio ?? 0.22, 0.02, 0.9);\n const colors = { ...DEFAULT_COLORS, ...options.colors };\n const maxVolume = Math.max(0, ...profile.bins.map((bin) => bin.volume));\n const valueArea = profile.valueArea;\n\n const overlay = chart.addOverlay({\n id,\n ...(options.paneId ? { paneId: options.paneId } : {}),\n draw(canvas, frame) {\n if (maxVolume <= 0) {\n return;\n }\n const maxWidth = frame.plot.width * widthRatio;\n for (const bin of profile.bins) {\n if (bin.volume <= 0) {\n continue;\n }\n const top = frame.priceToY(bin.priceHigh);\n const bottom = frame.priceToY(bin.priceLow);\n const height = Math.max(1, Math.abs(bottom - top));\n const width = (bin.volume / maxVolume) * maxWidth;\n const x = side === \"left\" ? frame.plot.left : frame.plot.right - width;\n const inValueArea =\n valueArea !== null && bin.priceMid >= valueArea.low && bin.priceMid <= valueArea.high;\n const isPoc = profile.poc?.index === bin.index;\n canvas.globalAlpha = isPoc ? 0.55 : inValueArea ? 0.4 : 0.22;\n canvas.fillStyle = isPoc ? colors.poc : inValueArea ? colors.valueArea : colors.bar;\n canvas.fillRect(x, Math.min(top, bottom), width, height);\n }\n canvas.globalAlpha = 1;\n },\n });\n\n return {\n id: overlay.id,\n paneId: overlay.paneId,\n requestRender: overlay.requestRender,\n remove: overlay.remove,\n profile,\n };\n}\n\nfunction clamp(value: number, min: number, max: number): number {\n return Math.min(max, Math.max(min, value));\n}\n","import type { Feature } from \"@wicklib/core\";\n\n/**\n * Features shipped in the commercial tier.\n */\nexport const PRO_FEATURES = [\n \"orderflow\",\n \"volume-profile\",\n \"strategy\",\n \"alerts\",\n \"script-functions\",\n] as const;\n\n/**\n * A feature name provided by the commercial tier.\n */\nexport type ProFeature = (typeof PRO_FEATURES)[number];\n\n/**\n * Core feature tokens covered by the pro feature list.\n */\nexport const PRO_CORE_FEATURES: readonly Feature[] = PRO_FEATURES;\n","import type { LicenseContext, WickExtension } from \"@wicklib/core\";\n\nimport type { ProFeature } from \"./features\";\nimport { PRO_VERSION } from \"./version\";\n\n/**\n * Extension descriptor for a commercial feature.\n */\nexport interface ProExtension extends WickExtension {\n readonly kind: \"feature\";\n readonly feature: ProFeature;\n}\n\nconst NAMES: Record<ProFeature, string> = {\n orderflow: \"Orderflow\",\n \"volume-profile\": \"Volume Profile\",\n strategy: \"Strategy\",\n alerts: \"Alerts\",\n \"script-functions\": \"Script Functions\",\n};\n\n/**\n * Capability descriptors for the commercial feature set.\n *\n * Hosts pass the granted descriptors through `ChartOptions.extensions`. Individual\n * analytics register their runtime behavior separately.\n */\nexport const PRO_EXTENSIONS: readonly ProExtension[] = Object.freeze(\n ([\"orderflow\", \"volume-profile\", \"strategy\", \"alerts\", \"script-functions\"] as const).map(\n (feature) =>\n Object.freeze({\n kind: \"feature\" as const,\n feature,\n meta: Object.freeze({\n id: `com.wicklib.${feature}`,\n name: NAMES[feature],\n version: PRO_VERSION,\n license: \"pro\" as const,\n }),\n }),\n ),\n);\n\n/**\n * Returns the feature descriptors granted by a license context.\n */\nexport function getProExtensions(context: LicenseContext): readonly ProExtension[] {\n return PRO_EXTENSIONS.filter((extension) => context.hasFeature(extension.feature));\n}\n","import type { Feature, LicenseContext } from \"@wicklib/core\";\n\n/**\n * Decoded payload of a Wicklib license token.\n *\n * Tokens are Ed25519-signed and verified offline. `exp` is seconds since the Unix\n * epoch. `kid` selects the embedded public key.\n */\nexport interface LicenseTokenPayload {\n product: string;\n plan: string;\n seats: number;\n domains: string[];\n exp: number;\n features: Feature[];\n kid: string;\n}\n\n/**\n * Options for creating a license context.\n */\nexport interface LicenseVerifierOptions {\n /** Public keys indexed by `kid`, encoded as base64url raw Ed25519 keys. */\n publicKeys: Readonly<Record<string, string>>;\n /** Clock override for deterministic tests. Returns seconds since the epoch. */\n now?: () => number;\n /** Origin the license is being used from, if domain locking is enabled. */\n domain?: string;\n /** Expected product id. Defaults to wicklib-pro. */\n product?: string;\n}\n\n/**\n * Machine-readable license failure codes.\n */\nexport type LicenseErrorCode =\n | \"CRYPTO_UNAVAILABLE\"\n | \"INVALID_TOKEN\"\n | \"UNSUPPORTED_ALGORITHM\"\n | \"UNKNOWN_KID\"\n | \"INVALID_PAYLOAD\"\n | \"EXPIRED\"\n | \"WRONG_PRODUCT\"\n | \"DOMAIN_REQUIRED\"\n | \"DOMAIN_NOT_ALLOWED\"\n | \"SIGNATURE_INVALID\";\n\n/**\n * Typed license verification failure.\n */\nexport class LicenseError extends Error {\n readonly code: LicenseErrorCode;\n\n constructor(code: LicenseErrorCode, message: string) {\n super(message);\n this.name = \"LicenseError\";\n this.code = code;\n }\n}\n\ninterface LicenseHeader {\n alg: string;\n typ?: string;\n kid?: string;\n}\n\n/**\n * Verifies an Ed25519 license token and returns the feature context used by pro\n * extensions.\n *\n * Verification is fully offline. No network or telemetry calls are made.\n */\nexport async function createLicenseContext(\n token: string,\n options: LicenseVerifierOptions,\n): Promise<LicenseContext> {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token must have three segments\");\n }\n\n const [headerPart, payloadPart, signaturePart] = parts as [string, string, string];\n const header = decodeJson<LicenseHeader>(headerPart, \"INVALID_TOKEN\");\n if (header.alg !== \"Ed25519\") {\n throw new LicenseError(\n \"UNSUPPORTED_ALGORITHM\",\n `Unsupported license algorithm: ${header.alg}`,\n );\n }\n\n const payload = decodeJson<LicenseTokenPayload>(payloadPart, \"INVALID_PAYLOAD\");\n validatePayload(payload);\n\n if (header.kid && header.kid !== payload.kid) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License header and payload kid do not match\");\n }\n\n const publicKey = options.publicKeys[payload.kid];\n if (!publicKey) {\n throw new LicenseError(\"UNKNOWN_KID\", `Unknown license key id: ${payload.kid}`);\n }\n\n const product = options.product ?? \"wicklib-pro\";\n if (payload.product !== product) {\n throw new LicenseError(\n \"WRONG_PRODUCT\",\n `License is for ${payload.product}, expected ${product}`,\n );\n }\n\n const now = options.now?.() ?? Math.floor(Date.now() / 1_000);\n if (payload.exp <= now) {\n throw new LicenseError(\"EXPIRED\", \"License has expired\");\n }\n\n if (payload.domains.length > 0) {\n if (!options.domain) {\n throw new LicenseError(\"DOMAIN_REQUIRED\", \"This license requires a domain\");\n }\n if (!domainAllowed(payload.domains, options.domain)) {\n throw new LicenseError(\n \"DOMAIN_NOT_ALLOWED\",\n `Domain is not covered by the license: ${options.domain}`,\n );\n }\n }\n\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) {\n throw new LicenseError(\"CRYPTO_UNAVAILABLE\", \"Web Crypto is not available\");\n }\n\n let key: CryptoKey;\n try {\n const raw = base64UrlDecode(publicKey);\n key = await subtle.importKey(\"raw\", raw, { name: \"Ed25519\" }, false, [\"verify\"]);\n } catch (error) {\n throw new LicenseError(\n \"INVALID_PAYLOAD\",\n error instanceof Error ? `Invalid license public key: ${error.message}` : \"Invalid license public key\",\n );\n }\n\n let valid = false;\n try {\n valid = await subtle.verify(\n { name: \"Ed25519\" },\n key,\n base64UrlDecode(signaturePart),\n new TextEncoder().encode(`${headerPart}.${payloadPart}`),\n );\n } catch (error) {\n throw new LicenseError(\n \"SIGNATURE_INVALID\",\n error instanceof Error ? `Signature verification failed: ${error.message}` : \"Signature verification failed\",\n );\n }\n\n if (!valid) {\n throw new LicenseError(\"SIGNATURE_INVALID\", \"License signature is invalid\");\n }\n\n const granted = new Set<Feature>(payload.features);\n return { hasFeature: (feature) => granted.has(feature) };\n}\n\nfunction validatePayload(payload: LicenseTokenPayload): void {\n if (\n !payload ||\n typeof payload.product !== \"string\" ||\n typeof payload.plan !== \"string\" ||\n typeof payload.kid !== \"string\" ||\n payload.kid.length === 0 ||\n !Number.isFinite(payload.exp) ||\n !Number.isInteger(payload.seats) ||\n payload.seats < 1 ||\n !Array.isArray(payload.domains) ||\n payload.domains.some((domain) => typeof domain !== \"string\") ||\n !Array.isArray(payload.features) ||\n payload.features.some((feature) => typeof feature !== \"string\")\n ) {\n throw new LicenseError(\"INVALID_PAYLOAD\", \"License payload is invalid\");\n }\n}\n\nfunction domainAllowed(domains: readonly string[], host: string): boolean {\n const normalized = normalizeDomain(host);\n return domains.some(\n (domain) => domain === \"*\" || normalizeDomain(domain) === normalized,\n );\n}\n\nfunction normalizeDomain(value: string): string {\n try {\n const url = new URL(value.includes(\"://\") ? value : `https://${value}`);\n return url.hostname.toLowerCase();\n } catch {\n return value.toLowerCase();\n }\n}\n\nfunction decodeJson<T>(value: string, code: LicenseErrorCode): T {\n try {\n return JSON.parse(new TextDecoder().decode(base64UrlDecode(value))) as T;\n } catch {\n throw new LicenseError(code, \"License token contains invalid base64url or JSON\");\n }\n}\n\nfunction base64UrlDecode(value: string): Uint8Array<ArrayBuffer> {\n const normalized = value.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded = normalized.padEnd(Math.ceil(normalized.length / 4) * 4, \"=\");\n try {\n const binary = atob(padded);\n const bytes = new Uint8Array(new ArrayBuffer(binary.length));\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return bytes;\n } catch {\n throw new LicenseError(\"INVALID_TOKEN\", \"License token contains invalid base64url\");\n }\n}\n","/**\n * Wicklib Pro public API.\n *\n * The package is published to npm under the Wicklib Commercial License; its source\n * repository is private.\n */\n\nexport { PRO_VERSION } from \"./version\";\nexport { runScriptBacktest } from \"./script/backtest\";\nexport type {\n CompiledScriptLike,\n ScriptAlertEvent,\n ScriptBacktestOptions,\n ScriptBacktestResult,\n ScriptRunResult,\n} from \"./script/backtest\";\nexport { runBacktest } from \"./strategy/backtest\";\nexport type {\n BacktestFill,\n BacktestOptions,\n BacktestResult,\n EquityPoint,\n StrategyContext,\n StrategyFunction,\n StrategyTarget,\n} from \"./strategy/backtest\";\nexport { AlertEngine, evaluateAlerts } from \"./alerts/engine\";\nexport type {\n AlertDirection,\n AlertPriceSource,\n AlertTrigger,\n PriceAlertRule,\n} from \"./alerts/engine\";\nexport { detectAbsorption } from \"./analytics/absorption\";\nexport type { AbsorptionEvent, AbsorptionOptions } from \"./analytics/absorption\";\nexport { DepthAggregator, computeDepth } from \"./analytics/depth\";\nexport type {\n DepthBar,\n DepthLevel,\n DepthLevelBar,\n DepthOptions,\n DepthSnapshot,\n} from \"./analytics/depth\";\nexport { FootprintAggregator, computeFootprint } from \"./analytics/orderflow\";\nexport type {\n FootprintBar,\n FootprintLevel,\n FootprintOptions,\n TradeSide,\n TradeTick,\n} from \"./analytics/orderflow\";\nexport { addVolumeProfileOverlay } from \"./analytics/volume-profile-overlay\";\nexport type {\n VolumeProfileOverlay,\n VolumeProfileOverlayColors,\n VolumeProfileOverlayOptions,\n} from \"./analytics/volume-profile-overlay\";\nexport { computeVolumeProfile } from \"./analytics/volume-profile\";\nexport type {\n VolumeProfile,\n VolumeProfileBin,\n VolumeProfileDistribution,\n VolumeProfileOptions,\n} from \"./analytics/volume-profile\";\nexport { PRO_CORE_FEATURES, PRO_FEATURES } from \"./features\";\nexport type { ProFeature } from \"./features\";\nexport * from \"./extensions\";\nexport * from \"./license/verify\";\n\nimport { assertFeature, type Feature, type LicenseContext } from \"@wicklib/core\";\n\n/**\n * Returns true when the active license grants a pro feature.\n */\nexport function hasProFeature(context: LicenseContext, feature: Feature): boolean {\n return context.hasFeature(feature);\n}\n\n/**\n * Throws `WickError(\"LICENSE_REQUIRED\")` when a pro feature is not granted.\n */\nexport function assertProFeature(context: LicenseContext, feature: Feature): void {\n assertFeature(context, feature);\n}\n"],"mappings":"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","names":["assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","assertFeature","WickError","DEFAULT_IMBALANCE_RATIO","imbalanceOf","DEFAULT_BUCKET_MS","assertFeature","WickError","assertFeature","WickError","DEFAULT_OPTIONS","assertFeature"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wicklib/pro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Wicklib commercial add-on",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"directory": "packages/pro"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
|
-
"@wicklib/core": "^0.
|
|
40
|
+
"@wicklib/core": "^0.13.0"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"tsup": "^9.0.0",
|