@backtest-kit/ui 3.1.2 → 3.2.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/build/index.cjs +114 -33
- package/build/index.mjs +116 -35
- package/build/modules/frontend/build/assets/IconPhoto-CC-I1xI7.js +1 -0
- package/build/modules/frontend/build/assets/index-CtieOfv6.js +1 -0
- package/build/modules/frontend/build/assets/{index-CHpWEHVB.js → index-DawE4H64.js} +9 -8
- package/build/modules/frontend/build/assets/index-Metwj24g.js +1 -0
- package/build/modules/frontend/build/assets/markdownit-Do1eTw3R.js +1 -0
- package/build/modules/frontend/build/index.html +1 -1
- package/package.json +3 -2
- package/types.d.ts +13 -3
- package/build/modules/frontend/build/assets/index-BjHVzUVO.js +0 -1
- package/build/modules/frontend/build/assets/markdownit-Bg4a7DMF.js +0 -1
package/build/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
|
-
import { isObject, singleshot, pickDocuments, str, memoize, errorData, getErrorMessage } from 'functools-kit';
|
|
2
|
+
import { isObject, singleshot, pickDocuments, str, memoize, BehaviorSubject, waitForNext, errorData, getErrorMessage } from 'functools-kit';
|
|
3
3
|
import micro from 'micro';
|
|
4
4
|
import Router from 'router';
|
|
5
5
|
import finalhandler from 'finalhandler';
|
|
6
6
|
import serveHandler from 'serve-handler';
|
|
7
7
|
import os from 'os';
|
|
8
8
|
import { createActivator } from 'di-kit';
|
|
9
|
-
import { Exchange, Notification, Storage } from 'backtest-kit';
|
|
9
|
+
import { Exchange, Notification, Storage, listenSignal } from 'backtest-kit';
|
|
10
10
|
import fs, { readdir, readFile } from 'fs/promises';
|
|
11
11
|
import path, { join, dirname } from 'path';
|
|
12
12
|
import { createRequire } from 'module';
|
|
@@ -17,10 +17,10 @@ const CC_WWWROOT_HOST = process.env.CC_WWWROOT_HOST || "0.0.0.0";
|
|
|
17
17
|
const CC_WWWROOT_PORT = parseInt(process.env.CC_WWWROOT_PORT) || 60050;
|
|
18
18
|
const CC_ENABLE_MOCK = !!parseInt(process.env.CC_ENABLE_MOCK) || false;
|
|
19
19
|
|
|
20
|
-
const router$
|
|
20
|
+
const router$7 = Router({
|
|
21
21
|
params: true,
|
|
22
22
|
});
|
|
23
|
-
router$
|
|
23
|
+
router$7.get("/api/v1/health/health_check", async (req, res) => {
|
|
24
24
|
const [cpuLoad] = os.loadavg();
|
|
25
25
|
return await micro.send(res, 200, {
|
|
26
26
|
uptime: process.uptime(),
|
|
@@ -55,6 +55,7 @@ const baseServices$1 = {
|
|
|
55
55
|
};
|
|
56
56
|
const connectionServices$1 = {
|
|
57
57
|
symbolConnectionService: Symbol("symbolConnectionService"),
|
|
58
|
+
priceConnectionService: Symbol("priceConnectionService"),
|
|
58
59
|
};
|
|
59
60
|
const metaServices$1 = {
|
|
60
61
|
symbolMetaService: Symbol("symbolMetaService"),
|
|
@@ -594,12 +595,56 @@ class SymbolMetaService {
|
|
|
594
595
|
}
|
|
595
596
|
}
|
|
596
597
|
|
|
598
|
+
const PRICE_TIMEOUT = 120000;
|
|
599
|
+
const CREATE_KEY_FN = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
600
|
+
const parts = [symbol, strategyName, exchangeName];
|
|
601
|
+
if (frameName)
|
|
602
|
+
parts.push(frameName);
|
|
603
|
+
parts.push(backtest ? "backtest" : "live");
|
|
604
|
+
return parts.join(":");
|
|
605
|
+
};
|
|
606
|
+
const GET_SUBJECT_FN = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
607
|
+
const GET_PRICE_FN = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
608
|
+
const priceSubject = GET_SUBJECT_FN(symbol, strategyName, exchangeName, frameName, backtest);
|
|
609
|
+
if (priceSubject.data) {
|
|
610
|
+
return priceSubject.data;
|
|
611
|
+
}
|
|
612
|
+
return await waitForNext(priceSubject, (data) => !!data, PRICE_TIMEOUT);
|
|
613
|
+
};
|
|
614
|
+
class PriceConnectionService {
|
|
615
|
+
constructor() {
|
|
616
|
+
this.loggerService = inject(TYPES.loggerService);
|
|
617
|
+
this.getSignalPendingPrice = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
618
|
+
this.loggerService.log("priceConnectionService getSignalPendingPrice", {
|
|
619
|
+
symbol,
|
|
620
|
+
strategyName,
|
|
621
|
+
exchangeName,
|
|
622
|
+
frameName,
|
|
623
|
+
backtest,
|
|
624
|
+
});
|
|
625
|
+
const currentPrice = await GET_PRICE_FN(symbol, strategyName, exchangeName, frameName, backtest);
|
|
626
|
+
if (typeof currentPrice === "symbol") {
|
|
627
|
+
throw new Error(`Price for ${CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest)} not received within timeout`);
|
|
628
|
+
}
|
|
629
|
+
return currentPrice;
|
|
630
|
+
};
|
|
631
|
+
this.init = singleshot(async () => {
|
|
632
|
+
this.loggerService.log("priceConnectionService init");
|
|
633
|
+
listenSignal((event) => {
|
|
634
|
+
const priceSubject = GET_SUBJECT_FN(event.symbol, event.strategyName, event.exchangeName, event.frameName, event.backtest);
|
|
635
|
+
event.currentPrice && priceSubject.next(event.currentPrice);
|
|
636
|
+
});
|
|
637
|
+
});
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
|
|
597
641
|
{
|
|
598
642
|
provide(TYPES.loggerService, () => new LoggerService());
|
|
599
643
|
provide(TYPES.exchangeService, () => new ExchangeService());
|
|
600
644
|
}
|
|
601
645
|
{
|
|
602
646
|
provide(TYPES.symbolConnectionService, () => new SymbolConnectionService());
|
|
647
|
+
provide(TYPES.priceConnectionService, () => new PriceConnectionService());
|
|
603
648
|
}
|
|
604
649
|
{
|
|
605
650
|
provide(TYPES.symbolMetaService, () => new SymbolMetaService());
|
|
@@ -621,6 +666,7 @@ const baseServices = {
|
|
|
621
666
|
};
|
|
622
667
|
const connectionServices = {
|
|
623
668
|
symbolConnectionService: inject(TYPES.symbolConnectionService),
|
|
669
|
+
priceConnectionService: inject(TYPES.priceConnectionService),
|
|
624
670
|
};
|
|
625
671
|
const metaServices = {
|
|
626
672
|
symbolMetaService: inject(TYPES.symbolMetaService),
|
|
@@ -644,11 +690,11 @@ const ioc = {
|
|
|
644
690
|
};
|
|
645
691
|
init();
|
|
646
692
|
|
|
647
|
-
const router$
|
|
693
|
+
const router$6 = Router({
|
|
648
694
|
params: true,
|
|
649
695
|
});
|
|
650
696
|
// ExchangeMockService endpoints
|
|
651
|
-
router$
|
|
697
|
+
router$6.post("/api/v1/mock/candles_signal", async (req, res) => {
|
|
652
698
|
try {
|
|
653
699
|
const request = await micro.json(req);
|
|
654
700
|
const { signalId, interval, requestId, serviceName } = request;
|
|
@@ -676,7 +722,7 @@ router$5.post("/api/v1/mock/candles_signal", async (req, res) => {
|
|
|
676
722
|
});
|
|
677
723
|
}
|
|
678
724
|
});
|
|
679
|
-
router$
|
|
725
|
+
router$6.post("/api/v1/mock/candles_point", async (req, res) => {
|
|
680
726
|
try {
|
|
681
727
|
const request = await micro.json(req);
|
|
682
728
|
const { currentTime, interval, requestId, serviceName, symbol, exchangeName } = request;
|
|
@@ -710,7 +756,7 @@ router$5.post("/api/v1/mock/candles_point", async (req, res) => {
|
|
|
710
756
|
}
|
|
711
757
|
});
|
|
712
758
|
// NotificationMockService endpoints
|
|
713
|
-
router$
|
|
759
|
+
router$6.post("/api/v1/mock/notification_list", async (req, res) => {
|
|
714
760
|
try {
|
|
715
761
|
const request = await micro.json(req);
|
|
716
762
|
const { requestId, serviceName } = request;
|
|
@@ -738,7 +784,7 @@ router$5.post("/api/v1/mock/notification_list", async (req, res) => {
|
|
|
738
784
|
});
|
|
739
785
|
}
|
|
740
786
|
});
|
|
741
|
-
router$
|
|
787
|
+
router$6.post("/api/v1/mock/notification_one/:id", async (req, res) => {
|
|
742
788
|
try {
|
|
743
789
|
const request = await micro.json(req);
|
|
744
790
|
const { requestId, serviceName } = request;
|
|
@@ -767,7 +813,7 @@ router$5.post("/api/v1/mock/notification_one/:id", async (req, res) => {
|
|
|
767
813
|
});
|
|
768
814
|
}
|
|
769
815
|
});
|
|
770
|
-
router$
|
|
816
|
+
router$6.post("/api/v1/mock/notification_filter", async (req, res) => {
|
|
771
817
|
try {
|
|
772
818
|
const request = await micro.json(req);
|
|
773
819
|
const { requestId, serviceName, filterData, limit, offset } = request;
|
|
@@ -796,7 +842,7 @@ router$5.post("/api/v1/mock/notification_filter", async (req, res) => {
|
|
|
796
842
|
}
|
|
797
843
|
});
|
|
798
844
|
// StorageMockService endpoints
|
|
799
|
-
router$
|
|
845
|
+
router$6.post("/api/v1/mock/storage_one/:id", async (req, res) => {
|
|
800
846
|
try {
|
|
801
847
|
const request = await micro.json(req);
|
|
802
848
|
const { requestId, serviceName } = request;
|
|
@@ -825,7 +871,7 @@ router$5.post("/api/v1/mock/storage_one/:id", async (req, res) => {
|
|
|
825
871
|
});
|
|
826
872
|
}
|
|
827
873
|
});
|
|
828
|
-
router$
|
|
874
|
+
router$6.post("/api/v1/mock/storage_list/live", async (req, res) => {
|
|
829
875
|
try {
|
|
830
876
|
const request = await micro.json(req);
|
|
831
877
|
const { requestId, serviceName } = request;
|
|
@@ -853,7 +899,7 @@ router$5.post("/api/v1/mock/storage_list/live", async (req, res) => {
|
|
|
853
899
|
});
|
|
854
900
|
}
|
|
855
901
|
});
|
|
856
|
-
router$
|
|
902
|
+
router$6.post("/api/v1/mock/storage_list/backtest", async (req, res) => {
|
|
857
903
|
try {
|
|
858
904
|
const request = await micro.json(req);
|
|
859
905
|
const { requestId, serviceName } = request;
|
|
@@ -882,11 +928,11 @@ router$5.post("/api/v1/mock/storage_list/backtest", async (req, res) => {
|
|
|
882
928
|
}
|
|
883
929
|
});
|
|
884
930
|
|
|
885
|
-
const router$
|
|
931
|
+
const router$5 = Router({
|
|
886
932
|
params: true,
|
|
887
933
|
});
|
|
888
934
|
// ExchangeViewService endpoints
|
|
889
|
-
router$
|
|
935
|
+
router$5.post("/api/v1/view/candles_signal", async (req, res) => {
|
|
890
936
|
try {
|
|
891
937
|
const request = await micro.json(req);
|
|
892
938
|
const { signalId, interval, requestId, serviceName } = request;
|
|
@@ -914,7 +960,7 @@ router$4.post("/api/v1/view/candles_signal", async (req, res) => {
|
|
|
914
960
|
});
|
|
915
961
|
}
|
|
916
962
|
});
|
|
917
|
-
router$
|
|
963
|
+
router$5.post("/api/v1/view/candles_point", async (req, res) => {
|
|
918
964
|
try {
|
|
919
965
|
const request = await micro.json(req);
|
|
920
966
|
const { currentTime, interval, requestId, serviceName, symbol, exchangeName } = request;
|
|
@@ -948,7 +994,7 @@ router$4.post("/api/v1/view/candles_point", async (req, res) => {
|
|
|
948
994
|
}
|
|
949
995
|
});
|
|
950
996
|
// NotificationViewService endpoints
|
|
951
|
-
router$
|
|
997
|
+
router$5.post("/api/v1/view/notification_list", async (req, res) => {
|
|
952
998
|
try {
|
|
953
999
|
const request = await micro.json(req);
|
|
954
1000
|
const { requestId, serviceName } = request;
|
|
@@ -976,7 +1022,7 @@ router$4.post("/api/v1/view/notification_list", async (req, res) => {
|
|
|
976
1022
|
});
|
|
977
1023
|
}
|
|
978
1024
|
});
|
|
979
|
-
router$
|
|
1025
|
+
router$5.post("/api/v1/view/notification_one/:id", async (req, res) => {
|
|
980
1026
|
try {
|
|
981
1027
|
const request = await micro.json(req);
|
|
982
1028
|
const { requestId, serviceName } = request;
|
|
@@ -1005,7 +1051,7 @@ router$4.post("/api/v1/view/notification_one/:id", async (req, res) => {
|
|
|
1005
1051
|
});
|
|
1006
1052
|
}
|
|
1007
1053
|
});
|
|
1008
|
-
router$
|
|
1054
|
+
router$5.post("/api/v1/view/notification_filter", async (req, res) => {
|
|
1009
1055
|
try {
|
|
1010
1056
|
const request = await micro.json(req);
|
|
1011
1057
|
const { requestId, serviceName, filterData, limit, offset } = request;
|
|
@@ -1034,7 +1080,7 @@ router$4.post("/api/v1/view/notification_filter", async (req, res) => {
|
|
|
1034
1080
|
}
|
|
1035
1081
|
});
|
|
1036
1082
|
// StorageViewService endpoints
|
|
1037
|
-
router$
|
|
1083
|
+
router$5.post("/api/v1/view/storage_one/:id", async (req, res) => {
|
|
1038
1084
|
try {
|
|
1039
1085
|
const request = await micro.json(req);
|
|
1040
1086
|
const { requestId, serviceName } = request;
|
|
@@ -1063,7 +1109,7 @@ router$4.post("/api/v1/view/storage_one/:id", async (req, res) => {
|
|
|
1063
1109
|
});
|
|
1064
1110
|
}
|
|
1065
1111
|
});
|
|
1066
|
-
router$
|
|
1112
|
+
router$5.post("/api/v1/view/storage_list/live", async (req, res) => {
|
|
1067
1113
|
try {
|
|
1068
1114
|
const request = await micro.json(req);
|
|
1069
1115
|
const { requestId, serviceName } = request;
|
|
@@ -1091,7 +1137,7 @@ router$4.post("/api/v1/view/storage_list/live", async (req, res) => {
|
|
|
1091
1137
|
});
|
|
1092
1138
|
}
|
|
1093
1139
|
});
|
|
1094
|
-
router$
|
|
1140
|
+
router$5.post("/api/v1/view/storage_list/backtest", async (req, res) => {
|
|
1095
1141
|
try {
|
|
1096
1142
|
const request = await micro.json(req);
|
|
1097
1143
|
const { requestId, serviceName } = request;
|
|
@@ -1127,7 +1173,7 @@ function getModulesPath() {
|
|
|
1127
1173
|
return join(basePath, "../../../");
|
|
1128
1174
|
}
|
|
1129
1175
|
|
|
1130
|
-
const router$
|
|
1176
|
+
const router$4 = Router({
|
|
1131
1177
|
params: true,
|
|
1132
1178
|
});
|
|
1133
1179
|
// getModulesPath
|
|
@@ -1144,7 +1190,7 @@ const ASSET_32 = CC_ENABLE_MOCK
|
|
|
1144
1190
|
const cache128 = new Map();
|
|
1145
1191
|
const cache32 = new Map();
|
|
1146
1192
|
const cacheSvg = new Map();
|
|
1147
|
-
router$
|
|
1193
|
+
router$4.get("/icon/128/:filename", async (req, res) => {
|
|
1148
1194
|
const filename = req.params.filename;
|
|
1149
1195
|
// Check cache first
|
|
1150
1196
|
if (cache128.has(filename)) {
|
|
@@ -1160,7 +1206,7 @@ router$3.get("/icon/128/:filename", async (req, res) => {
|
|
|
1160
1206
|
}
|
|
1161
1207
|
return await micro.send(res, 404, "File not found (128)");
|
|
1162
1208
|
});
|
|
1163
|
-
router$
|
|
1209
|
+
router$4.get("/icon/32/:filename", async (req, res) => {
|
|
1164
1210
|
const filename = req.params.filename;
|
|
1165
1211
|
// Check cache first
|
|
1166
1212
|
if (cache32.has(filename)) {
|
|
@@ -1176,7 +1222,7 @@ router$3.get("/icon/32/:filename", async (req, res) => {
|
|
|
1176
1222
|
}
|
|
1177
1223
|
return await micro.send(res, 404, "File not found (32)");
|
|
1178
1224
|
});
|
|
1179
|
-
router$
|
|
1225
|
+
router$4.get("/icon/svg/:filename", async (req, res) => {
|
|
1180
1226
|
const filename = req.params.filename;
|
|
1181
1227
|
// Check cache first
|
|
1182
1228
|
if (cacheSvg.has(filename)) {
|
|
@@ -1192,7 +1238,7 @@ router$3.get("/icon/svg/:filename", async (req, res) => {
|
|
|
1192
1238
|
}
|
|
1193
1239
|
return await micro.send(res, 404, "File not found (svg)");
|
|
1194
1240
|
});
|
|
1195
|
-
router$
|
|
1241
|
+
router$4.get("/icon/:filename", async (req, res) => {
|
|
1196
1242
|
const filename = req.params.filename;
|
|
1197
1243
|
// Check cache first
|
|
1198
1244
|
if (cache32.has(filename)) {
|
|
@@ -1209,10 +1255,10 @@ router$3.get("/icon/:filename", async (req, res) => {
|
|
|
1209
1255
|
return await micro.send(res, 404, "File not found (root)");
|
|
1210
1256
|
});
|
|
1211
1257
|
|
|
1212
|
-
const router$
|
|
1258
|
+
const router$3 = Router({
|
|
1213
1259
|
params: true,
|
|
1214
1260
|
});
|
|
1215
|
-
router$
|
|
1261
|
+
router$3.post("/api/v1/dict/symbol/list", async (req, res) => {
|
|
1216
1262
|
try {
|
|
1217
1263
|
const request = await micro.json(req);
|
|
1218
1264
|
const { requestId, serviceName } = request;
|
|
@@ -1240,7 +1286,7 @@ router$2.post("/api/v1/dict/symbol/list", async (req, res) => {
|
|
|
1240
1286
|
});
|
|
1241
1287
|
}
|
|
1242
1288
|
});
|
|
1243
|
-
router$
|
|
1289
|
+
router$3.post("/api/v1/dict/symbol/map", async (req, res) => {
|
|
1244
1290
|
try {
|
|
1245
1291
|
const request = await micro.json(req);
|
|
1246
1292
|
const { requestId, serviceName } = request;
|
|
@@ -1268,7 +1314,7 @@ router$2.post("/api/v1/dict/symbol/map", async (req, res) => {
|
|
|
1268
1314
|
});
|
|
1269
1315
|
}
|
|
1270
1316
|
});
|
|
1271
|
-
router$
|
|
1317
|
+
router$3.post("/api/v1/dict/symbol/one", async (req, res) => {
|
|
1272
1318
|
try {
|
|
1273
1319
|
const request = await micro.json(req);
|
|
1274
1320
|
const { requestId, serviceName, id } = request;
|
|
@@ -1297,6 +1343,38 @@ router$2.post("/api/v1/dict/symbol/one", async (req, res) => {
|
|
|
1297
1343
|
}
|
|
1298
1344
|
});
|
|
1299
1345
|
|
|
1346
|
+
const router$2 = Router({
|
|
1347
|
+
params: true,
|
|
1348
|
+
});
|
|
1349
|
+
router$2.post("/api/v1/global/signal_pending_price", async (req, res) => {
|
|
1350
|
+
try {
|
|
1351
|
+
const request = await micro.json(req);
|
|
1352
|
+
const { symbol, strategyName, exchangeName, frameName, backtest, requestId, serviceName } = request;
|
|
1353
|
+
const data = await ioc.priceConnectionService.getSignalPendingPrice(symbol, strategyName, exchangeName, frameName, backtest);
|
|
1354
|
+
const result = {
|
|
1355
|
+
data,
|
|
1356
|
+
status: "ok",
|
|
1357
|
+
error: "",
|
|
1358
|
+
requestId,
|
|
1359
|
+
serviceName,
|
|
1360
|
+
};
|
|
1361
|
+
ioc.loggerService.log("/api/v1/global/signal_pending_price ok", {
|
|
1362
|
+
request,
|
|
1363
|
+
result: omit(result, "data"),
|
|
1364
|
+
});
|
|
1365
|
+
return await micro.send(res, 200, result);
|
|
1366
|
+
}
|
|
1367
|
+
catch (error) {
|
|
1368
|
+
ioc.loggerService.log("/api/v1/global/signal_pending_price error", {
|
|
1369
|
+
error: errorData(error),
|
|
1370
|
+
});
|
|
1371
|
+
return await micro.send(res, 200, {
|
|
1372
|
+
status: "error",
|
|
1373
|
+
error: getErrorMessage(error),
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1300
1378
|
const require = createRequire(import.meta.url);
|
|
1301
1379
|
function getPublicPath() {
|
|
1302
1380
|
const modulePath = require.resolve('@backtest-kit/ui');
|
|
@@ -1308,18 +1386,21 @@ const router = Router({
|
|
|
1308
1386
|
params: true,
|
|
1309
1387
|
});
|
|
1310
1388
|
router.all("/api/v1/health/*", (req, res) => {
|
|
1311
|
-
return router$
|
|
1389
|
+
return router$7(req, res, finalhandler(req, res));
|
|
1312
1390
|
});
|
|
1313
1391
|
router.all("/api/v1/mock/*", (req, res) => {
|
|
1314
|
-
return router$
|
|
1392
|
+
return router$6(req, res, finalhandler(req, res));
|
|
1315
1393
|
});
|
|
1316
1394
|
router.all("/api/v1/view/*", (req, res) => {
|
|
1317
|
-
return router$
|
|
1395
|
+
return router$5(req, res, finalhandler(req, res));
|
|
1318
1396
|
});
|
|
1319
1397
|
router.all("/icon/*", (req, res) => {
|
|
1320
|
-
return router$
|
|
1398
|
+
return router$4(req, res, finalhandler(req, res));
|
|
1321
1399
|
});
|
|
1322
1400
|
router.all("/api/v1/dict/*", (req, res) => {
|
|
1401
|
+
return router$3(req, res, finalhandler(req, res));
|
|
1402
|
+
});
|
|
1403
|
+
router.all("/api/v1/global/*", (req, res) => {
|
|
1323
1404
|
return router$2(req, res, finalhandler(req, res));
|
|
1324
1405
|
});
|
|
1325
1406
|
router.get("/*", (req, res) => serveHandler(req, res, {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a7 as e,a8 as t,w as a,a9 as s,f as i,aa as r,ab as n,ac as o,ad as d,ae as c,af as l,ag as u,ah as m,c as h,i as p,B as b,J as x}from"./index-DawE4H64.js";const g=e(),f=["className","component","disableGutters","fixed","maxWidth","classes"],y=c(),k=g("div",{name:"MuiContainer",slot:"Root",overridesResolver:(e,t)=>{const{ownerState:a}=e;return[t.root,t[`maxWidth${n(String(a.maxWidth))}`],a.fixed&&t.fixed,a.disableGutters&&t.disableGutters]}}),W=e=>o({props:e,name:"MuiContainer",defaultTheme:y});const v=function(e={}){const{createStyledComponent:o=k,useThemeProps:c=W,componentName:u="MuiContainer"}=e,m=o(({theme:e,ownerState:a})=>t({width:"100%",marginLeft:"auto",boxSizing:"border-box",marginRight:"auto",display:"block"},!a.disableGutters&&{paddingLeft:e.spacing(2),paddingRight:e.spacing(2),[e.breakpoints.up("sm")]:{paddingLeft:e.spacing(3),paddingRight:e.spacing(3)}}),({theme:e,ownerState:t})=>t.fixed&&Object.keys(e.breakpoints.values).reduce((t,a)=>{const s=a,i=e.breakpoints.values[s];return 0!==i&&(t[e.breakpoints.up(s)]={maxWidth:`${i}${e.breakpoints.unit}`}),t},{}),({theme:e,ownerState:a})=>t({},"xs"===a.maxWidth&&{[e.breakpoints.up("xs")]:{maxWidth:Math.max(e.breakpoints.values.xs,444)}},a.maxWidth&&"xs"!==a.maxWidth&&{[e.breakpoints.up(a.maxWidth)]:{maxWidth:`${e.breakpoints.values[a.maxWidth]}${e.breakpoints.unit}`}}));return a.forwardRef(function(e,a){const o=c(e),{className:h,component:p="div",disableGutters:b=!1,fixed:x=!1,maxWidth:g="lg"}=o,y=s(o,f),k=t({},o,{component:p,disableGutters:b,fixed:x,maxWidth:g}),W=((e,t)=>{const{classes:a,fixed:s,disableGutters:i,maxWidth:r}=e,o={root:["root",r&&`maxWidth${n(String(r))}`,s&&"fixed",i&&"disableGutters"]};return d(o,e=>l(t,e),a)})(k,u);return i(m,t({as:p,ownerState:k,className:r(W.root,h),ref:a},y))})}({createStyledComponent:m("div",{name:"MuiContainer",slot:"Root",overridesResolver:(e,t)=>{const{ownerState:a}=e;return[t.root,t[`maxWidth${n(String(a.maxWidth))}`],a.fixed&&t.fixed,a.disableGutters&&t.disableGutters]}}),useThemeProps:e=>u({props:e,name:"MuiContainer"})}),w=h(i("path",{d:"M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"}),"Refresh"),R=({className:e,symbol:t,style:a,sx:s})=>i(x,{children:async()=>{try{const r=(await p.symbolGlobalService.getSymbolMap())[t],n=null==r?void 0:r.icon,o=(null==r?void 0:r.color)||"#ccc";return i(b,{className:e,sx:{position:"relative",width:24,height:24,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",background:n?"transparent":o,...s},style:a,children:n?i("img",{loading:"lazy",crossOrigin:"anonymous",src:n,alt:t,style:{width:"100%",height:"100%",borderRadius:"50%",objectFit:"contain"},onError:e=>{const t=e.target,a=t.parentElement;a&&(a.style.background=o,t.style.display="none")}}):i(b,{sx:{width:"60%",height:"60%",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.2)"}})})}catch(r){return i(b,{className:e,sx:{position:"relative",width:24,height:24,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",background:"#ccc",...s},style:a,children:i(b,{sx:{width:"60%",height:"60%",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.2)"}})})}}});export{v as C,R as I,w as R};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as e,f as a,a as n,Z as t,q as o,I as i,D as s,b as r,k as l,i as c,z as d,X as p,R as h,J as b,L as u,d as m,e as g,B as y,T as v,v as x,g as f,l as k,h as w,j as S,m as L,n as R,o as F,p as D,r as P,F as W,S as $,x as j,s as C}from"./index-DawE4H64.js";import{R as T,I as z,C as A}from"./IconPhoto-CC-I1xI7.js";const B=e(a("path",{d:"M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z"}),"Dashboard"),I=new n,M=[{type:t.Link,action:"back-action",label:"Main"},{type:t.Link,action:"back-action",label:"Dashboard"}],N=[{action:"dashboard-action",label:"Dashboard",icon:()=>a(i,{icon:B,color:"#4caf50"})},{divider:!0},{action:"download-action",label:"Download",icon:()=>a(i,{icon:s,color:"#4caf50"})},{divider:!0},{action:"update-now",label:"Refresh",icon:()=>a(i,{icon:T,color:"#4caf50"})}],O=()=>a(o,{items:M,actions:N,onAction:I.next});const V=({data:{type:e},setLoading:n})=>{const{elementRef:t,size:o}=r({closest:".MuiContainer-root",compute:e=>(e.height-=150,e)}),[i,{loading:s,execute:$}]=l(async()=>"live"===e?await c.storageViewService.listSignalLive():await c.storageViewService.listSignalBacktest(),{onLoadStart:()=>n(!0),onLoadEnd:()=>n(!1),deps:[e]}),j=d(i),C=d(e);p(()=>I.subscribe(e=>{if("update-now"===e&&$(),"download-action"===e){const e=new Blob([JSON.stringify(j.current,null,2)],{type:"application/json"}),a=URL.createObjectURL(e);c.layoutService.downloadFile(a,`signals_${C.current}_${Date.now()}.json`)}"dashboard-action"===e&&c.routerService.push(`/dashboard/${C.current}`)}));const T=h.useMemo(()=>i?i.reduce((e,a)=>(e[a.symbol]||(e[a.symbol]=[]),e[a.symbol].push(a),e),{}):{},[i]),A=e=>{const n=T[e]||[];return n.length?a(W,{children:n.map((n,t)=>{return a(L,{sx:{background:e=>t%2==1?F(e.palette.getContrastText(e.palette.background.paper),.02):void 0},onClick:()=>c.layoutService.pickSignal(n.id),children:[a(m,{primary:a(y,{sx:{display:"flex",gap:2,flexWrap:"wrap",alignItems:"center"},children:[a(v,{variant:"body2",component:"span",sx:{fontWeight:"bold",px:1,py:.5,borderRadius:1,background:"long"===n.position?"#1976D2":"#F57C00",color:"white"},children:"long"===n.position?"LONG":"SHORT"}),a(v,{variant:"body2",component:"span",sx:{fontWeight:"medium"},children:[a(y,{component:"span",sx:{color:"text.secondary",mr:.5},children:"Entry:"}),R(n.priceOpen),"$"]}),a(v,{variant:"body2",component:"span",sx:{fontWeight:"medium",color:"success.main"},children:[a(y,{component:"span",sx:{color:"text.secondary",mr:.5},children:"TP:"}),R(n.priceTakeProfit),"$"]}),a(v,{variant:"body2",component:"span",sx:{fontWeight:"medium",color:"error.main"},children:[a(y,{component:"span",sx:{color:"text.secondary",mr:.5},children:"SL:"}),R(n.priceStopLoss),"$"]}),"pnl"in n&&a(v,{variant:"body2",component:"span",sx:{fontWeight:"bold",px:1,py:.5,borderRadius:1,background:n.pnl.pnlPercentage>=0?F("#4caf50",.15):F("#f44336",.15),color:n.pnl.pnlPercentage>=0?"#2e7d32":"#c62828"},children:["PNL: ",n.pnl.pnlPercentage>=0?"+":"",n.pnl.pnlPercentage.toFixed(2),"%"]}),a(v,{variant:"caption",component:"span",sx:{px:1,py:.25,borderRadius:.5,background:"opened"===n.status?F("#4caf50",.2):"scheduled"===n.status?F("#ff9800",.2):"closed"===n.status?F("#9e9e9e",.2):F("#f44336",.2),color:"opened"===n.status?"#2e7d32":"scheduled"===n.status?"#e65100":"closed"===n.status?"#616161":"#c62828"},children:n.status})]}),secondary:a(v,{pt:.5,variant:"subtitle2",sx:{opacity:.5},children:(o=n.createdAt||n.pendingAt,new Date(o).toLocaleString([],{year:"numeric",month:"numeric",day:"numeric",hourCycle:"h24",hour:"2-digit",minute:"2-digit",second:"2-digit"}))})}),a(D,{disableRipple:!0,children:a(P,{})})]},`item-${e}-${n.id}`);var o})}):a(u,{children:a(m,{sx:{"& .MuiTypography-body2":{maxWidth:"435px"}},primary:"No signals",secondary:"Signals will be displayed here after they appear"})})};return s?null:a(w,{ref:t,sx:{width:"100%",maxHeight:o.height,overflowX:"hidden",overflowY:"auto",scrollbarWidth:"thin",bgcolor:"background.paper",position:"relative","& ul":{padding:0}},subheader:a("li",{}),children:a(b,{deps:[T],children:async()=>{const n=Object.keys(T),t=await c.symbolGlobalService.getSymbolMap();return n.length?n.map(e=>{var n,o,i;const s=null==(n=t[e])?void 0:n.color,r=(null==(o=T[e])?void 0:o.length)||0;return a("li",{children:a("ul",{children:[a(g,{sx:{background:(l=s,S(l,"#000000")>S(l,"#FFFFFF")?f(s,.1):k(s,.1)),color:"white !important",zIndex:9,display:"flex",alignItems:"center",justifyContent:"space-between"},children:[a(y,{sx:{position:"relative",paddingRight:"8px"},children:a(z,{symbol:e})}),(null==(i=t[e])?void 0:i.displayName)||e,a(y,{flex:1}),a(v,{variant:"body2",sx:{fontWeight:"medium"},children:x(r,{one:"Signal",two:"Signals",many:"Signals"})})]}),a(y,{sx:{marginTop:"16px",marginBottom:"16px"},children:A(e)})]})},`section-${e}`);var l}):a(u,{children:a(m,{primary:"No signals yet",secondary:"live"===e?"Live signals will be displayed here":"Backtest signals will be displayed here"})})}})})},H=()=>a($,{children:"\n body {\n background-color: #ddd !important;\n }\n "}),E=C(),G=(e,a)=>e.some(e=>e.includes(a)),J=[{id:"backtest",element:V,isActive:e=>G(["/backtest"],e)},{id:"live",element:V,isActive:e=>G(["/live"],e)}],U=[{id:"backtest",label:"Backtest"},{id:"live",label:"Live"}],X=({symbol:e})=>{p(()=>E.replace("/backtest"));return a(A,{children:[a(j,{withScroll:!0,sx:{height:"calc(100vh - 105px)"},BeforePaper:O,onLoadStart:()=>c.layoutService.setAppbarLoader(!0),onLoadEnd:()=>c.layoutService.setAppbarLoader(!1),routes:J,tabs:U,history:E,initialData:()=>({backtest:{type:"backtest"},live:{type:"live"}}),payload:()=>({symbol:e}),onTabChange:(e,a)=>{"backtest"===e&&a.replace("/backtest"),"live"===e&&a.replace("/live")}}),a(H,{})]})};export{X as MainPage,X as default};
|