@tradejs/app 1.0.9 → 1.0.11

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 (125) hide show
  1. package/README.md +16 -3
  2. package/bin/tradejs-app.mjs +146 -2
  3. package/next.config.mjs +0 -14
  4. package/package.json +35 -19
  5. package/src/app/actions/backtest.ts +54 -0
  6. package/src/app/actions/kline.ts +10 -5
  7. package/src/app/actions/scanner.ts +8 -3
  8. package/src/app/actions/strategies.ts +39 -0
  9. package/src/app/api/ai/route.ts +5 -4
  10. package/src/app/api/auth/[...nextauth]/route.ts +1 -1
  11. package/src/app/api/backtest/configs/route.ts +25 -0
  12. package/src/app/api/backtest/files/route.ts +5 -2
  13. package/src/app/api/backtest/order-log/[strategy]/[name]/route.ts +26 -2
  14. package/src/app/api/backtest/result/[strategy]/[name]/route.ts +27 -2
  15. package/src/app/api/backtest/runs/[jobId]/route.ts +124 -0
  16. package/src/app/api/backtest/runs/route.ts +45 -0
  17. package/src/app/api/backtest/test/[strategy]/[name]/route.ts +19 -2
  18. package/src/app/api/derivatives/summary/route.ts +8 -1
  19. package/src/app/api/install/route.ts +51 -0
  20. package/src/app/api/kline/[provider]/[universe]/[symbol]/[interval]/route.ts +1 -0
  21. package/src/app/api/kline/{[provider]/[symbol]/[interval]/route.ts → handler.ts} +61 -39
  22. package/src/app/api/scanner/[provider]/[universe]/route.ts +1 -0
  23. package/src/app/api/scanner/[provider]/route.ts +30 -12
  24. package/src/app/api/scanner/route.ts +3 -3
  25. package/src/app/api/signal/[symbol]/[signalId]/route.ts +1 -1
  26. package/src/app/api/strategies/ai/[cardId]/route.ts +22 -0
  27. package/src/app/api/strategies/ai/route.ts +139 -0
  28. package/src/app/api/strategies/replay/[cardId]/route.ts +18 -0
  29. package/src/app/api/strategies/replay/route.ts +44 -0
  30. package/src/app/api/strategies/runtime/route.ts +831 -0
  31. package/src/app/api/user/runtime-deployments/[deploymentId]/route.ts +25 -0
  32. package/src/app/api/user/runtime-deployments/route.ts +94 -0
  33. package/src/app/api/user/runtime-strategy-configs/route.ts +241 -0
  34. package/src/app/api/user/settings/route.ts +18 -1
  35. package/src/app/api/user/trading-accounts/[accountId]/route.ts +35 -0
  36. package/src/app/api/user/trading-accounts/route.ts +134 -0
  37. package/src/app/auth.ts +1 -19
  38. package/src/app/components/Backtest/CompareList/index.tsx +1 -1
  39. package/src/app/components/Backtest/ResultsPageClient.tsx +376 -0
  40. package/src/app/components/Backtest/TestCard/ActionsMenu/index.tsx +123 -0
  41. package/src/app/components/Backtest/TestCard/Chart/index.tsx +1 -1
  42. package/src/app/components/Backtest/TestCard/CompareButton/index.tsx +1 -1
  43. package/src/app/components/Backtest/TestCard/ConfigDrawer/index.tsx +28 -12
  44. package/src/app/components/Backtest/TestCard/DeleteButton/index.tsx +33 -17
  45. package/src/app/components/Backtest/TestCard/FavoriteIndicator/index.tsx +2 -2
  46. package/src/app/components/Backtest/TestCard/OpenDashboardButton/index.tsx +10 -1
  47. package/src/app/components/Backtest/TestCard/OrdersDrawer/index.tsx +128 -0
  48. package/src/app/components/Backtest/TestCard/Root/index.tsx +18 -4
  49. package/src/app/components/Backtest/TestCard/Stat/index.tsx +2 -0
  50. package/src/app/components/Backtest/TestCard/StatDrawer/index.tsx +66 -0
  51. package/src/app/components/Backtest/TestCard/index.ts +6 -2
  52. package/src/app/components/Backtest/TestList/index.tsx +4 -9
  53. package/src/app/components/Dashboard/AiDrawer/index.tsx +1 -1
  54. package/src/app/components/Dashboard/KlineChart/hooks/useBacktest.ts +1 -1
  55. package/src/app/components/Dashboard/KlineChart/hooks/useBbIndicator.ts +10 -5
  56. package/src/app/components/Dashboard/KlineChart/hooks/useBtcCorrelation.ts +1 -1
  57. package/src/app/components/Dashboard/KlineChart/hooks/useBtcIndicator.ts +4 -1
  58. package/src/app/components/Dashboard/KlineChart/hooks/useEmaIndicator.ts +3 -1
  59. package/src/app/components/Dashboard/KlineChart/hooks/usePluginIndicators.ts +1 -1
  60. package/src/app/components/Dashboard/KlineChart/hooks/useSetup.ts +1 -1
  61. package/src/app/components/Dashboard/KlineChart/hooks/useSignal.ts +1 -1
  62. package/src/app/components/Dashboard/KlineChart/hooks/useSpreadIndicator.ts +1 -1
  63. package/src/app/components/Dashboard/KlineChart/hooks/useTrendLine.ts +1 -1
  64. package/src/app/components/Dashboard/KlineChart/hooks/useWmaIndicator.ts +3 -1
  65. package/src/app/components/Dashboard/KlineChart/index.tsx +21 -7
  66. package/src/app/components/Dashboard/MainChart/index.tsx +3 -22
  67. package/src/app/components/Shared/AppShell.tsx +2 -2
  68. package/src/app/components/Shared/BulkSelection/index.tsx +140 -0
  69. package/src/app/components/Shared/BulkSelection/useBulkSelection.ts +97 -0
  70. package/src/app/components/Shared/BulkSelection/utils.ts +126 -0
  71. package/src/app/components/Shared/Filters/Backtest/index.tsx +51 -51
  72. package/src/app/components/Shared/Filters/FavoriteIndicator/index.tsx +5 -3
  73. package/src/app/components/Shared/Filters/Indicators/index.tsx +2 -2
  74. package/src/app/components/Shared/Filters/Interval/index.tsx +1 -1
  75. package/src/app/components/Shared/Filters/Provider/index.tsx +8 -2
  76. package/src/app/components/Shared/Filters/Symbol/index.tsx +4 -3
  77. package/src/app/components/Shared/Filters/Universe/index.tsx +36 -0
  78. package/src/app/components/Shared/Filters/index.ts +2 -0
  79. package/src/app/components/Shared/OrdersDrawer.tsx +629 -0
  80. package/src/app/components/Shared/Sidebar/AccountSettingsDrawer.tsx +55 -28
  81. package/src/app/components/Shared/Sidebar/TradingAccountsPanel.tsx +445 -0
  82. package/src/app/components/Shared/Sidebar/index.tsx +17 -3
  83. package/src/app/components/Strategies/AdvancedMetricsPanel.tsx +727 -0
  84. package/src/app/components/Strategies/RuntimeStrategyCard.tsx +2204 -0
  85. package/src/app/components/Strategies/RuntimeStrategyCardSkeleton.tsx +40 -0
  86. package/src/app/components/Strategies/RuntimeStrategyChart.tsx +121 -0
  87. package/src/app/components/Strategies/RuntimeStrategyConfigDrawer.tsx +458 -0
  88. package/src/app/components/Strategies/StrategySnapshotCard.tsx +2890 -0
  89. package/src/app/components/Strategies/StrategySnapshotChart.tsx +94 -0
  90. package/src/app/components/Strategies/StrategySnapshotList.tsx +82 -0
  91. package/src/app/components/UI/Segment/index.tsx +8 -1
  92. package/src/app/components/UI/Select/index.tsx +24 -13
  93. package/src/app/components/UI/SelectWithSearch/index.tsx +46 -5
  94. package/src/app/layout.tsx +1 -1
  95. package/src/app/lib/backtestJobs.ts +925 -0
  96. package/src/app/lib/cardPageLayout.ts +1 -0
  97. package/src/app/lib/connectorCreator.ts +28 -0
  98. package/src/app/lib/currentUser.ts +1 -1
  99. package/src/app/lib/errorMessage.ts +34 -0
  100. package/src/app/lib/installation.ts +83 -0
  101. package/src/app/lib/marketDefaults.ts +12 -0
  102. package/src/app/lib/marketRoutes.ts +58 -0
  103. package/src/app/lib/runtimeStrategies.ts +1376 -0
  104. package/src/app/lib/runtimeStrategyConfigForm.ts +86 -0
  105. package/src/app/provider.tsx +1 -1
  106. package/src/app/routes/backtest/page.tsx +1100 -302
  107. package/src/app/routes/dashboard/{[provider]/[symbol]/[interval]/page.tsx → Dashboard.tsx} +76 -35
  108. package/src/app/routes/dashboard/[provider]/[universe]/[symbol]/[interval]/page.tsx +1 -0
  109. package/src/app/routes/dashboard/page.tsx +15 -3
  110. package/src/app/routes/derivatives/page.tsx +1222 -165
  111. package/src/app/routes/install/page.tsx +175 -0
  112. package/src/app/routes/signin/page.tsx +7 -0
  113. package/src/app/routes/strategies/StrategiesPageClient.tsx +593 -0
  114. package/src/app/routes/strategies/[mode]/page.tsx +20 -0
  115. package/src/app/routes/strategies/page.tsx +7 -0
  116. package/src/app/store/ai.ts +1 -1
  117. package/src/app/store/data.ts +73 -17
  118. package/src/app/store/filters.ts +1 -0
  119. package/src/app/store/marketKlineStream.ts +87 -0
  120. package/src/app/store/tests.ts +83 -45
  121. package/src/app/store/tickers.ts +59 -22
  122. package/src/proxy.ts +4 -0
  123. package/tsconfig.json +17 -12
  124. package/src/app/components/Backtest/TestCard/OpenReportButton/index.tsx +0 -24
  125. package/src/app/routes/backtest/[test]/page.tsx +0 -33
@@ -2,22 +2,33 @@
2
2
 
3
3
  import { useCallback, useEffect } from 'react';
4
4
  import { useSearchParams } from 'next/navigation';
5
- import { Box, Flex, ClientOnly } from '@chakra-ui/react';
6
- import { useFilters, useTickers, useTestList } from '@store';
7
- import { Filters } from '@shared/Filters';
8
- import { MainChart } from '@app/components/Dashboard/MainChart';
9
- import { Interval, OnChangeFilters, Provider } from '@tradejs/types';
5
+ import Link from 'next/link';
6
+ import { Box, Button, Flex, ClientOnly } from '@chakra-ui/react';
7
+ import { useFilters, useTickers, useTestList } from '#store';
8
+ import { Filters } from '#shared/Filters';
9
+ import { MainChart } from '#app/components/Dashboard/MainChart';
10
+ import {
11
+ Interval,
12
+ MarketUniverse,
13
+ OnChangeFilters,
14
+ Provider,
15
+ } from '@tradejs/types';
16
+ import {
17
+ buildDashboardPath,
18
+ parseDashboardPath as parseMarketDashboardPath,
19
+ } from '#app/lib/marketRoutes';
10
20
 
11
- const Dashboard = () => {
21
+ const DashboardRoute = () => {
12
22
  const searchParams = useSearchParams();
13
23
  const { filters, setFilters } = useFilters();
14
24
  const { tickers, ensureLoaded: ensureTickersLoaded } = useTickers(
15
25
  filters.provider || 'bybit',
26
+ filters.universe ?? 'crypto',
16
27
  { enabled: false },
17
28
  );
18
29
  const { tests, ensureLoaded: ensureBacktestsLoaded } = useTestList({
19
30
  symbol: filters.symbol,
20
- enabled: false,
31
+ enabled: Boolean(filters.backtestId || filters.backtestStrategy),
21
32
  });
22
33
  const hasBacktestId = searchParams.has('backtestId');
23
34
  const hasBacktestStrategy = searchParams.has('backtestStrategy');
@@ -26,18 +37,18 @@ const Dashboard = () => {
26
37
  const isScreenshotMode = searchParams.get('screenshot') === '1';
27
38
 
28
39
  const parseDashboardPath = useCallback(() => {
29
- const parts = window.location.pathname.split('/').filter(Boolean);
30
- return {
31
- provider: (parts[2] || filters.provider || 'bybit') as Provider,
32
- symbol: (parts[3] || filters.symbol) as string,
33
- interval: (parts[4] || filters.interval) as Interval,
34
- };
40
+ return parseMarketDashboardPath(window.location.pathname, {
41
+ provider: (filters.provider || 'bybit') as Provider,
42
+ symbol: filters.symbol,
43
+ interval: filters.interval as Interval,
44
+ });
35
45
  }, [filters.interval, filters.provider, filters.symbol]);
36
46
 
37
47
  useEffect(() => {
38
48
  const parsed = parseDashboardPath();
39
49
  setFilters({
40
50
  provider: parsed.provider,
51
+ universe: parsed.universe,
41
52
  symbol: parsed.symbol,
42
53
  interval: parsed.interval,
43
54
  ...(hasBacktestId ? { backtestId } : {}),
@@ -59,14 +70,17 @@ const Dashboard = () => {
59
70
  ...filters,
60
71
  ...newFilters,
61
72
  provider: (newFilters.provider || parsed.provider) as Provider,
73
+ universe: (newFilters.universe || parsed.universe) as MarketUniverse,
62
74
  symbol: (newFilters.symbol || parsed.symbol) as string,
63
75
  interval: (newFilters.interval || parsed.interval) as Interval,
64
76
  };
65
77
  setFilters(nextFilters);
66
78
  const nextProvider = nextFilters.provider || 'bybit';
79
+ const nextUniverse = nextFilters.universe || 'crypto';
67
80
  const nextSymbol = nextFilters.symbol;
68
81
  const nextInterval = nextFilters.interval;
69
82
  const params = new URLSearchParams(window.location.search);
83
+ params.delete('universe');
70
84
 
71
85
  if (nextFilters.backtestId) {
72
86
  params.set('backtestId', nextFilters.backtestId);
@@ -80,12 +94,18 @@ const Dashboard = () => {
80
94
  params.delete('backtestStrategy');
81
95
  }
82
96
 
83
- const search = params.toString();
84
-
85
97
  window.history.replaceState(
86
98
  null,
87
99
  '',
88
- `/routes/dashboard/${nextProvider}/${nextSymbol}/${nextInterval}${search ? `?${search}` : ''}`,
100
+ buildDashboardPath(
101
+ {
102
+ provider: nextProvider,
103
+ universe: nextUniverse,
104
+ symbol: nextSymbol,
105
+ interval: nextInterval,
106
+ },
107
+ params,
108
+ ),
89
109
  );
90
110
  },
91
111
  [filters, parseDashboardPath, setFilters],
@@ -104,25 +124,46 @@ const Dashboard = () => {
104
124
  alignItems="flex-start"
105
125
  >
106
126
  {!isScreenshotMode && (
107
- <Filters.Root
108
- filters={filters}
109
- tickers={tickers}
110
- backtestFiles={tests}
111
- onChangeFilters={onChangeFilters}
112
- ensureTickersLoaded={ensureTickersLoaded}
113
- ensureBacktestsLoaded={ensureBacktestsLoaded}
127
+ <Box
128
+ w="full"
129
+ display="grid"
130
+ gridTemplateColumns={{ base: '1fr', lg: 'minmax(0, 1fr) auto' }}
131
+ columnGap={4}
132
+ alignItems="start"
114
133
  >
115
- <Flex mb={2} gap={4} alignItems="center" flexDirection="row">
116
- <Filters.SelectProvider />
117
- <Filters.SelectSymbol />
118
- <Filters.FavoriteIndicator />
119
- <Filters.SelectInterval />
120
- <Filters.SelectIndicator />
121
- </Flex>
122
- <Flex mb={4} gap={4} flexDirection="row">
123
- <Filters.SelectBacktest />
124
- </Flex>
125
- </Filters.Root>
134
+ <Box minW={0}>
135
+ <Filters.Root
136
+ filters={filters}
137
+ tickers={tickers}
138
+ backtestFiles={tests}
139
+ onChangeFilters={onChangeFilters}
140
+ ensureTickersLoaded={ensureTickersLoaded}
141
+ ensureBacktestsLoaded={ensureBacktestsLoaded}
142
+ >
143
+ <Flex mb={2} gap={4} alignItems="center" flexDirection="row">
144
+ <Filters.SelectProvider />
145
+ {Filters.SelectUniverse ? <Filters.SelectUniverse /> : null}
146
+ <Filters.SelectSymbol />
147
+ <Filters.FavoriteIndicator />
148
+ <Filters.SelectInterval />
149
+ <Filters.SelectIndicator />
150
+ </Flex>
151
+ <Flex mb={4} gap={4} flexDirection="row">
152
+ <Filters.SelectBacktest />
153
+ </Flex>
154
+ </Filters.Root>
155
+ </Box>
156
+ <Button
157
+ asChild
158
+ bg="#20c5bd"
159
+ color="gray.950"
160
+ _hover={{ bg: '#42d8d0' }}
161
+ justifySelf={{ base: 'start', lg: 'end' }}
162
+ mb={4}
163
+ >
164
+ <Link href="/routes/backtest">Create backtest</Link>
165
+ </Button>
166
+ </Box>
126
167
  )}
127
168
  <Box position="relative" flex="1" w="full">
128
169
  <MainChart screenshotMode={isScreenshotMode} />
@@ -132,4 +173,4 @@ const Dashboard = () => {
132
173
  );
133
174
  };
134
175
 
135
- export default Dashboard;
176
+ export default DashboardRoute;
@@ -0,0 +1 @@
1
+ export { default } from '../../../../Dashboard';
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { useEffect } from 'react';
4
4
  import { useRouter } from 'next/navigation';
5
- import { useFilters } from '@store';
5
+ import { useFilters } from '#store';
6
+ import { buildDashboardPath } from '#app/lib/marketRoutes';
6
7
 
7
8
  const DashboardIndex = () => {
8
9
  const { filters } = useFilters();
@@ -10,9 +11,20 @@ const DashboardIndex = () => {
10
11
 
11
12
  useEffect(() => {
12
13
  router.replace(
13
- `/routes/dashboard/${filters.provider || 'bybit'}/${filters.symbol}/${filters.interval}`,
14
+ buildDashboardPath({
15
+ provider: filters.provider || 'bybit',
16
+ universe: filters.universe || 'crypto',
17
+ symbol: filters.symbol,
18
+ interval: filters.interval,
19
+ }),
14
20
  );
15
- }, [filters.interval, filters.provider, filters.symbol, router]);
21
+ }, [
22
+ filters.interval,
23
+ filters.provider,
24
+ filters.symbol,
25
+ filters.universe,
26
+ router,
27
+ ]);
16
28
 
17
29
  return null;
18
30
  };