@tradejs/node 3.0.1 → 3.1.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.
@@ -0,0 +1,31 @@
1
+ import { ClosedPnlRecord, RuntimeTradeRecord, ExchangeEntryRecord, PositionPnlSnapshot } from '@tradejs/types';
2
+
3
+ type ClosedPnlRecordWithOrderLinkId = ClosedPnlRecord & {
4
+ direction?: RuntimeTradeRecord['direction'];
5
+ entryTimestamp?: number;
6
+ orderLinkId?: string;
7
+ };
8
+ declare const takeExactClosedPnlMatch: ({ exactByOrderLinkId, exactByOrderId, symbolBuckets, orderLinkId, orderId, }: {
9
+ exactByOrderLinkId: Map<string, ClosedPnlRecordWithOrderLinkId>;
10
+ exactByOrderId: Map<string, ClosedPnlRecordWithOrderLinkId>;
11
+ symbolBuckets: Map<string, ClosedPnlRecordWithOrderLinkId[]>;
12
+ orderLinkId?: string | null;
13
+ orderId?: string | null;
14
+ }) => ClosedPnlRecordWithOrderLinkId | null;
15
+ declare const takeClosedPnlMatch: ({ exactByOrderLinkId, exactByOrderId, symbolBuckets, trade, }: {
16
+ exactByOrderLinkId: Map<string, ClosedPnlRecordWithOrderLinkId>;
17
+ exactByOrderId?: Map<string, ClosedPnlRecordWithOrderLinkId>;
18
+ symbolBuckets: Map<string, ClosedPnlRecordWithOrderLinkId[]>;
19
+ trade: RuntimeTradeRecord;
20
+ }) => ClosedPnlRecordWithOrderLinkId | null;
21
+
22
+ declare const buildExchangeFallbackRuntimeTrades: ({ entryRows, closedPnlRows, openPositions, strategyNames, existingTrades, endTime, }: {
23
+ entryRows: ExchangeEntryRecord[];
24
+ closedPnlRows: ClosedPnlRecordWithOrderLinkId[];
25
+ openPositions: PositionPnlSnapshot[];
26
+ strategyNames: string[];
27
+ existingTrades: RuntimeTradeRecord[];
28
+ endTime: number;
29
+ }) => RuntimeTradeRecord[];
30
+
31
+ export { type ClosedPnlRecordWithOrderLinkId, buildExchangeFallbackRuntimeTrades, takeClosedPnlMatch, takeExactClosedPnlMatch };
@@ -0,0 +1,31 @@
1
+ import { ClosedPnlRecord, RuntimeTradeRecord, ExchangeEntryRecord, PositionPnlSnapshot } from '@tradejs/types';
2
+
3
+ type ClosedPnlRecordWithOrderLinkId = ClosedPnlRecord & {
4
+ direction?: RuntimeTradeRecord['direction'];
5
+ entryTimestamp?: number;
6
+ orderLinkId?: string;
7
+ };
8
+ declare const takeExactClosedPnlMatch: ({ exactByOrderLinkId, exactByOrderId, symbolBuckets, orderLinkId, orderId, }: {
9
+ exactByOrderLinkId: Map<string, ClosedPnlRecordWithOrderLinkId>;
10
+ exactByOrderId: Map<string, ClosedPnlRecordWithOrderLinkId>;
11
+ symbolBuckets: Map<string, ClosedPnlRecordWithOrderLinkId[]>;
12
+ orderLinkId?: string | null;
13
+ orderId?: string | null;
14
+ }) => ClosedPnlRecordWithOrderLinkId | null;
15
+ declare const takeClosedPnlMatch: ({ exactByOrderLinkId, exactByOrderId, symbolBuckets, trade, }: {
16
+ exactByOrderLinkId: Map<string, ClosedPnlRecordWithOrderLinkId>;
17
+ exactByOrderId?: Map<string, ClosedPnlRecordWithOrderLinkId>;
18
+ symbolBuckets: Map<string, ClosedPnlRecordWithOrderLinkId[]>;
19
+ trade: RuntimeTradeRecord;
20
+ }) => ClosedPnlRecordWithOrderLinkId | null;
21
+
22
+ declare const buildExchangeFallbackRuntimeTrades: ({ entryRows, closedPnlRows, openPositions, strategyNames, existingTrades, endTime, }: {
23
+ entryRows: ExchangeEntryRecord[];
24
+ closedPnlRows: ClosedPnlRecordWithOrderLinkId[];
25
+ openPositions: PositionPnlSnapshot[];
26
+ strategyNames: string[];
27
+ existingTrades: RuntimeTradeRecord[];
28
+ endTime: number;
29
+ }) => RuntimeTradeRecord[];
30
+
31
+ export { type ClosedPnlRecordWithOrderLinkId, buildExchangeFallbackRuntimeTrades, takeClosedPnlMatch, takeExactClosedPnlMatch };
@@ -0,0 +1,321 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/runtimeTrades.ts
21
+ var runtimeTrades_exports = {};
22
+ __export(runtimeTrades_exports, {
23
+ buildExchangeFallbackRuntimeTrades: () => buildExchangeFallbackRuntimeTrades,
24
+ takeClosedPnlMatch: () => takeClosedPnlMatch,
25
+ takeExactClosedPnlMatch: () => takeExactClosedPnlMatch
26
+ });
27
+ module.exports = __toCommonJS(runtimeTrades_exports);
28
+ var import_runtimeTrades = require("@tradejs/core/runtimeTrades");
29
+
30
+ // src/runtimeTradeReconciliation.ts
31
+ var toNonEmptyString = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
32
+ var removeFromExactMaps = (exactByOrderLinkId, exactByOrderId, row) => {
33
+ for (const [key, value] of exactByOrderLinkId) {
34
+ if (value === row) exactByOrderLinkId.delete(key);
35
+ }
36
+ for (const [key, value] of exactByOrderId) {
37
+ if (value === row) exactByOrderId.delete(key);
38
+ }
39
+ };
40
+ var removeFromSymbolBuckets = (buckets, row) => {
41
+ const rows = buckets.get(row.symbol);
42
+ const index = rows?.findIndex((candidate) => candidate === row) ?? -1;
43
+ if (index >= 0) rows?.splice(index, 1);
44
+ };
45
+ var takeExactClosedPnlMatch = ({
46
+ exactByOrderLinkId,
47
+ exactByOrderId,
48
+ symbolBuckets,
49
+ orderLinkId,
50
+ orderId
51
+ }) => {
52
+ const keys = [
53
+ [exactByOrderLinkId, orderLinkId],
54
+ [exactByOrderId, orderId]
55
+ ];
56
+ for (const [bucket, key] of keys) {
57
+ const normalizedKey = toNonEmptyString(key);
58
+ if (!normalizedKey) continue;
59
+ const match = bucket.get(normalizedKey);
60
+ if (!match) continue;
61
+ removeFromExactMaps(exactByOrderLinkId, exactByOrderId, match);
62
+ removeFromSymbolBuckets(symbolBuckets, match);
63
+ return match;
64
+ }
65
+ return null;
66
+ };
67
+ var takeClosedPnlMatch = ({
68
+ exactByOrderLinkId,
69
+ exactByOrderId = /* @__PURE__ */ new Map(),
70
+ symbolBuckets,
71
+ trade
72
+ }) => {
73
+ const exactMatch = takeExactClosedPnlMatch({
74
+ exactByOrderLinkId,
75
+ exactByOrderId,
76
+ symbolBuckets,
77
+ orderLinkId: trade.orderId,
78
+ orderId: trade.orderId
79
+ });
80
+ if (exactMatch) return exactMatch;
81
+ const rows = symbolBuckets.get(trade.symbol);
82
+ if (!rows?.length) return null;
83
+ const minimumClosedAt = trade.entryTimestamp - 5 * 6e4;
84
+ const matchIndex = rows.reduce((bestIndex, row2, index) => {
85
+ if (!Number.isFinite(row2.closedAt) || row2.closedAt < minimumClosedAt || row2.direction && row2.direction !== trade.direction) {
86
+ return bestIndex;
87
+ }
88
+ if (bestIndex < 0) return index;
89
+ return row2.closedAt < rows[bestIndex].closedAt ? index : bestIndex;
90
+ }, -1);
91
+ if (matchIndex < 0) return null;
92
+ const [row] = rows.splice(matchIndex, 1);
93
+ if (row) removeFromExactMaps(exactByOrderLinkId, exactByOrderId, row);
94
+ return row ?? null;
95
+ };
96
+
97
+ // src/runtimeTrades.ts
98
+ var toNonEmptyString2 = (value) => typeof value === "string" && value.trim() ? value.trim() : null;
99
+ var roundValue = (value, digits = 2) => {
100
+ if (!Number.isFinite(value)) return 0;
101
+ const factor = 10 ** digits;
102
+ return Math.round(value * factor) / factor;
103
+ };
104
+ var removeExactMatches = (exactByOrderLinkId, exactByOrderId, row) => {
105
+ if (row.orderLinkId) exactByOrderLinkId.delete(row.orderLinkId);
106
+ if (row.orderId) exactByOrderId.delete(row.orderId);
107
+ };
108
+ var takeClosedPnlMatchForEntry = ({
109
+ exactByOrderLinkId,
110
+ exactByOrderId,
111
+ symbolBuckets,
112
+ entry
113
+ }) => {
114
+ const exactMatch = takeExactClosedPnlMatch({
115
+ exactByOrderLinkId,
116
+ exactByOrderId,
117
+ symbolBuckets,
118
+ orderLinkId: entry.orderLinkId,
119
+ orderId: entry.orderId
120
+ });
121
+ if (exactMatch) return exactMatch;
122
+ const rows = symbolBuckets.get(entry.symbol);
123
+ if (!rows?.length) return null;
124
+ const minimumClosedAt = entry.entryTimestamp - 5 * 6e4;
125
+ const matchIndex = rows.reduce((bestIndex, row, index) => {
126
+ if (!Number.isFinite(row.closedAt) || row.closedAt < minimumClosedAt || row.direction && row.direction !== entry.direction) {
127
+ return bestIndex;
128
+ }
129
+ if (bestIndex < 0) return index;
130
+ return row.closedAt < rows[bestIndex].closedAt ? index : bestIndex;
131
+ }, -1);
132
+ if (matchIndex < 0) return null;
133
+ const [match] = rows.splice(matchIndex, 1);
134
+ if (match) removeExactMatches(exactByOrderLinkId, exactByOrderId, match);
135
+ return match ?? null;
136
+ };
137
+ var aggregateExchangeEntriesByOrder = (entryRows) => {
138
+ const grouped = /* @__PURE__ */ new Map();
139
+ entryRows.forEach((entry, index) => {
140
+ const orderLinkId = toNonEmptyString2(entry.orderLinkId);
141
+ const orderId = toNonEmptyString2(entry.orderId);
142
+ const key = orderLinkId || orderId || `${entry.symbol}:${entry.direction}:${entry.entryTimestamp}:${index}`;
143
+ const existing = grouped.get(key);
144
+ const hasPrice = Number.isFinite(entry.qty) && typeof entry.entryPrice === "number" && Number.isFinite(entry.entryPrice);
145
+ if (!existing) {
146
+ grouped.set(key, {
147
+ ...entry,
148
+ qty: Number.isFinite(entry.qty) ? entry.qty : 0,
149
+ pricingQty: hasPrice ? entry.qty : 0,
150
+ pricingNotional: hasPrice ? entry.qty * (entry.entryPrice ?? 0) : 0
151
+ });
152
+ return;
153
+ }
154
+ existing.qty += Number.isFinite(entry.qty) ? entry.qty : 0;
155
+ existing.entryTimestamp = Math.min(
156
+ existing.entryTimestamp,
157
+ entry.entryTimestamp
158
+ );
159
+ if (hasPrice) {
160
+ existing.pricingQty += entry.qty;
161
+ existing.pricingNotional += entry.qty * (entry.entryPrice ?? 0);
162
+ }
163
+ });
164
+ return [...grouped.values()].map(({ pricingQty, pricingNotional, ...entry }) => ({
165
+ ...entry,
166
+ qty: roundValue(entry.qty, 8),
167
+ entryPrice: pricingQty > 0 ? roundValue(pricingNotional / pricingQty, 8) : null
168
+ })).sort((left, right) => left.entryTimestamp - right.entryTimestamp);
169
+ };
170
+ var resolveStrategy = ({
171
+ orderLinkId,
172
+ orderId,
173
+ strategyNameByOrderId,
174
+ strategyNames
175
+ }) => (orderLinkId ? strategyNameByOrderId.get(orderLinkId) : null) ?? (orderId ? strategyNameByOrderId.get(orderId) : null) ?? (0, import_runtimeTrades.resolveStrategyNameByOrderLinkId)({ orderLinkId, strategyNames });
176
+ var buildRiskLevels = (position) => {
177
+ const takeProfitPrice = position?.takeProfitPrice;
178
+ const stopLossPrice = position?.stopLossPrice;
179
+ if ((typeof takeProfitPrice !== "number" || !Number.isFinite(takeProfitPrice)) && (typeof stopLossPrice !== "number" || !Number.isFinite(stopLossPrice))) {
180
+ return null;
181
+ }
182
+ return {
183
+ ...typeof takeProfitPrice === "number" && Number.isFinite(takeProfitPrice) ? { takeProfitPrice } : {},
184
+ ...typeof stopLossPrice === "number" && Number.isFinite(stopLossPrice) ? { stopLossPrice } : {}
185
+ };
186
+ };
187
+ var buildExchangeFallbackRuntimeTrades = ({
188
+ entryRows,
189
+ closedPnlRows,
190
+ openPositions,
191
+ strategyNames,
192
+ existingTrades,
193
+ endTime
194
+ }) => {
195
+ if (!entryRows.length && !closedPnlRows.length) return [];
196
+ const strategyNameByOrderId = new Map(
197
+ existingTrades.filter(
198
+ (trade) => Boolean(trade.orderId?.trim() && trade.strategy?.trim())
199
+ ).map((trade) => [trade.orderId, trade.strategy])
200
+ );
201
+ const strategyNamesPool = [
202
+ .../* @__PURE__ */ new Set([
203
+ ...strategyNames,
204
+ ...existingTrades.map(({ strategy }) => strategy)
205
+ ])
206
+ ];
207
+ const openPositionBySymbol = new Map(
208
+ openPositions.map((position) => [position.symbol, position])
209
+ );
210
+ const existingOrderIds = new Set(
211
+ existingTrades.map(({ orderId }) => toNonEmptyString2(orderId)).filter((value) => value != null)
212
+ );
213
+ const exactByOrderLinkId = new Map(
214
+ closedPnlRows.filter((row) => Boolean(row.orderLinkId)).map((row) => [row.orderLinkId, row])
215
+ );
216
+ const exactByOrderId = new Map(
217
+ closedPnlRows.filter((row) => Boolean(row.orderId)).map((row) => [row.orderId, row])
218
+ );
219
+ const symbolBuckets = /* @__PURE__ */ new Map();
220
+ for (const row of closedPnlRows) {
221
+ const bucket = symbolBuckets.get(row.symbol) ?? [];
222
+ bucket.push(row);
223
+ symbolBuckets.set(row.symbol, bucket);
224
+ }
225
+ const fallbackTrades = aggregateExchangeEntriesByOrder(entryRows).map((entry) => {
226
+ const orderLinkId = toNonEmptyString2(entry.orderLinkId);
227
+ const orderId = toNonEmptyString2(entry.orderId);
228
+ const runtimeOrderId = orderLinkId ?? orderId;
229
+ if (!runtimeOrderId || existingOrderIds.has(runtimeOrderId)) return null;
230
+ const strategy = resolveStrategy({
231
+ orderLinkId,
232
+ orderId,
233
+ strategyNameByOrderId,
234
+ strategyNames: strategyNamesPool
235
+ });
236
+ if (!strategy) return null;
237
+ const closed = takeClosedPnlMatchForEntry({
238
+ exactByOrderLinkId,
239
+ exactByOrderId,
240
+ symbolBuckets,
241
+ entry
242
+ });
243
+ const position = openPositionBySymbol.get(entry.symbol);
244
+ const isActive = !closed && position?.direction === entry.direction && Number.isFinite(position.currentPrice) && Number.isFinite(position.unrealizedPnl);
245
+ const entryPrice = typeof entry.entryPrice === "number" && Number.isFinite(entry.entryPrice) ? entry.entryPrice : typeof closed?.entryPrice === "number" && Number.isFinite(closed.entryPrice) ? closed.entryPrice : null;
246
+ if (entryPrice == null) return null;
247
+ return {
248
+ orderId: runtimeOrderId,
249
+ strategy,
250
+ symbol: entry.symbol,
251
+ direction: entry.direction,
252
+ qty: entry.qty,
253
+ entryPrice,
254
+ actualEntryPrice: closed?.entryPrice ?? entry.entryPrice ?? null,
255
+ entryTimestamp: entry.entryTimestamp,
256
+ status: isActive ? "active" : "closed",
257
+ currentPrice: isActive ? position?.currentPrice ?? null : closed?.exitPrice ?? null,
258
+ currentPnl: isActive ? position?.unrealizedPnl ?? null : closed?.closedPnl ?? null,
259
+ closedPnl: isActive ? null : closed?.closedPnl ?? null,
260
+ exitPrice: isActive ? null : closed?.exitPrice ?? null,
261
+ actualExitPrice: isActive ? null : closed?.exitPrice ?? null,
262
+ exitTimestamp: isActive ? null : closed?.closedAt ?? null,
263
+ aiAnalysis: isActive ? buildRiskLevels(position) : null,
264
+ openFee: closed?.openFee ?? entry.openFee ?? null,
265
+ closeFee: closed?.closeFee ?? entry.closeFee ?? null,
266
+ fundingFee: closed?.fundingFee ?? entry.fundingFee ?? null,
267
+ totalFee: closed?.totalFee ?? entry.totalFee ?? null,
268
+ lastSyncedAt: endTime
269
+ };
270
+ }).filter((trade) => trade != null);
271
+ const usedOrderIds = /* @__PURE__ */ new Set([
272
+ ...existingOrderIds,
273
+ ...fallbackTrades.map(({ orderId }) => orderId)
274
+ ]);
275
+ const remainingClosedTrades = [...symbolBuckets.values()].flat().map((row) => {
276
+ const orderLinkId = toNonEmptyString2(row.orderLinkId);
277
+ const orderId = toNonEmptyString2(row.orderId);
278
+ const runtimeOrderId = orderLinkId ?? orderId;
279
+ if (!runtimeOrderId || usedOrderIds.has(runtimeOrderId)) return null;
280
+ const strategy = resolveStrategy({
281
+ orderLinkId,
282
+ orderId,
283
+ strategyNameByOrderId,
284
+ strategyNames: strategyNamesPool
285
+ });
286
+ if (!strategy || row.entryPrice == null || !Number.isFinite(row.entryPrice) || !row.direction) {
287
+ return null;
288
+ }
289
+ return {
290
+ orderId: runtimeOrderId,
291
+ strategy,
292
+ symbol: row.symbol,
293
+ direction: row.direction,
294
+ qty: row.qty,
295
+ entryPrice: row.entryPrice,
296
+ actualEntryPrice: row.entryPrice,
297
+ entryTimestamp: typeof row.entryTimestamp === "number" && Number.isFinite(row.entryTimestamp) ? row.entryTimestamp : row.closedAt,
298
+ status: "closed",
299
+ currentPrice: row.exitPrice,
300
+ currentPnl: row.closedPnl,
301
+ closedPnl: row.closedPnl,
302
+ exitPrice: row.exitPrice,
303
+ actualExitPrice: row.exitPrice,
304
+ exitTimestamp: row.closedAt,
305
+ openFee: row.openFee ?? null,
306
+ closeFee: row.closeFee ?? null,
307
+ fundingFee: row.fundingFee ?? null,
308
+ totalFee: row.totalFee ?? null,
309
+ lastSyncedAt: endTime
310
+ };
311
+ }).filter((trade) => trade != null);
312
+ return [...fallbackTrades, ...remainingClosedTrades].sort(
313
+ (left, right) => left.entryTimestamp - right.entryTimestamp
314
+ );
315
+ };
316
+ // Annotate the CommonJS export names for ESM import in node:
317
+ 0 && (module.exports = {
318
+ buildExchangeFallbackRuntimeTrades,
319
+ takeClosedPnlMatch,
320
+ takeExactClosedPnlMatch
321
+ });
@@ -0,0 +1,11 @@
1
+ import {
2
+ buildExchangeFallbackRuntimeTrades,
3
+ takeClosedPnlMatch,
4
+ takeExactClosedPnlMatch
5
+ } from "./chunk-FB5NUEOQ.mjs";
6
+ import "./chunk-Y6FXYEAI.mjs";
7
+ export {
8
+ buildExchangeFallbackRuntimeTrades,
9
+ takeClosedPnlMatch,
10
+ takeExactClosedPnlMatch
11
+ };
@@ -1,6 +1,6 @@
1
1
  export * from '@tradejs/core/strategies';
2
- export { DEFAULT_AI_MODEL, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, buildCompactAiIndicatorsSnapshot, getDeterministicAiGateContext, getOpenRouterModelKwargs, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.mjs';
3
- export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.mjs';
2
+ export { AiChatMessage, DEFAULT_AI_MODEL, InvokeAiChatOptions, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, buildCompactAiIndicatorsSnapshot, getDeterministicAiGateContext, getOpenRouterModelKwargs, invokeAiChat, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.mjs';
3
+ export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyDefaults, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.mjs';
4
4
  import { StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, RuntimeStrategyConfigSnapshot, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Connector, Tp, MarketFeatureInterval, StrategyEntrySignalContext } from '@tradejs/types';
5
5
  import { TradejsConfigOnBarHook, TradejsConfigBeforeSignalsHook } from '@tradejs/core/config';
6
6
 
@@ -1,6 +1,6 @@
1
1
  export * from '@tradejs/core/strategies';
2
- export { DEFAULT_AI_MODEL, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, buildCompactAiIndicatorsSnapshot, getDeterministicAiGateContext, getOpenRouterModelKwargs, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.js';
3
- export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.js';
2
+ export { AiChatMessage, DEFAULT_AI_MODEL, InvokeAiChatOptions, MAX_AI_SERIES_POINTS, askAI, buildAiHumanPrompt, buildAiPayload, buildAiPrompts, buildAiSystemPrompt, buildCompactAiIndicatorsSnapshot, getDeterministicAiGateContext, getOpenRouterModelKwargs, invokeAiChat, resetAiRuntimeCache, runAiPrompt, runAiPromptLocal, trimSeriesDeep } from './ai.js';
3
+ export { ensureIndicatorPluginsLoaded, ensureStrategyPluginsLoaded, getAvailableStrategyNames, getRegisteredManifests, getRegisteredStrategies, getStrategyCreator, getStrategyDefaults, getStrategyManifest, isKnownStrategy, registerStrategyEntries, resetStrategyRegistryCache, strategies } from './registry.js';
4
4
  import { StrategyConfig, CreateStrategyCore, StrategyManifest, StrategyCreator, RuntimeStrategyConfigSnapshot, Signal, Direction, StrategyRuntimeMlOptions, StrategyRuntimeAiOptions, Connector, Tp, MarketFeatureInterval, StrategyEntrySignalContext } from '@tradejs/types';
5
5
  import { TradejsConfigOnBarHook, TradejsConfigBeforeSignalsHook } from '@tradejs/core/config';
6
6