@tradejs/node 3.0.0 → 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.
- package/README.md +2 -0
- package/dist/ai.d.mts +26 -4
- package/dist/ai.d.ts +26 -4
- package/dist/ai.js +161 -165
- package/dist/ai.mjs +3 -1
- package/dist/backtest.js +496 -188
- package/dist/backtest.mjs +3 -3
- package/dist/chunk-3TWULKHV.mjs +595 -0
- package/dist/chunk-FB5NUEOQ.mjs +295 -0
- package/dist/{chunk-VRXU4E4O.mjs → chunk-KOQSLFT2.mjs} +169 -169
- package/dist/chunk-LAJ7NA3Q.mjs +377 -0
- package/dist/{chunk-OGAWBO3Z.mjs → chunk-MKLTJQLY.mjs} +1 -1
- package/dist/cli.js +150 -161
- package/dist/cli.mjs +1 -1
- package/dist/connectors.d.mts +5 -2
- package/dist/connectors.d.ts +5 -2
- package/dist/connectors.js +329 -8
- package/dist/connectors.mjs +5 -1
- package/dist/registry.d.mts +2 -1
- package/dist/registry.d.ts +2 -1
- package/dist/registry.js +157 -161
- package/dist/registry.mjs +4 -2
- package/dist/runtimeDashboard.d.mts +12 -0
- package/dist/runtimeDashboard.d.ts +12 -0
- package/dist/runtimeDashboard.js +8433 -0
- package/dist/runtimeDashboard.mjs +955 -0
- package/dist/runtimeTrades.d.mts +31 -0
- package/dist/runtimeTrades.d.ts +31 -0
- package/dist/runtimeTrades.js +321 -0
- package/dist/runtimeTrades.mjs +11 -0
- package/dist/strategies.d.mts +2 -2
- package/dist/strategies.d.ts +2 -2
- package/dist/strategies.js +168 -165
- package/dist/strategies.mjs +13 -372
- package/package.json +18 -5
- package/dist/chunk-V3YMKE4I.mjs +0 -271
|
@@ -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
|
+
};
|
package/dist/strategies.d.mts
CHANGED
|
@@ -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
|
|
package/dist/strategies.d.ts
CHANGED
|
@@ -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
|
|