@backtest-kit/ui 3.8.0 → 5.0.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.
Files changed (22) hide show
  1. package/build/index.cjs +383 -6
  2. package/build/index.mjs +384 -7
  3. package/build/modules/frontend/build/assets/Background-hRKtQSrv.js +1 -0
  4. package/build/modules/frontend/build/assets/{IconPhoto-DLj3pG_p.js → IconPhoto-DQlKNGdb.js} +1 -1
  5. package/build/modules/frontend/build/assets/{KeyboardArrowLeft-DLEPx5Pm.js → KeyboardArrowLeft-wYBUTbRV.js} +1 -1
  6. package/build/modules/frontend/build/assets/{Refresh-BDbWoqW-.js → Refresh-_yMWRw_x.js} +1 -1
  7. package/build/modules/frontend/build/assets/{index-zSnwHsC4.js → index-3gnGrSPi.js} +12 -12
  8. package/build/modules/frontend/build/assets/index-BFSXu2bZ.js +1 -0
  9. package/build/modules/frontend/build/assets/index-BPJ87g-R.js +1 -0
  10. package/build/modules/frontend/build/assets/index-BUme2lKb.js +1 -0
  11. package/build/modules/frontend/build/assets/index-Bay1AtTY.js +1 -0
  12. package/build/modules/frontend/build/assets/index-Kwt_oEAl.js +1 -0
  13. package/build/modules/frontend/build/assets/index-TU650r8r.js +1 -0
  14. package/build/modules/frontend/build/assets/markdownit-CZc4lN8k.js +1 -0
  15. package/build/modules/frontend/build/index.html +1 -1
  16. package/package.json +3 -3
  17. package/types.d.ts +65 -0
  18. package/build/modules/frontend/build/assets/index-BWNCsO4C.js +0 -1
  19. package/build/modules/frontend/build/assets/index-D2XsO1HQ.js +0 -1
  20. package/build/modules/frontend/build/assets/index-YO0gE9Ra.js +0 -1
  21. package/build/modules/frontend/build/assets/index-wbcZHlIz.js +0 -1
  22. package/build/modules/frontend/build/assets/markdownit-DzS63FBS.js +0 -1
package/build/index.cjs CHANGED
@@ -68,12 +68,14 @@ const mockServices$1 = {
68
68
  storageMockService: Symbol("storageMockService"),
69
69
  exchangeMockService: Symbol("exchangeMockService"),
70
70
  logMockService: Symbol("logMockService"),
71
+ statusMockService: Symbol("statusMockService"),
71
72
  };
72
73
  const viewServices$1 = {
73
74
  notificationViewService: Symbol("notificationViewService"),
74
75
  storageViewService: Symbol("storageViewService"),
75
76
  exchangeViewService: Symbol("exchangeViewService"),
76
77
  logViewService: Symbol("logViewService"),
78
+ statusViewService: Symbol("statusViewService"),
77
79
  };
78
80
  const TYPES = {
79
81
  ...baseServices$1,
@@ -176,9 +178,9 @@ class LoggerService {
176
178
  }
177
179
  }
178
180
 
179
- const MOCK_PATH$2 = "./mock/notifications.json";
181
+ const MOCK_PATH$3 = "./mock/notifications.json";
180
182
  const READ_NOTIFICATION_LIST_FN = functoolsKit.singleshot(async () => {
181
- const data = await fs.readFile(MOCK_PATH$2, "utf-8");
183
+ const data = await fs.readFile(MOCK_PATH$3, "utf-8");
182
184
  return JSON.parse(data);
183
185
  });
184
186
  const DEFAULT_LIMIT$3 = 25;
@@ -238,9 +240,9 @@ class NotificationMockService {
238
240
  }
239
241
  }
240
242
 
241
- const MOCK_PATH$1 = "./mock/db";
243
+ const MOCK_PATH$2 = "./mock/db";
242
244
  const READ_BACKTEST_STORAGE_FN = functoolsKit.singleshot(async () => {
243
- const dbPath = path.join(process.cwd(), MOCK_PATH$1);
245
+ const dbPath = path.join(process.cwd(), MOCK_PATH$2);
244
246
  const files = await fs.readdir(dbPath);
245
247
  const signals = [];
246
248
  for (const file of files) {
@@ -275,6 +277,7 @@ class StorageMockService {
275
277
  }
276
278
  }
277
279
 
280
+ const MS_PER_MINUTE$1 = 60000;
278
281
  class ExchangeMockService {
279
282
  constructor() {
280
283
  this.loggerService = inject(TYPES.loggerService);
@@ -298,12 +301,31 @@ class ExchangeMockService {
298
301
  interval,
299
302
  });
300
303
  };
304
+ this.getLiveCandles = async (signalId, interval) => {
305
+ this.loggerService.log("exchangeMockService getLiveCandles", {
306
+ signalId,
307
+ interval,
308
+ });
309
+ const signal = await this.storageMockService.findSignalById(signalId);
310
+ if (!signal) {
311
+ throw new Error(`Signal with ID ${signalId} not found`);
312
+ }
313
+ const { pendingAt, scheduledAt, minuteEstimatedTime, } = signal;
314
+ const eventAt = pendingAt || scheduledAt;
315
+ return await this.exchangeService.getRangeCandles({
316
+ symbol: signal.symbol,
317
+ exchangeName: signal.exchangeName,
318
+ signalStartTime: eventAt,
319
+ signalStopTime: eventAt + minuteEstimatedTime * MS_PER_MINUTE$1,
320
+ interval,
321
+ });
322
+ };
301
323
  }
302
324
  }
303
325
 
304
- const MOCK_PATH = "./mock/logs.json";
326
+ const MOCK_PATH$1 = "./mock/logs.json";
305
327
  const READ_LOG_LIST_FN = functoolsKit.singleshot(async () => {
306
- const data = await fs.readFile(MOCK_PATH, "utf-8");
328
+ const data = await fs.readFile(MOCK_PATH$1, "utf-8");
307
329
  return JSON.parse(data);
308
330
  });
309
331
  const DEFAULT_LIMIT$2 = 25;
@@ -351,6 +373,68 @@ class LogMockService {
351
373
  }
352
374
  }
353
375
 
376
+ const MOCK_PATH = "./mock/status.json";
377
+ const READ_STATUS_LIST_FN = functoolsKit.singleshot(async () => {
378
+ const data = await fs.readFile(MOCK_PATH, "utf-8");
379
+ return JSON.parse(data);
380
+ });
381
+ class StatusMockService {
382
+ constructor() {
383
+ this.loggerService = inject(TYPES.loggerService);
384
+ this.getStatusList = async () => {
385
+ this.loggerService.log("statusMockService getStatusList");
386
+ const list = await READ_STATUS_LIST_FN();
387
+ return list.map(({ id, symbol, strategyName, exchangeName }) => ({
388
+ id,
389
+ symbol,
390
+ strategyName,
391
+ exchangeName,
392
+ status: "pending",
393
+ }));
394
+ };
395
+ this.getStatusMap = async () => {
396
+ this.loggerService.log("statusMockService getStatusMap");
397
+ const list = await this.getStatusList();
398
+ return list.reduce((acm, cur) => ({ ...acm, [cur.id]: cur }), {});
399
+ };
400
+ this.getStatusOne = async (id) => {
401
+ this.loggerService.log("statusMockService getStatusOne", { id });
402
+ const list = await READ_STATUS_LIST_FN();
403
+ const signal = list.find((s) => s.id === id);
404
+ if (!signal) {
405
+ return null;
406
+ }
407
+ const positionEntries = signal._entry ?? [];
408
+ const positionLevels = positionEntries.map((e) => e.price);
409
+ const positionPartials = signal._partial ?? [];
410
+ return {
411
+ signalId: signal.signalId,
412
+ position: signal.position,
413
+ symbol: signal.symbol,
414
+ exchangeName: signal.exchangeName,
415
+ strategyName: signal.strategyName,
416
+ totalEntries: signal.totalEntries,
417
+ totalPartials: signal.totalPartials,
418
+ originalPriceStopLoss: signal.originalPriceStopLoss,
419
+ originalPriceTakeProfit: signal.originalPriceTakeProfit,
420
+ originalPriceOpen: signal.originalPriceOpen,
421
+ priceOpen: signal.priceOpen,
422
+ priceTakeProfit: signal.priceTakeProfit,
423
+ priceStopLoss: signal.priceStopLoss,
424
+ pnlPercentage: signal.pnl.pnlPercentage,
425
+ pnlCost: signal.pnl.pnlCost,
426
+ pnlEntries: signal.pnl.pnlEntries,
427
+ partialExecuted: signal.partialExecuted,
428
+ minuteEstimatedTime: signal.minuteEstimatedTime,
429
+ pendingAt: signal.pendingAt,
430
+ positionLevels,
431
+ positionEntries,
432
+ positionPartials,
433
+ };
434
+ };
435
+ }
436
+ }
437
+
354
438
  const DEFAULT_LIMIT$1 = 25;
355
439
  const DEFAULT_OFFSET$1 = 0;
356
440
  const CREATE_FILTER_LIST_FN$1 = (filterData) => Object.keys(filterData).map((key) => (row) => new RegExp(filterData[key], "i").test(row[key]));
@@ -495,6 +579,7 @@ class StorageViewService {
495
579
  }
496
580
  }
497
581
 
582
+ const MS_PER_MINUTE = 60000;
498
583
  class ExchangeViewService {
499
584
  constructor() {
500
585
  this.loggerService = inject(TYPES.loggerService);
@@ -522,6 +607,28 @@ class ExchangeViewService {
522
607
  interval,
523
608
  });
524
609
  };
610
+ this.getLiveCandles = async (signalId, interval) => {
611
+ this.loggerService.log("exchangeViewService getLiveCandles", {
612
+ signalId,
613
+ interval,
614
+ });
615
+ if (CC_ENABLE_MOCK) {
616
+ return await this.exchangeMockService.getLiveCandles(signalId, interval);
617
+ }
618
+ const signal = await this.storageViewService.findSignalById(signalId);
619
+ if (!signal) {
620
+ throw new Error(`Signal with ID ${signalId} not found`);
621
+ }
622
+ const { pendingAt, scheduledAt, minuteEstimatedTime, } = signal;
623
+ const eventAt = pendingAt || scheduledAt;
624
+ return await this.exchangeService.getRangeCandles({
625
+ symbol: signal.symbol,
626
+ exchangeName: signal.exchangeName,
627
+ signalStartTime: eventAt,
628
+ signalStopTime: eventAt + minuteEstimatedTime * MS_PER_MINUTE,
629
+ interval,
630
+ });
631
+ };
525
632
  }
526
633
  }
527
634
 
@@ -580,6 +687,100 @@ class LogViewService {
580
687
  }
581
688
  }
582
689
 
690
+ class StatusViewService {
691
+ constructor() {
692
+ this.loggerService = inject(TYPES.loggerService);
693
+ this.statusMockService = inject(TYPES.statusMockService);
694
+ this.getStatusList = async () => {
695
+ this.loggerService.log("statusViewService getStatusList");
696
+ if (CC_ENABLE_MOCK) {
697
+ const liveList = await this.statusMockService.getStatusList();
698
+ return liveList.filter(({ status }) => status === "pending");
699
+ }
700
+ return await backtestKit.Live.list();
701
+ };
702
+ this.getStatusMap = async () => {
703
+ this.loggerService.log("statusViewService getStatusMap");
704
+ if (CC_ENABLE_MOCK) {
705
+ return await this.statusMockService.getStatusMap();
706
+ }
707
+ const liveList = await backtestKit.Live.list();
708
+ return liveList
709
+ .filter(({ status }) => status === "pending")
710
+ .reduce((acm, cur) => ({ ...acm, [cur.id]: cur }), {});
711
+ };
712
+ this.getStatusOne = async (id) => {
713
+ this.loggerService.log("statusViewService getStatusOne", {
714
+ id,
715
+ });
716
+ if (CC_ENABLE_MOCK) {
717
+ return await this.statusMockService.getStatusOne(id);
718
+ }
719
+ const liveList = await backtestKit.Live.list();
720
+ const liveOne = liveList.find((live) => live.id === id);
721
+ if (!liveOne) {
722
+ throw new Error(`Live with id ${id} not found`);
723
+ }
724
+ const { symbol, strategyName, exchangeName } = liveOne;
725
+ const currentPrice = await backtestKit.Exchange.getAveragePrice(symbol, {
726
+ exchangeName,
727
+ });
728
+ const pendingSignal = await backtestKit.Live.getPendingSignal(symbol, currentPrice, {
729
+ strategyName,
730
+ exchangeName,
731
+ });
732
+ if (!pendingSignal) {
733
+ return null;
734
+ }
735
+ const positionLevels = await backtestKit.Live.getPositionLevels(symbol, {
736
+ strategyName,
737
+ exchangeName,
738
+ });
739
+ if (!positionLevels) {
740
+ return null;
741
+ }
742
+ const positionEntries = await backtestKit.Live.getPositionEntries(symbol, {
743
+ strategyName,
744
+ exchangeName,
745
+ });
746
+ if (!positionEntries) {
747
+ return null;
748
+ }
749
+ const positionPartials = await backtestKit.Live.getPositionPartials(symbol, {
750
+ strategyName,
751
+ exchangeName,
752
+ });
753
+ if (!positionPartials) {
754
+ return null;
755
+ }
756
+ return {
757
+ signalId: pendingSignal.id,
758
+ position: pendingSignal.position,
759
+ symbol: pendingSignal.symbol,
760
+ exchangeName: pendingSignal.exchangeName,
761
+ strategyName: pendingSignal.strategyName,
762
+ totalEntries: pendingSignal.totalEntries,
763
+ totalPartials: pendingSignal.totalPartials,
764
+ originalPriceStopLoss: pendingSignal.originalPriceStopLoss,
765
+ originalPriceTakeProfit: pendingSignal.originalPriceTakeProfit,
766
+ originalPriceOpen: pendingSignal.originalPriceOpen,
767
+ priceOpen: pendingSignal.priceOpen,
768
+ priceTakeProfit: pendingSignal.priceTakeProfit,
769
+ priceStopLoss: pendingSignal.priceStopLoss,
770
+ pnlPercentage: pendingSignal.pnl.pnlPercentage,
771
+ pnlCost: pendingSignal.pnl.pnlCost,
772
+ pnlEntries: pendingSignal.pnl.pnlEntries,
773
+ partialExecuted: pendingSignal.partialExecuted,
774
+ pendingAt: pendingSignal.pendingAt,
775
+ minuteEstimatedTime: pendingSignal.minuteEstimatedTime,
776
+ positionEntries,
777
+ positionLevels,
778
+ positionPartials,
779
+ };
780
+ };
781
+ }
782
+ }
783
+
583
784
  const symbol_list = [
584
785
  {
585
786
  icon: "/icon/btc.png",
@@ -764,12 +965,14 @@ class PriceConnectionService {
764
965
  provide(TYPES.storageMockService, () => new StorageMockService());
765
966
  provide(TYPES.exchangeMockService, () => new ExchangeMockService());
766
967
  provide(TYPES.logMockService, () => new LogMockService());
968
+ provide(TYPES.statusMockService, () => new StatusMockService());
767
969
  }
768
970
  {
769
971
  provide(TYPES.notificationViewService, () => new NotificationViewService());
770
972
  provide(TYPES.storageViewService, () => new StorageViewService());
771
973
  provide(TYPES.exchangeViewService, () => new ExchangeViewService());
772
974
  provide(TYPES.logViewService, () => new LogViewService());
975
+ provide(TYPES.statusViewService, () => new StatusViewService());
773
976
  }
774
977
 
775
978
  const baseServices = {
@@ -788,12 +991,14 @@ const mockServices = {
788
991
  storageMockService: inject(TYPES.storageMockService),
789
992
  exchangeMockService: inject(TYPES.exchangeMockService),
790
993
  logMockService: inject(TYPES.logMockService),
994
+ statusMockService: inject(TYPES.statusMockService),
791
995
  };
792
996
  const viewServices = {
793
997
  notificationViewService: inject(TYPES.notificationViewService),
794
998
  storageViewService: inject(TYPES.storageViewService),
795
999
  exchangeViewService: inject(TYPES.exchangeViewService),
796
1000
  logViewService: inject(TYPES.logViewService),
1001
+ statusViewService: inject(TYPES.statusViewService),
797
1002
  };
798
1003
  const ioc = {
799
1004
  ...baseServices,
@@ -1127,6 +1332,92 @@ router$6.post("/api/v1/mock/log_filter", async (req, res) => {
1127
1332
  });
1128
1333
  }
1129
1334
  });
1335
+ router$6.post("/api/v1/mock/candles_live", async (req, res) => {
1336
+ try {
1337
+ const request = await micro.json(req);
1338
+ const { signalId, interval, requestId, serviceName } = request;
1339
+ const data = await ioc.exchangeMockService.getLiveCandles(signalId, interval);
1340
+ const result = {
1341
+ data,
1342
+ status: "ok",
1343
+ error: "",
1344
+ requestId,
1345
+ serviceName,
1346
+ };
1347
+ ioc.loggerService.log("/api/v1/mock/candles_live ok", {
1348
+ request,
1349
+ result: omit(result, "data"),
1350
+ });
1351
+ return await micro.send(res, 200, result);
1352
+ }
1353
+ catch (error) {
1354
+ ioc.loggerService.log("/api/v1/mock/candles_live error", {
1355
+ error: functoolsKit.errorData(error),
1356
+ });
1357
+ return await micro.send(res, 200, {
1358
+ status: "error",
1359
+ error: functoolsKit.getErrorMessage(error),
1360
+ });
1361
+ }
1362
+ });
1363
+ // StatusMockService endpoints
1364
+ router$6.post("/api/v1/mock/status_list", async (req, res) => {
1365
+ try {
1366
+ const request = await micro.json(req);
1367
+ const { requestId, serviceName } = request;
1368
+ const data = await ioc.statusMockService.getStatusList();
1369
+ const result = {
1370
+ data,
1371
+ status: "ok",
1372
+ error: "",
1373
+ requestId,
1374
+ serviceName,
1375
+ };
1376
+ ioc.loggerService.log("/api/v1/mock/status_list ok", {
1377
+ request,
1378
+ result: omit(result, "data"),
1379
+ });
1380
+ return await micro.send(res, 200, result);
1381
+ }
1382
+ catch (error) {
1383
+ ioc.loggerService.log("/api/v1/mock/status_list error", {
1384
+ error: functoolsKit.errorData(error),
1385
+ });
1386
+ return await micro.send(res, 200, {
1387
+ status: "error",
1388
+ error: functoolsKit.getErrorMessage(error),
1389
+ });
1390
+ }
1391
+ });
1392
+ router$6.post("/api/v1/mock/status_one/:id", async (req, res) => {
1393
+ try {
1394
+ const request = await micro.json(req);
1395
+ const { requestId, serviceName } = request;
1396
+ const id = req.params.id;
1397
+ const data = await ioc.statusMockService.getStatusOne(id);
1398
+ const result = {
1399
+ data,
1400
+ status: "ok",
1401
+ error: "",
1402
+ requestId,
1403
+ serviceName,
1404
+ };
1405
+ ioc.loggerService.log("/api/v1/mock/status_one/:id ok", {
1406
+ request,
1407
+ result: omit(result, "data"),
1408
+ });
1409
+ return await micro.send(res, 200, result);
1410
+ }
1411
+ catch (error) {
1412
+ ioc.loggerService.log("/api/v1/mock/status_one/:id error", {
1413
+ error: functoolsKit.errorData(error),
1414
+ });
1415
+ return await micro.send(res, 200, {
1416
+ status: "error",
1417
+ error: functoolsKit.getErrorMessage(error),
1418
+ });
1419
+ }
1420
+ });
1130
1421
 
1131
1422
  const router$5 = Router({
1132
1423
  params: true,
@@ -1193,6 +1484,34 @@ router$5.post("/api/v1/view/candles_point", async (req, res) => {
1193
1484
  });
1194
1485
  }
1195
1486
  });
1487
+ router$5.post("/api/v1/view/candles_live", async (req, res) => {
1488
+ try {
1489
+ const request = await micro.json(req);
1490
+ const { signalId, interval, requestId, serviceName } = request;
1491
+ const data = await ioc.exchangeViewService.getLiveCandles(signalId, interval);
1492
+ const result = {
1493
+ data,
1494
+ status: "ok",
1495
+ error: "",
1496
+ requestId,
1497
+ serviceName,
1498
+ };
1499
+ ioc.loggerService.log("/api/v1/view/candles_live ok", {
1500
+ request,
1501
+ result: omit(result, "data"),
1502
+ });
1503
+ return await micro.send(res, 200, result);
1504
+ }
1505
+ catch (error) {
1506
+ ioc.loggerService.log("/api/v1/view/candles_live error", {
1507
+ error: functoolsKit.errorData(error),
1508
+ });
1509
+ return await micro.send(res, 200, {
1510
+ status: "error",
1511
+ error: functoolsKit.getErrorMessage(error),
1512
+ });
1513
+ }
1514
+ });
1196
1515
  // NotificationViewService endpoints
1197
1516
  router$5.post("/api/v1/view/notification_list", async (req, res) => {
1198
1517
  try {
@@ -1451,6 +1770,64 @@ router$5.post("/api/v1/view/log_filter", async (req, res) => {
1451
1770
  });
1452
1771
  }
1453
1772
  });
1773
+ // StatusViewService endpoints
1774
+ router$5.post("/api/v1/view/status_list", async (req, res) => {
1775
+ try {
1776
+ const request = await micro.json(req);
1777
+ const { requestId, serviceName } = request;
1778
+ const data = await ioc.statusViewService.getStatusList();
1779
+ const result = {
1780
+ data,
1781
+ status: "ok",
1782
+ error: "",
1783
+ requestId,
1784
+ serviceName,
1785
+ };
1786
+ ioc.loggerService.log("/api/v1/view/status_list ok", {
1787
+ request,
1788
+ result: omit(result, "data"),
1789
+ });
1790
+ return await micro.send(res, 200, result);
1791
+ }
1792
+ catch (error) {
1793
+ ioc.loggerService.log("/api/v1/view/status_list error", {
1794
+ error: functoolsKit.errorData(error),
1795
+ });
1796
+ return await micro.send(res, 200, {
1797
+ status: "error",
1798
+ error: functoolsKit.getErrorMessage(error),
1799
+ });
1800
+ }
1801
+ });
1802
+ router$5.post("/api/v1/view/status_one/:id", async (req, res) => {
1803
+ try {
1804
+ const request = await micro.json(req);
1805
+ const { requestId, serviceName } = request;
1806
+ const id = req.params.id;
1807
+ const data = await ioc.statusViewService.getStatusOne(id);
1808
+ const result = {
1809
+ data,
1810
+ status: "ok",
1811
+ error: "",
1812
+ requestId,
1813
+ serviceName,
1814
+ };
1815
+ ioc.loggerService.log("/api/v1/view/status_one/:id ok", {
1816
+ request,
1817
+ result: omit(result, "data"),
1818
+ });
1819
+ return await micro.send(res, 200, result);
1820
+ }
1821
+ catch (error) {
1822
+ ioc.loggerService.log("/api/v1/view/status_one/:id error", {
1823
+ error: functoolsKit.errorData(error),
1824
+ });
1825
+ return await micro.send(res, 200, {
1826
+ status: "error",
1827
+ error: functoolsKit.getErrorMessage(error),
1828
+ });
1829
+ }
1830
+ });
1454
1831
 
1455
1832
  const require$2 = module$1.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href)));
1456
1833
  function getModulesPath() {