@backtest-kit/ui 5.0.0 → 5.1.1
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 +113 -11
- package/build/index.cjs +1 -28
- package/build/index.mjs +3 -30
- package/build/modules/frontend/build/assets/{Background-hRKtQSrv.js → Background-R1KXHv-Z.js} +1 -1
- package/build/modules/frontend/build/assets/{IconPhoto-DQlKNGdb.js → IconPhoto--GmLas0w.js} +1 -1
- package/build/modules/frontend/build/assets/{KeyboardArrowLeft-wYBUTbRV.js → KeyboardArrowLeft-D-vyob5u.js} +1 -1
- package/build/modules/frontend/build/assets/{Refresh-_yMWRw_x.js → Refresh-DFUXqFNa.js} +1 -1
- package/build/modules/frontend/build/assets/{index-TU650r8r.js → index-BHG0a1C-.js} +1 -1
- package/build/modules/frontend/build/assets/{index-BPJ87g-R.js → index-BVKx1ckY.js} +1 -1
- package/build/modules/frontend/build/assets/{index-3gnGrSPi.js → index-CBPue3Jb.js} +11 -11
- package/build/modules/frontend/build/assets/{index-Kwt_oEAl.js → index-DBCc2lP5.js} +1 -1
- package/build/modules/frontend/build/assets/{index-BUme2lKb.js → index-Dbp3opeR.js} +1 -1
- package/build/modules/frontend/build/assets/{index-BFSXu2bZ.js → index-gLu7a5UG.js} +1 -1
- package/build/modules/frontend/build/assets/{index-Bay1AtTY.js → index-ptRs7meL.js} +1 -1
- package/build/modules/frontend/build/assets/{markdownit-CZc4lN8k.js → markdownit-DKEIqGnR.js} +1 -1
- package/build/modules/frontend/build/index.html +1 -1
- package/package.json +3 -3
- package/types.d.ts +0 -1
package/README.md
CHANGED
|
@@ -67,25 +67,127 @@ setLogger({
|
|
|
67
67
|
|
|
68
68
|
## 📐 Dashboard Revenue Math
|
|
69
69
|
|
|
70
|
-
The **Revenue** metrics on the dashboard are calculated in **dollar terms
|
|
70
|
+
The **Revenue** metrics on the dashboard are calculated in **dollar terms** by summing the `pnlCost` field from all closed signals within each time window.
|
|
71
71
|
|
|
72
72
|
### Dollar PnL formula
|
|
73
73
|
|
|
74
74
|
```
|
|
75
|
-
|
|
75
|
+
revenue[window] = Σ signal.pnl.pnlCost (for all closed signals in that window)
|
|
76
76
|
```
|
|
77
77
|
|
|
78
|
-
|
|
79
|
-
|:--------------:|-------------------:|-------------------------:|
|
|
80
|
-
| 1 | $100 | +$5.00 |
|
|
81
|
-
| 2 | $200 | +$10.00 |
|
|
82
|
-
| 3 | $300 | +$15.00 |
|
|
78
|
+
`pnlCost` is computed by the backend (`toProfitLossDto`) as:
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
80
|
+
```
|
|
81
|
+
pnlCost = (pnlPercentage / 100) × pnlEntries
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
| Field | Source | Description |
|
|
85
|
+
|-------|--------|-------------|
|
|
86
|
+
| `pnl.pnlCost` | `IStorageSignalRow` | Absolute P&L in USD — the only value summed for revenue |
|
|
87
|
+
| `pnl.pnlPercentage` | `IStorageSignalRow` | Percentage P&L (accounts for DCA-weighted entry price, slippage, and fees) |
|
|
88
|
+
| `pnl.pnlEntries` | `IStorageSignalRow` | Total invested capital in USD — sum of all entry costs (`Σ entry.cost`) |
|
|
89
|
+
|
|
90
|
+
**Example** (1 DCA entry at $100, position closed +5%):
|
|
91
|
+
|
|
92
|
+
| DCA entries | `pnlEntries` | `pnlPercentage` | `pnlCost` |
|
|
93
|
+
|:-----------:|-------------:|----------------:|----------:|
|
|
94
|
+
| 1 | $100 | 5 % | +$5.00 |
|
|
95
|
+
| 2 | $200 | 5 % | +$10.00 |
|
|
96
|
+
| 3 | $300 | 5 % | +$15.00 |
|
|
97
|
+
|
|
98
|
+
### Time windows
|
|
99
|
+
|
|
100
|
+
The anchor point depends on execution mode:
|
|
101
|
+
|
|
102
|
+
- **Backtest mode** — latest `updatedAt` across all closed signals (time windows are relative to the end of the run)
|
|
103
|
+
- **Live mode** — `Date.now()` (wall-clock time)
|
|
104
|
+
|
|
105
|
+
| Window | Range |
|
|
106
|
+
|--------|-------|
|
|
107
|
+
| Today | `>= startOf(anchorDay)` |
|
|
108
|
+
| Yesterday | `[anchorDay − 1d, anchorDay)` |
|
|
109
|
+
| 7 days | `>= anchorDay − 7d` |
|
|
110
|
+
| 31 days | `>= anchorDay − 31d` |
|
|
111
|
+
|
|
112
|
+
Revenue and signal count are tracked separately for each window and aggregated across all symbols on the Dashboard.
|
|
113
|
+
|
|
114
|
+
## 📐 Position PNL Math
|
|
115
|
+
|
|
116
|
+
### Effective entry price (DCA-weighted)
|
|
117
|
+
|
|
118
|
+
When multiple DCA entries exist, the effective open price is a **cost-weighted harmonic mean**:
|
|
119
|
+
|
|
120
|
+
```
|
|
121
|
+
effectivePrice = Σcost / Σ(cost / price)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
This is the correct formula for fixed-dollar entries (not simple average), because buying $100 worth at different prices gives different coin quantities.
|
|
125
|
+
|
|
126
|
+
### Partial closes (PP/PL)
|
|
127
|
+
|
|
128
|
+
Each partial stores a `costBasisAtClose` snapshot — the running dollar cost-basis **before** that partial fired. This avoids replaying the full entry history on every call.
|
|
129
|
+
|
|
130
|
+
**Cost-basis replay:**
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
for each partial[i]:
|
|
134
|
+
closedDollar += (percent[i] / 100) × costBasisAtClose[i]
|
|
135
|
+
remainingCostBasis = costBasisAtClose[i] × (1 - percent[i] / 100)
|
|
136
|
+
|
|
137
|
+
# DCA entries added AFTER the last partial are appended:
|
|
138
|
+
remainingCostBasis += Σ entry.cost for entries[lastEntryCount..]
|
|
139
|
+
|
|
140
|
+
totalClosedPercent = closedDollar / totalInvested × 100
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Effective price through partials** is computed iteratively so that a partial sell does not change the entry price of the remaining coins:
|
|
144
|
+
|
|
145
|
+
```
|
|
146
|
+
# partial[0]:
|
|
147
|
+
effPrice = costBasisAtClose[0] / Σ(cost/price for entries[0..cnt[0]])
|
|
148
|
+
|
|
149
|
+
# partial[j]:
|
|
150
|
+
remainingCB = prev.costBasisAtClose × (1 - prev.percent / 100)
|
|
151
|
+
oldCoins = remainingCB / effPrice ← coins still held
|
|
152
|
+
newCoins = Σ(cost/price for DCA entries between j-1 and j)
|
|
153
|
+
effPrice = (remainingCB + newCost) / (oldCoins + newCoins)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### toProfitLossDto — weighted PNL with slippage & fees
|
|
157
|
+
|
|
158
|
+
**Without partials:**
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
priceOpenSlip = effectivePrice × (1 ± slippage)
|
|
162
|
+
priceCloseSlip = priceClose × (1 ∓ slippage)
|
|
163
|
+
|
|
164
|
+
pnlPercentage = (priceCloseSlip - priceOpenSlip) / priceOpenSlip × 100
|
|
165
|
+
fee = CC_PERCENT_FEE × (1 + priceCloseSlip / priceOpenSlip)
|
|
166
|
+
pnlPercentage -= fee
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**With partials — dollar-weighted sum:**
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
weight[i] = (percent[i] / 100 × costBasisAtClose[i]) / totalInvested
|
|
173
|
+
|
|
174
|
+
totalWeightedPnl = Σ weight[i] × pnl[i] # each partial at its own effectivePrice
|
|
175
|
+
+ remainingWeight × pnlRemaining # rest closed at final priceClose
|
|
176
|
+
|
|
177
|
+
fee = CC_PERCENT_FEE # open (once)
|
|
178
|
+
+ Σ CC_PERCENT_FEE × weight[i] × (closeSlip[i] / openSlip[i]) # per partial
|
|
179
|
+
+ CC_PERCENT_FEE × remainingWeight × (closeSlip / openSlip) # final close
|
|
180
|
+
|
|
181
|
+
pnlPercentage = totalWeightedPnl - fee
|
|
182
|
+
pnlCost = pnlPercentage / 100 × totalInvested
|
|
183
|
+
```
|
|
87
184
|
|
|
88
|
-
|
|
185
|
+
| Field | Description |
|
|
186
|
+
|-------|-------------|
|
|
187
|
+
| `totalInvested` | `Σ entry.cost` (or `CC_POSITION_ENTRY_COST` if no `_entry`) |
|
|
188
|
+
| `weight[i]` | Real dollar share of each partial relative to `totalInvested` |
|
|
189
|
+
| `effectivePrice` at partial `i` | Computed via iterative `costBasisAtClose` replay up to `partials[i]` |
|
|
190
|
+
| `priceOpen` in result | `getEffectivePriceOpen(signal)` — DCA-weighted harmonic mean across all entries |
|
|
89
191
|
|
|
90
192
|
## 🖥️ Dashboard Views
|
|
91
193
|
|
package/build/index.cjs
CHANGED
|
@@ -906,22 +906,6 @@ class SymbolMetaService {
|
|
|
906
906
|
}
|
|
907
907
|
}
|
|
908
908
|
|
|
909
|
-
const PRICE_TIMEOUT = 120000;
|
|
910
|
-
const CREATE_KEY_FN = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
911
|
-
const parts = [symbol, strategyName, exchangeName];
|
|
912
|
-
if (frameName)
|
|
913
|
-
parts.push(frameName);
|
|
914
|
-
parts.push(backtest ? "backtest" : "live");
|
|
915
|
-
return parts.join(":");
|
|
916
|
-
};
|
|
917
|
-
const GET_SUBJECT_FN = functoolsKit.memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest), () => new functoolsKit.BehaviorSubject());
|
|
918
|
-
const GET_PRICE_FN = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
919
|
-
const priceSubject = GET_SUBJECT_FN(symbol, strategyName, exchangeName, frameName, backtest);
|
|
920
|
-
if (priceSubject.data) {
|
|
921
|
-
return priceSubject.data;
|
|
922
|
-
}
|
|
923
|
-
return await functoolsKit.waitForNext(priceSubject, (data) => !!data, PRICE_TIMEOUT);
|
|
924
|
-
};
|
|
925
909
|
class PriceConnectionService {
|
|
926
910
|
constructor() {
|
|
927
911
|
this.loggerService = inject(TYPES.loggerService);
|
|
@@ -933,19 +917,8 @@ class PriceConnectionService {
|
|
|
933
917
|
frameName,
|
|
934
918
|
backtest,
|
|
935
919
|
});
|
|
936
|
-
|
|
937
|
-
if (typeof currentPrice === "symbol") {
|
|
938
|
-
throw new Error(`Price for ${CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest)} not received within timeout`);
|
|
939
|
-
}
|
|
940
|
-
return currentPrice;
|
|
920
|
+
return await backtestKit.lib.priceMetaService.getCurrentPrice(symbol, { strategyName, exchangeName, frameName }, backtest);
|
|
941
921
|
};
|
|
942
|
-
this.init = functoolsKit.singleshot(async () => {
|
|
943
|
-
this.loggerService.log("priceConnectionService init");
|
|
944
|
-
backtestKit.listenSignal((event) => {
|
|
945
|
-
const priceSubject = GET_SUBJECT_FN(event.symbol, event.strategyName, event.exchangeName, event.frameName, event.backtest);
|
|
946
|
-
event.currentPrice && priceSubject.next(event.currentPrice);
|
|
947
|
-
});
|
|
948
|
-
});
|
|
949
922
|
}
|
|
950
923
|
}
|
|
951
924
|
|
package/build/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import http from 'http';
|
|
2
|
-
import { isObject, singleshot, pickDocuments, str, memoize,
|
|
2
|
+
import { isObject, singleshot, pickDocuments, str, memoize, 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, Log, Live,
|
|
9
|
+
import { Exchange, Notification, Storage, Log, Live, lib } 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';
|
|
@@ -903,22 +903,6 @@ class SymbolMetaService {
|
|
|
903
903
|
}
|
|
904
904
|
}
|
|
905
905
|
|
|
906
|
-
const PRICE_TIMEOUT = 120000;
|
|
907
|
-
const CREATE_KEY_FN = (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
908
|
-
const parts = [symbol, strategyName, exchangeName];
|
|
909
|
-
if (frameName)
|
|
910
|
-
parts.push(frameName);
|
|
911
|
-
parts.push(backtest ? "backtest" : "live");
|
|
912
|
-
return parts.join(":");
|
|
913
|
-
};
|
|
914
|
-
const GET_SUBJECT_FN = memoize(([symbol, strategyName, exchangeName, frameName, backtest]) => CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest), () => new BehaviorSubject());
|
|
915
|
-
const GET_PRICE_FN = async (symbol, strategyName, exchangeName, frameName, backtest) => {
|
|
916
|
-
const priceSubject = GET_SUBJECT_FN(symbol, strategyName, exchangeName, frameName, backtest);
|
|
917
|
-
if (priceSubject.data) {
|
|
918
|
-
return priceSubject.data;
|
|
919
|
-
}
|
|
920
|
-
return await waitForNext(priceSubject, (data) => !!data, PRICE_TIMEOUT);
|
|
921
|
-
};
|
|
922
906
|
class PriceConnectionService {
|
|
923
907
|
constructor() {
|
|
924
908
|
this.loggerService = inject(TYPES.loggerService);
|
|
@@ -930,19 +914,8 @@ class PriceConnectionService {
|
|
|
930
914
|
frameName,
|
|
931
915
|
backtest,
|
|
932
916
|
});
|
|
933
|
-
|
|
934
|
-
if (typeof currentPrice === "symbol") {
|
|
935
|
-
throw new Error(`Price for ${CREATE_KEY_FN(symbol, strategyName, exchangeName, frameName, backtest)} not received within timeout`);
|
|
936
|
-
}
|
|
937
|
-
return currentPrice;
|
|
917
|
+
return await lib.priceMetaService.getCurrentPrice(symbol, { strategyName, exchangeName, frameName }, backtest);
|
|
938
918
|
};
|
|
939
|
-
this.init = singleshot(async () => {
|
|
940
|
-
this.loggerService.log("priceConnectionService init");
|
|
941
|
-
listenSignal((event) => {
|
|
942
|
-
const priceSubject = GET_SUBJECT_FN(event.symbol, event.strategyName, event.exchangeName, event.frameName, event.backtest);
|
|
943
|
-
event.currentPrice && priceSubject.next(event.currentPrice);
|
|
944
|
-
});
|
|
945
|
-
});
|
|
946
919
|
}
|
|
947
920
|
}
|
|
948
921
|
|
package/build/modules/frontend/build/assets/{Background-hRKtQSrv.js → Background-R1KXHv-Z.js}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{f as n,az as o}from"./index-
|
|
1
|
+
import{f as n,az as o}from"./index-CBPue3Jb.js";const d=()=>n(o,{children:"\n body {\n background-color: #ddd !important;\n }\n "});export{d as B};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{f as e,i as t,B as r,J as s}from"./index-
|
|
1
|
+
import{f as e,i as t,B as r,J as s}from"./index-CBPue3Jb.js";const a=({className:a,symbol:i,style:o,sx:n})=>e(s,{children:async()=>{try{const s=(await t.symbolGlobalService.getSymbolMap())[i],l=null==s?void 0:s.icon,c=(null==s?void 0:s.color)||"#ccc";return e(r,{className:a,sx:{position:"relative",width:24,height:24,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",background:l?"transparent":c,...n},style:o,children:l?e("img",{loading:"lazy",crossOrigin:"anonymous",src:l,alt:i,style:{width:"100%",height:"100%",borderRadius:"50%",objectFit:"contain"},onError:e=>{const t=e.target,r=t.parentElement;r&&(r.style.background=c,t.style.display="none")}}):e(r,{sx:{width:"60%",height:"60%",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.2)"}})})}catch(s){return e(r,{className:a,sx:{position:"relative",width:24,height:24,borderRadius:"50%",display:"flex",alignItems:"center",justifyContent:"center",background:"#ccc",...n},style:o,children:e(r,{sx:{width:"60%",height:"60%",borderRadius:"50%",backgroundColor:"rgba(255, 255, 255, 0.2)"}})})}}});export{a as I};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as o,f as r}from"./index-
|
|
1
|
+
import{c as o,f as r}from"./index-CBPue3Jb.js";const a=o(r("path",{d:"M15.41 16.59 10.83 12l4.58-4.59L14 6l-6 6 6 6 1.41-1.41z"}),"KeyboardArrowLeft");export{a as K};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{aA as e,aB as t,r as a,aC as s,f as i,aD as n,aE as o,aF as r,aG as d,aH as m,aI as u,aJ as p,aK as x,c}from"./index-
|
|
1
|
+
import{aA as e,aB as t,r as a,aC as s,f as i,aD as n,aE as o,aF as r,aG as d,aH as m,aI as u,aJ as p,aK as x,c}from"./index-CBPue3Jb.js";const h=e(),l=["className","component","disableGutters","fixed","maxWidth","classes"],b=m(),f=h("div",{name:"MuiContainer",slot:"Root",overridesResolver:(e,t)=>{const{ownerState:a}=e;return[t.root,t[`maxWidth${o(String(a.maxWidth))}`],a.fixed&&t.fixed,a.disableGutters&&t.disableGutters]}}),g=e=>r({props:e,name:"MuiContainer",defaultTheme:b});const W=function(e={}){const{createStyledComponent:r=f,useThemeProps:m=g,componentName:p="MuiContainer"}=e,x=r(({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 r=m(e),{className:c,component:h="div",disableGutters:b=!1,fixed:f=!1,maxWidth:g="lg"}=r,W=s(r,l),k=t({},r,{component:h,disableGutters:b,fixed:f,maxWidth:g}),S=((e,t)=>{const{classes:a,fixed:s,disableGutters:i,maxWidth:n}=e,r={root:["root",n&&`maxWidth${o(String(n))}`,s&&"fixed",i&&"disableGutters"]};return d(r,e=>u(t,e),a)})(k,p);return i(x,t({as:h,ownerState:k,className:n(S.root,c),ref:a},W))})}({createStyledComponent:x("div",{name:"MuiContainer",slot:"Root",overridesResolver:(e,t)=>{const{ownerState:a}=e;return[t.root,t[`maxWidth${o(String(a.maxWidth))}`],a.fixed&&t.fixed,a.disableGutters&&t.disableGutters]}}),useThemeProps:e=>p({props:e,name:"MuiContainer"})}),k=c(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");export{W as C,k as R};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{c as a,f as e,an as t,B as o,S as r,a8 as n,T as i,G as c,C as s,F as l,a9 as d,P as h,ac as p,ap as u,aq as w,a1 as v,j as b,i as f,a2 as x,z as g,a7 as y,q as m,Z as S,ao as L,D as k,I as z}from"./index-
|
|
1
|
+
import{c as a,f as e,an as t,B as o,S as r,a8 as n,T as i,G as c,C as s,F as l,a9 as d,P as h,ac as p,ap as u,aq as w,a1 as v,j as b,i as f,a2 as x,z as g,a7 as y,q as m,Z as S,ao as L,D as k,I as z}from"./index-CBPue3Jb.js";import{C as H,R as j}from"./Refresh-DFUXqFNa.js";import{K as C}from"./KeyboardArrowLeft-D-vyob5u.js";const A=a(e("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-5 14H7v-2h7v2zm3-4H7v-2h10v2zm0-4H7V7h10v2z"}),"Article"),R=a(e("path",{d:"M20 8h-2.81c-.45-.78-1.07-1.45-1.82-1.96L17 4.41 15.59 3l-2.17 2.17C12.96 5.06 12.49 5 12 5c-.49 0-.96.06-1.41.17L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8zm-6 8h-4v-2h4v2zm0-4h-4v-2h4v2z"}),"BugReport"),M=a(e("path",{d:"M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"}),"Search"),B=a=>{const t={color:"white",fontSize:28};switch(a.type){case"debug":return e(R,{sx:t});case"info":return e(u,{sx:t});case"warn":return e(p,{sx:t});default:return e(A,{sx:t})}},D=t.virtualize(({data:a,sx:t})=>{const p=(a=>{switch(a.type){case"debug":default:return"#9E9E9E";case"info":return"#2196F3";case"warn":return"#FF9800";case"log":return"#4CAF50"}})(a);return e(h,{variant:"outlined",sx:{display:"flex",alignItems:"stretch",justifyContent:"stretch",...t},children:e(o,{sx:{flex:1,position:"relative",overflow:"hidden",height:"100%",width:"100%",borderRadius:"12px"},children:[e(r,{direction:"row",spacing:2,sx:{p:2},children:[e(n,{sx:{width:56,height:56,background:p},children:B(a)}),e(r,{flex:1,spacing:1,children:[e(r,{direction:"row",justifyContent:"space-between",alignItems:"flex-start",children:[e(i,{variant:"h6",sx:{fontWeight:600,wordBreak:"break-all"},children:a.topic}),e(i,{variant:"body2",color:"text.secondary",sx:{whiteSpace:"nowrap",ml:2},children:c(a.createdAt).format("HH:mm DD/MM/YYYY")})]}),e(r,{direction:"row",spacing:1,flexWrap:"wrap",children:e(s,{size:"small",label:a.type.toUpperCase(),sx:{background:p,color:"white",fontWeight:500}})}),a.args.length>0&&e(l,{children:[e(d,{sx:{my:1}}),e(o,{component:"pre",sx:{m:0,fontSize:"0.75rem",whiteSpace:"pre-wrap",wordBreak:"break-all",color:"text.secondary"},children:JSON.stringify(1===a.args.length?a.args[0]:a.args,null,2)})]})]})]}),e(o,{sx:{position:"absolute",top:0,left:0,bottom:0,width:6,zIndex:1,background:p}})]})})}),E=[{action:"download-action",label:"Download",icon:()=>e(z,{icon:k,color:"#4caf50"})},{divider:!0},{action:"update-now",label:"Refresh manually",icon:()=>e(z,{icon:j,color:"#4caf50"})}],F=[{type:S.Link,action:"back-action",label:e(C,{sx:{display:"block"}})},{type:S.Link,action:"back-action",label:"Main"},{type:S.Link,action:"back-action",label:"Logs"},{type:S.Button,icon:M,action:"search-action",label:"Search"}],I=new b,V=()=>{const[a,o]=w(""),{data:r,hasMore:n,loading:i,onSkip:c}=v({handler:async(e,t)=>{const o=await f.logViewService.getList(),r=x(e,t);for(const n of o)if(new RegExp(a.current,"i").test(n.topic)&&r([n]).done)break;return r().rows},onLoadStart:()=>f.layoutService.setAppbarLoader(!0),onLoadEnd:()=>f.layoutService.setAppbarLoader(!1),reloadSubject:I}),s=g(r),{execute:l}=y(async()=>{const a=new Blob([JSON.stringify(s.current,null,2)],{type:"application/json"}),e=URL.createObjectURL(a);f.layoutService.downloadFile(e,`logs_${Date.now()}.json`)},{onLoadStart:()=>f.layoutService.setAppbarLoader(!0),onLoadEnd:()=>f.layoutService.setAppbarLoader(!1)});return e(H,{children:[e(m,{items:F,actions:E,onAction:async a=>{"back-action"===a&&f.routerService.push("/"),"download-action"===a&&l(),"update-now"===a&&(o(""),await I.next()),"search-action"===a&&(async()=>{const a=await f.layoutService.prompt("Search keyword");if(a)return o(a),void I.next();o(""),I.next()})()}}),e(t,{sx:{height:"calc(100vh - 155px)"},withScrollbar:!0,minHeight:72,loading:i,onDataRequest:c,bufferSize:L,hasMore:n,children:r.map(a=>e(D,{data:a,sx:{mb:1}},a.id))})]})};export{V as LogPage,V as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as e,f as a,P as i,B as r,S as n,a8 as t,T as s,G as l,C as o,_ as c,F as p,a9 as d,aa as m,ab as u,ac as b,ad as v,ae as y,af as g,a6 as h,ag as k,ah as $,ai as f,aj as x,ak as S,al as _,am as C,i as P,a1 as w,j as L,a2 as A,q as z,Z as O,an as j,ao as E,I as F}from"./index-3gnGrSPi.js";import{C as T,R}from"./Refresh-_yMWRw_x.js";import{K as B}from"./KeyboardArrowLeft-wYBUTbRV.js";const U=e=>{const i={color:"white",fontSize:28};switch(e.type){case"signal.opened":case"partial_profit.available":case"partial_profit.commit":return a(S,{sx:i});case"signal.closed":case"signal_sync.close":return a(h,{sx:i});case"signal.scheduled":return a(C,{sx:i});case"signal.cancelled":return a(_,{sx:i});case"partial_loss.available":case"partial_loss.commit":case"average_buy.commit":return a(f,{sx:i});case"breakeven.available":case"breakeven.commit":return a(x,{sx:i});case"activate_scheduled.commit":case"signal_sync.open":return a(k,{sx:i});case"trailing_stop.commit":case"trailing_take.commit":return a($,{sx:i});case"risk.rejection":return a(g,{sx:i});case"error.info":case"error.validation":return a(y,{sx:i});case"error.critical":return a(v,{sx:i});default:return a(b,{sx:i})}},D=e=>{switch(e.type){case"signal.opened":return`${c("Opened")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal.closed":return`${c("Closed")} ${e.symbol} (${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%)`;case"signal.scheduled":return`${c("Scheduled")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal.cancelled":return`${c("Cancelled")} ${e.symbol}`;case"partial_profit.available":return`${c("Partial profit")} ${e.level}% ${e.symbol}`;case"partial_profit.commit":return`${c("Profit fixed")} ${e.percentToClose}% ${e.symbol}`;case"partial_loss.available":return`${c("Partial loss")} ${e.level}% ${e.symbol}`;case"partial_loss.commit":return`${c("Loss fixed")} ${e.percentToClose}% ${e.symbol}`;case"breakeven.available":return`${c("Breakeven available")} ${e.symbol}`;case"breakeven.commit":return`${c("Breakeven set")} ${e.symbol}`;case"activate_scheduled.commit":return`${c("Activated")} ${e.position.toUpperCase()} ${e.symbol}`;case"average_buy.commit":return`${c("Average Buy")} ${e.symbol}`;case"trailing_stop.commit":return`${c("Trailing stop")} ${e.symbol}`;case"trailing_take.commit":return`${c("Trailing take")} ${e.symbol}`;case"signal_sync.open":return`${c("Sync Open")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal_sync.close":return`${c("Sync Close")} ${e.symbol} (${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%)`;case"risk.rejection":return`${c("Rejected")} ${e.position.toUpperCase()} ${e.symbol}`;case"error.info":return`${c("Error")}: ${e.message}`;case"error.validation":return`${c("Validation")}: ${e.message}`;case"error.critical":return`${c("Critical")}: ${e.message}`;default:return c("Unknown")}},W=e=>{switch(e.type){case"signal.opened":return c("Signal Opened");case"signal.closed":return c("Signal Closed");case"signal.scheduled":return c("Signal Scheduled");case"signal.cancelled":return c("Signal Cancelled");case"partial_profit.available":return c("Partial Profit Available");case"partial_profit.commit":return c("Partial Profit Commit");case"partial_loss.available":return c("Partial Loss Available");case"partial_loss.commit":return c("Partial Loss Commit");case"breakeven.available":return c("Breakeven Available");case"breakeven.commit":return c("Breakeven Commit");case"activate_scheduled.commit":return c("Activated Scheduled");case"average_buy.commit":return c("Average Buy");case"trailing_stop.commit":return c("Trailing Stop");case"trailing_take.commit":return c("Trailing Take");case"signal_sync.open":return c("Signal Sync Open");case"signal_sync.close":return c("Signal Sync Close");case"risk.rejection":return c("Risk Rejection");case"error.info":return c("Info Error");case"error.validation":return c("Validation Error");case"error.critical":return c("Critical Error");default:return c("Unknown")}},I=e=>"symbol"in e,M=e=>"position"in e,N=e=>"priceOpen"in e&&"priceTakeProfit"in e&&"priceStopLoss"in e,Y=e=>"pnlPercentage"in e,H=e=>"level"in e,V=e=>"percentToClose"in e,q=e=>"currentPrice"in e,K=e=>"duration"in e,G=e=>"closeReason"in e,Z=e=>"cancelReason"in e,J=e=>"priceClose"in e,Q=e=>"percentShift"in e,X=e=>"note"in e&&!!e.note,ee=e=>"message"in e,ae=e=>"rejectionNote"in e,ie=e=>"activePositionCount"in e,re=e=>"effectivePriceOpen"in e,ne=e=>"totalEntries"in e&&e.totalEntries>1,te=e=>"originalPriceOpen"in e&&"priceOpen"in e&&e.originalPriceOpen!==e.priceOpen,se=e=>"totalPartials"in e&&e.totalPartials>0,le=e=>"cost"in e,oe=e=>"pnlPriceOpen"in e&&"pnlPriceClose"in e&&"pnlCost"in e&&"pnlEntries"in e,ce=e.forwardRef(({item:e,className:b,style:v,sx:y},g)=>{const h=(e=>{switch(e.type){case"signal.opened":case"activate_scheduled.commit":case"signal_sync.open":return"#4CAF50";case"signal.closed":case"signal_sync.close":return"#2196F3";case"signal.scheduled":case"average_buy.commit":case"error.info":case"error.validation":return"#FF9800";case"signal.cancelled":default:return"#9E9E9E";case"partial_profit.available":case"partial_profit.commit":return"#8BC34A";case"partial_loss.available":case"partial_loss.commit":return"#FF5722";case"breakeven.available":case"breakeven.commit":return"#00BCD4";case"trailing_stop.commit":case"trailing_take.commit":return"#673AB7";case"risk.rejection":return"#F44336";case"error.critical":return"#D32F2F"}})(e),k=(e=>"timestamp"in e)(e)?e.timestamp:Date.now();return a("div",{className:b,style:v,ref:g,children:a(i,{variant:"outlined",onClick:()=>(e=>{switch(e.type){case"risk.rejection":P.layoutService.pickRisk(e.id);break;case"signal.opened":P.layoutService.pickSignalOpened(e.id);break;case"signal.closed":P.layoutService.pickSignalClosed(e.id);break;case"signal.scheduled":P.layoutService.pickSignalScheduled(e.id);break;case"signal.cancelled":P.layoutService.pickSignalCancelled(e.id);break;case"partial_profit.available":P.layoutService.pickPartialProfitAvailable(e.id);break;case"partial_profit.commit":P.layoutService.pickPartialProfitCommit(e.id);break;case"partial_loss.available":P.layoutService.pickPartialLossAvailable(e.id);break;case"partial_loss.commit":P.layoutService.pickPartialLossCommit(e.id);break;case"breakeven.available":P.layoutService.pickBreakevenAvailable(e.id);break;case"breakeven.commit":P.layoutService.pickBreakevenCommit(e.id);break;case"trailing_stop.commit":P.layoutService.pickTrailingStop(e.id);break;case"trailing_take.commit":P.layoutService.pickTrailingTake(e.id);break;case"activate_scheduled.commit":P.layoutService.pickActivateScheduled(e.id);break;case"average_buy.commit":P.layoutService.pickAverageBuyCommit(e.id);break;case"signal_sync.open":P.layoutService.pickSignalSyncOpen(e.id);break;case"signal_sync.close":P.layoutService.pickSignalSyncClose(e.id)}})(e),sx:{transition:"box-shadow 0.2s ease",cursor:"pointer",display:"flex",alignItems:"stretch",justifyContent:"stretch","&:hover":{boxShadow:4},...y},children:a(r,{sx:{flex:1,position:"relative",overflow:"hidden",height:"100%",width:"100%",borderRadius:"12px"},children:[a(n,{direction:"row",spacing:2,sx:{p:2},children:[a(t,{sx:{width:56,height:56,background:h},children:U(e)}),a(n,{flex:1,spacing:1,children:[a(n,{direction:"row",justifyContent:"space-between",alignItems:"flex-start",children:[a(s,{variant:"h6",sx:{fontWeight:600},children:D(e)}),a(s,{variant:"body2",color:"text.secondary",sx:{whiteSpace:"nowrap",ml:2},children:l(k).format("HH:mm DD/MM/YYYY")})]}),a(n,{direction:"row",spacing:1,flexWrap:"wrap",children:[a(o,{size:"small",label:W(e),sx:{background:h,color:"white",fontWeight:500}}),I(e)&&a(o,{size:"small",label:e.symbol,variant:"outlined"}),M(e)&&a(o,{size:"small",label:e.position.toUpperCase(),variant:"outlined",color:"long"===e.position?"success":"error"}),Y(e)&&a(o,{size:"small",label:`PnL: ${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%`,color:e.pnlPercentage>=0?"success":"error",variant:"outlined"}),H(e)&&a(o,{size:"small",label:`${c("Level")}: ${e.level}%`,variant:"outlined"}),V(e)&&a(o,{size:"small",label:`${c("Close")}: ${e.percentToClose}%`,variant:"outlined"}),K(e)&&a(o,{size:"small",label:`${c("Duration")}: ${e.duration} ${c("min")}`,variant:"outlined"}),G(e)&&a(o,{size:"small",label:e.closeReason,variant:"outlined",color:"info"}),Z(e)&&a(o,{size:"small",label:e.cancelReason,variant:"outlined",color:"info"}),Q(e)&&a(o,{size:"small",label:`${c("Shift")}: ${e.percentShift>0?"+":""}${e.percentShift}%`,variant:"outlined"}),ie(e)&&a(o,{size:"small",label:`${c("Active")}: ${e.activePositionCount}`,variant:"outlined"}),ne(e)&&a(o,{size:"small",label:`${c("Entries")}: ${e.totalEntries}`,variant:"outlined"}),se(e)&&a(o,{size:"small",label:`${c("Partials")}: ${e.totalPartials}`,variant:"outlined"}),le(e)&&a(o,{size:"small",label:`${c("Cost")}: ${e.cost.toFixed(2)}$`,variant:"outlined"}),re(e)&&a(o,{size:"small",label:`${c("Avg entry")}: ${e.effectivePriceOpen}`,variant:"outlined",color:"warning"}),te(e)&&a(o,{size:"small",label:`${c("Orig entry")}: ${e.originalPriceOpen}`,variant:"outlined"})]}),N(e)&&a(p,{children:[a(d,{sx:{my:1}}),a(n,{direction:"row",spacing:3,flexWrap:"wrap",children:[a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Entry"),":"," "]}),e.priceOpen]}),J(e)&&a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Close"),":"," "]}),e.priceClose]}),q(e)&&a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Current"),":"," "]}),e.currentPrice]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Take Profit"),":"," "]}),e.priceTakeProfit]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Stop Loss"),":"," "]}),e.priceStopLoss]})]})]}),oe(e)&&a(p,{children:[a(d,{sx:{my:1}}),a(n,{direction:"row",spacing:3,flexWrap:"wrap",children:[a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL Entry"),":"," "]}),e.pnlPriceOpen]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL Exit"),":"," "]}),e.pnlPriceClose]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL"),":"," "]}),a(s,{component:"span",color:e.pnlCost>=0?"success.main":"error.main",children:[e.pnlCost>=0?"+":"",e.pnlCost.toFixed(2),"$"]})]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Invested"),":"," "]}),e.pnlEntries.toFixed(2),"$"]})]})]})]})]}),X(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(r,{component:"pre",sx:{m:0,whiteSpace:"pre-wrap",wordWrap:"break-word"},children:a(m,{style:{textWrap:"wrap"},config:u,handler:()=>e.note})})]}),ae(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(s,{variant:"body2",color:"error",children:e.rejectionNote})]}),ee(e)&&!X(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(s,{variant:"body2",color:"text.secondary",children:e.message})]}),a(r,{sx:{position:"absolute",top:0,left:0,bottom:0,width:6,zIndex:1,background:h}})]})})})}),pe=[{action:"update-now",label:"Refresh manually",icon:()=>a(F,{icon:R,color:"#4caf50"})}],de=[{type:O.Link,action:"back-action",label:a(B,{sx:{display:"block"}})},{type:O.Link,action:"back-action",label:"Main"},{type:O.Link,action:"back-action",label:"Notifications"}],me=new L,ue=()=>{const{data:e,hasMore:i,loading:r,onSkip:n}=w({handler:async(e,a)=>{const i=await P.notificationViewService.getList(),r=A(e,a);for(const n of i)if(r([n]).done)break;return r().rows},onLoadStart:()=>P.layoutService.setAppbarLoader(!0),onLoadEnd:()=>P.layoutService.setAppbarLoader(!1),reloadSubject:me});return a(T,{children:[a(z,{items:de,actions:pe,onAction:async e=>{"back-action"===e&&P.routerService.push("/"),"update-now"===e&&await me.next()}}),a(j,{sx:{height:"calc(100vh - 155px)"},withScrollbar:!0,minHeight:72,loading:r,onDataRequest:n,bufferSize:E,hasMore:i,children:e.map(e=>a(ce,{item:e,sx:{mb:1}},e.id))})]})};export{ue as NotificationPage,ue as default};
|
|
1
|
+
import{r as e,f as a,P as i,B as r,S as n,a8 as t,T as s,G as l,C as o,_ as c,F as p,a9 as d,aa as m,ab as u,ac as b,ad as v,ae as y,af as g,a6 as h,ag as k,ah as $,ai as f,aj as x,ak as S,al as _,am as C,i as P,a1 as w,j as L,a2 as A,q as z,Z as O,an as j,ao as E,I as F}from"./index-CBPue3Jb.js";import{C as T,R}from"./Refresh-DFUXqFNa.js";import{K as B}from"./KeyboardArrowLeft-D-vyob5u.js";const U=e=>{const i={color:"white",fontSize:28};switch(e.type){case"signal.opened":case"partial_profit.available":case"partial_profit.commit":return a(S,{sx:i});case"signal.closed":case"signal_sync.close":return a(h,{sx:i});case"signal.scheduled":return a(C,{sx:i});case"signal.cancelled":return a(_,{sx:i});case"partial_loss.available":case"partial_loss.commit":case"average_buy.commit":return a(f,{sx:i});case"breakeven.available":case"breakeven.commit":return a(x,{sx:i});case"activate_scheduled.commit":case"signal_sync.open":return a(k,{sx:i});case"trailing_stop.commit":case"trailing_take.commit":return a($,{sx:i});case"risk.rejection":return a(g,{sx:i});case"error.info":case"error.validation":return a(y,{sx:i});case"error.critical":return a(v,{sx:i});default:return a(b,{sx:i})}},D=e=>{switch(e.type){case"signal.opened":return`${c("Opened")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal.closed":return`${c("Closed")} ${e.symbol} (${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%)`;case"signal.scheduled":return`${c("Scheduled")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal.cancelled":return`${c("Cancelled")} ${e.symbol}`;case"partial_profit.available":return`${c("Partial profit")} ${e.level}% ${e.symbol}`;case"partial_profit.commit":return`${c("Profit fixed")} ${e.percentToClose}% ${e.symbol}`;case"partial_loss.available":return`${c("Partial loss")} ${e.level}% ${e.symbol}`;case"partial_loss.commit":return`${c("Loss fixed")} ${e.percentToClose}% ${e.symbol}`;case"breakeven.available":return`${c("Breakeven available")} ${e.symbol}`;case"breakeven.commit":return`${c("Breakeven set")} ${e.symbol}`;case"activate_scheduled.commit":return`${c("Activated")} ${e.position.toUpperCase()} ${e.symbol}`;case"average_buy.commit":return`${c("Average Buy")} ${e.symbol}`;case"trailing_stop.commit":return`${c("Trailing stop")} ${e.symbol}`;case"trailing_take.commit":return`${c("Trailing take")} ${e.symbol}`;case"signal_sync.open":return`${c("Sync Open")} ${e.position.toUpperCase()} ${e.symbol}`;case"signal_sync.close":return`${c("Sync Close")} ${e.symbol} (${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%)`;case"risk.rejection":return`${c("Rejected")} ${e.position.toUpperCase()} ${e.symbol}`;case"error.info":return`${c("Error")}: ${e.message}`;case"error.validation":return`${c("Validation")}: ${e.message}`;case"error.critical":return`${c("Critical")}: ${e.message}`;default:return c("Unknown")}},W=e=>{switch(e.type){case"signal.opened":return c("Signal Opened");case"signal.closed":return c("Signal Closed");case"signal.scheduled":return c("Signal Scheduled");case"signal.cancelled":return c("Signal Cancelled");case"partial_profit.available":return c("Partial Profit Available");case"partial_profit.commit":return c("Partial Profit Commit");case"partial_loss.available":return c("Partial Loss Available");case"partial_loss.commit":return c("Partial Loss Commit");case"breakeven.available":return c("Breakeven Available");case"breakeven.commit":return c("Breakeven Commit");case"activate_scheduled.commit":return c("Activated Scheduled");case"average_buy.commit":return c("Average Buy");case"trailing_stop.commit":return c("Trailing Stop");case"trailing_take.commit":return c("Trailing Take");case"signal_sync.open":return c("Signal Sync Open");case"signal_sync.close":return c("Signal Sync Close");case"risk.rejection":return c("Risk Rejection");case"error.info":return c("Info Error");case"error.validation":return c("Validation Error");case"error.critical":return c("Critical Error");default:return c("Unknown")}},I=e=>"symbol"in e,M=e=>"position"in e,N=e=>"priceOpen"in e&&"priceTakeProfit"in e&&"priceStopLoss"in e,Y=e=>"pnlPercentage"in e,H=e=>"level"in e,V=e=>"percentToClose"in e,q=e=>"currentPrice"in e,K=e=>"duration"in e,G=e=>"closeReason"in e,Z=e=>"cancelReason"in e,J=e=>"priceClose"in e,Q=e=>"percentShift"in e,X=e=>"note"in e&&!!e.note,ee=e=>"message"in e,ae=e=>"rejectionNote"in e,ie=e=>"activePositionCount"in e,re=e=>"effectivePriceOpen"in e,ne=e=>"totalEntries"in e&&e.totalEntries>1,te=e=>"originalPriceOpen"in e&&"priceOpen"in e&&e.originalPriceOpen!==e.priceOpen,se=e=>"totalPartials"in e&&e.totalPartials>0,le=e=>"cost"in e,oe=e=>"pnlPriceOpen"in e&&"pnlPriceClose"in e&&"pnlCost"in e&&"pnlEntries"in e,ce=e.forwardRef(({item:e,className:b,style:v,sx:y},g)=>{const h=(e=>{switch(e.type){case"signal.opened":case"activate_scheduled.commit":case"signal_sync.open":return"#4CAF50";case"signal.closed":case"signal_sync.close":return"#2196F3";case"signal.scheduled":case"average_buy.commit":case"error.info":case"error.validation":return"#FF9800";case"signal.cancelled":default:return"#9E9E9E";case"partial_profit.available":case"partial_profit.commit":return"#8BC34A";case"partial_loss.available":case"partial_loss.commit":return"#FF5722";case"breakeven.available":case"breakeven.commit":return"#00BCD4";case"trailing_stop.commit":case"trailing_take.commit":return"#673AB7";case"risk.rejection":return"#F44336";case"error.critical":return"#D32F2F"}})(e),k=(e=>"timestamp"in e)(e)?e.timestamp:Date.now();return a("div",{className:b,style:v,ref:g,children:a(i,{variant:"outlined",onClick:()=>(e=>{switch(e.type){case"risk.rejection":P.layoutService.pickRisk(e.id);break;case"signal.opened":P.layoutService.pickSignalOpened(e.id);break;case"signal.closed":P.layoutService.pickSignalClosed(e.id);break;case"signal.scheduled":P.layoutService.pickSignalScheduled(e.id);break;case"signal.cancelled":P.layoutService.pickSignalCancelled(e.id);break;case"partial_profit.available":P.layoutService.pickPartialProfitAvailable(e.id);break;case"partial_profit.commit":P.layoutService.pickPartialProfitCommit(e.id);break;case"partial_loss.available":P.layoutService.pickPartialLossAvailable(e.id);break;case"partial_loss.commit":P.layoutService.pickPartialLossCommit(e.id);break;case"breakeven.available":P.layoutService.pickBreakevenAvailable(e.id);break;case"breakeven.commit":P.layoutService.pickBreakevenCommit(e.id);break;case"trailing_stop.commit":P.layoutService.pickTrailingStop(e.id);break;case"trailing_take.commit":P.layoutService.pickTrailingTake(e.id);break;case"activate_scheduled.commit":P.layoutService.pickActivateScheduled(e.id);break;case"average_buy.commit":P.layoutService.pickAverageBuyCommit(e.id);break;case"signal_sync.open":P.layoutService.pickSignalSyncOpen(e.id);break;case"signal_sync.close":P.layoutService.pickSignalSyncClose(e.id)}})(e),sx:{transition:"box-shadow 0.2s ease",cursor:"pointer",display:"flex",alignItems:"stretch",justifyContent:"stretch","&:hover":{boxShadow:4},...y},children:a(r,{sx:{flex:1,position:"relative",overflow:"hidden",height:"100%",width:"100%",borderRadius:"12px"},children:[a(n,{direction:"row",spacing:2,sx:{p:2},children:[a(t,{sx:{width:56,height:56,background:h},children:U(e)}),a(n,{flex:1,spacing:1,children:[a(n,{direction:"row",justifyContent:"space-between",alignItems:"flex-start",children:[a(s,{variant:"h6",sx:{fontWeight:600},children:D(e)}),a(s,{variant:"body2",color:"text.secondary",sx:{whiteSpace:"nowrap",ml:2},children:l(k).format("HH:mm DD/MM/YYYY")})]}),a(n,{direction:"row",spacing:1,flexWrap:"wrap",children:[a(o,{size:"small",label:W(e),sx:{background:h,color:"white",fontWeight:500}}),I(e)&&a(o,{size:"small",label:e.symbol,variant:"outlined"}),M(e)&&a(o,{size:"small",label:e.position.toUpperCase(),variant:"outlined",color:"long"===e.position?"success":"error"}),Y(e)&&a(o,{size:"small",label:`PnL: ${e.pnlPercentage>0?"+":""}${e.pnlPercentage.toFixed(2)}%`,color:e.pnlPercentage>=0?"success":"error",variant:"outlined"}),H(e)&&a(o,{size:"small",label:`${c("Level")}: ${e.level}%`,variant:"outlined"}),V(e)&&a(o,{size:"small",label:`${c("Close")}: ${e.percentToClose}%`,variant:"outlined"}),K(e)&&a(o,{size:"small",label:`${c("Duration")}: ${e.duration} ${c("min")}`,variant:"outlined"}),G(e)&&a(o,{size:"small",label:e.closeReason,variant:"outlined",color:"info"}),Z(e)&&a(o,{size:"small",label:e.cancelReason,variant:"outlined",color:"info"}),Q(e)&&a(o,{size:"small",label:`${c("Shift")}: ${e.percentShift>0?"+":""}${e.percentShift}%`,variant:"outlined"}),ie(e)&&a(o,{size:"small",label:`${c("Active")}: ${e.activePositionCount}`,variant:"outlined"}),ne(e)&&a(o,{size:"small",label:`${c("Entries")}: ${e.totalEntries}`,variant:"outlined"}),se(e)&&a(o,{size:"small",label:`${c("Partials")}: ${e.totalPartials}`,variant:"outlined"}),le(e)&&a(o,{size:"small",label:`${c("Cost")}: ${e.cost.toFixed(2)}$`,variant:"outlined"}),re(e)&&a(o,{size:"small",label:`${c("Avg entry")}: ${e.effectivePriceOpen}`,variant:"outlined",color:"warning"}),te(e)&&a(o,{size:"small",label:`${c("Orig entry")}: ${e.originalPriceOpen}`,variant:"outlined"})]}),N(e)&&a(p,{children:[a(d,{sx:{my:1}}),a(n,{direction:"row",spacing:3,flexWrap:"wrap",children:[a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Entry"),":"," "]}),e.priceOpen]}),J(e)&&a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Close"),":"," "]}),e.priceClose]}),q(e)&&a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Current"),":"," "]}),e.currentPrice]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Take Profit"),":"," "]}),e.priceTakeProfit]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Stop Loss"),":"," "]}),e.priceStopLoss]})]})]}),oe(e)&&a(p,{children:[a(d,{sx:{my:1}}),a(n,{direction:"row",spacing:3,flexWrap:"wrap",children:[a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL Entry"),":"," "]}),e.pnlPriceOpen]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL Exit"),":"," "]}),e.pnlPriceClose]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("PnL"),":"," "]}),a(s,{component:"span",color:e.pnlCost>=0?"success.main":"error.main",children:[e.pnlCost>=0?"+":"",e.pnlCost.toFixed(2),"$"]})]}),a(s,{variant:"body2",children:[a(s,{component:"span",color:"text.secondary",children:[c("Invested"),":"," "]}),e.pnlEntries.toFixed(2),"$"]})]})]})]})]}),X(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(r,{component:"pre",sx:{m:0,whiteSpace:"pre-wrap",wordWrap:"break-word"},children:a(m,{style:{textWrap:"wrap"},config:u,handler:()=>e.note})})]}),ae(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(s,{variant:"body2",color:"error",children:e.rejectionNote})]}),ee(e)&&!X(e)&&a(r,{sx:{px:2,pb:2},children:[a(d,{sx:{mb:1.5}}),a(s,{variant:"body2",color:"text.secondary",children:e.message})]}),a(r,{sx:{position:"absolute",top:0,left:0,bottom:0,width:6,zIndex:1,background:h}})]})})})}),pe=[{action:"update-now",label:"Refresh manually",icon:()=>a(F,{icon:R,color:"#4caf50"})}],de=[{type:O.Link,action:"back-action",label:a(B,{sx:{display:"block"}})},{type:O.Link,action:"back-action",label:"Main"},{type:O.Link,action:"back-action",label:"Notifications"}],me=new L,ue=()=>{const{data:e,hasMore:i,loading:r,onSkip:n}=w({handler:async(e,a)=>{const i=await P.notificationViewService.getList(),r=A(e,a);for(const n of i)if(r([n]).done)break;return r().rows},onLoadStart:()=>P.layoutService.setAppbarLoader(!0),onLoadEnd:()=>P.layoutService.setAppbarLoader(!1),reloadSubject:me});return a(T,{children:[a(z,{items:de,actions:pe,onAction:async e=>{"back-action"===e&&P.routerService.push("/"),"update-now"===e&&await me.next()}}),a(j,{sx:{height:"calc(100vh - 155px)"},withScrollbar:!0,minHeight:72,loading:r,onDataRequest:n,bufferSize:E,hasMore:i,children:e.map(e=>a(ce,{item:e,sx:{mb:1}},e.id))})]})};export{ue as NotificationPage,ue as default};
|