From 870df5705180e3aee0c069a8406c08b1a9a4e710 Mon Sep 17 00:00:00 2001
From: ramseshk <45832522+ramseshk@users.noreply.github.com>
Date: Fri, 7 Aug 2026 15:19:18 +0800
Subject: [PATCH] =?UTF-8?q?fix:=20dashboard=20errors=20=E2=80=94=20Math.ab?=
=?UTF-8?q?s,=20API=20routing,=20fetchHistorical=20guard?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Fixes three bugs in dashboard:
1. vbt.html: bare abs(dd) → Math.abs(dd) — fixes ReferenceError
2. server.py: Add /cv/ routing for Next.js quant dashboard
- Mount _next static assets at /cv/_next (not /cv/ which eats API routes)
- Add /cv/api/* routes for backtests/historical, detail, recalc, risk
- Add /cv/ws WebSocket endpoints for live/paper metrics
- Add /cv/ catchall for Next.js HTML pages
3. dashboard-next/src/lib/api.ts: add res.ok guard to fetchHistorical()
— prevents SyntaxError when API returns HTML error pages
4. sim/maker.py: guard observe() against zero mid_price
---
cli.py | 6 +-
dashboard-next/next-env.d.ts | 7 ++
dashboard-next/out/404.html | 2 +-
dashboard-next/out/404/index.html | 2 +-
dashboard-next/out/__next.__PAGE__.txt | 27 +++---
dashboard-next/out/__next._full.txt | 31 ++++---
dashboard-next/out/__next._tree.txt | 12 ++-
.../41wlgrdKzoSUpkrWIQ9jn/_buildManifest.js | 11 ---
.../_clientMiddlewareManifest.js | 1 -
.../41wlgrdKzoSUpkrWIQ9jn/_ssgManifest.js | 1 -
.../CxC9DIW0Ude54_bbbG52g/_buildManifest.js | 11 ---
.../_clientMiddlewareManifest.js | 1 -
.../CxC9DIW0Ude54_bbbG52g/_ssgManifest.js | 1 -
.../out/_next/static/chunks/0h2qsuyze9ds1.js | 1 -
.../out/_next/static/chunks/0oyhbmfwzlodf.js | 9 --
.../out/_next/static/chunks/0zo24_4e178qg.js | 22 -----
.../out/_next/static/chunks/1inwntv0b4r-7.js | 31 -------
.../out/_next/static/chunks/3_iofbsn7eau1.js | 22 -----
.../out/_next/static/chunks/3wqi32p1v2fl1.css | 3 -
.../static/chunks/turbopack-03obbfwpb8m_e.js | 1 -
.../static/chunks/turbopack-0h5dlbl0gen72.js | 1 -
.../13bf9871fe164e7f-s.2f7nqdagzwx2-.woff2 | Bin 2020 -> 0 bytes
.../1bffadaabf893a1e-s.3-6t-g6q0vh0a.woff2 | Bin 85272 -> 0 bytes
.../2bbe8d2671613f1f-s.0k62hbripvv8p.woff2 | Bin 10280 -> 0 bytes
.../2c55a0e60120577a-s.0-dom-5bn10r2.woff2 | Bin 25844 -> 0 bytes
.../3fe682a82f50d426-s.0vfdmo25voy_0.woff2 | Bin 15204 -> 0 bytes
.../5476f68d60460930-s.2uwcyprjm3xu3.woff2 | Bin 19044 -> 0 bytes
.../70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2 | Bin 40480 -> 0 bytes
.../71b036adf157cdcf-s.0bp8oijd_gu96.woff2 | Bin 9084 -> 0 bytes
.../83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2 | Bin 48432 -> 0 bytes
.../89b21bb081cb7469-s.1fby2rem9ngyr.woff2 | Bin 7468 -> 0 bytes
.../9c72aa0f40e4eef8-s.1y4-pdgsjb-pw.woff2 | Bin 18744 -> 0 bytes
.../ad66f9afd8947f86-s.3lvt2whj97whp.woff2 | Bin 11272 -> 0 bytes
.../cc545e633e20c56d-s.176arc174-8zp.woff2 | Bin 12064 -> 0 bytes
.../static/media/favicon.2vob68tjqpejf.ico | Bin 25931 -> 0 bytes
.../out/_not-found/__next._full.txt | 19 ++---
.../_not-found/__next._not-found.__PAGE__.txt | 29 +++----
.../out/_not-found/__next._tree.txt | 4 +-
dashboard-next/out/_not-found/index.html | 2 +-
dashboard-next/out/_not-found/index.txt | 19 ++---
dashboard-next/out/favicon.ico | Bin 25931 -> 0 bytes
dashboard-next/out/file.svg | 1 -
dashboard-next/out/globe.svg | 1 -
dashboard-next/out/index.html | 5 +-
dashboard-next/out/index.txt | 31 ++++---
dashboard-next/out/next.svg | 1 -
dashboard-next/out/vercel.svg | 1 -
dashboard-next/out/window.svg | 1 -
dashboard-next/src/lib/api.ts | 1 +
dashboard/server.py | 80 +++++++++++++++++-
dashboard/static/vbt.html | 2 +-
sim/maker.py | 3 +
52 files changed, 188 insertions(+), 215 deletions(-)
create mode 100644 dashboard-next/next-env.d.ts
delete mode 100644 dashboard-next/out/_next/static/41wlgrdKzoSUpkrWIQ9jn/_buildManifest.js
delete mode 100644 dashboard-next/out/_next/static/41wlgrdKzoSUpkrWIQ9jn/_clientMiddlewareManifest.js
delete mode 100644 dashboard-next/out/_next/static/41wlgrdKzoSUpkrWIQ9jn/_ssgManifest.js
delete mode 100644 dashboard-next/out/_next/static/CxC9DIW0Ude54_bbbG52g/_buildManifest.js
delete mode 100644 dashboard-next/out/_next/static/CxC9DIW0Ude54_bbbG52g/_clientMiddlewareManifest.js
delete mode 100644 dashboard-next/out/_next/static/CxC9DIW0Ude54_bbbG52g/_ssgManifest.js
delete mode 100644 dashboard-next/out/_next/static/chunks/0h2qsuyze9ds1.js
delete mode 100644 dashboard-next/out/_next/static/chunks/0oyhbmfwzlodf.js
delete mode 100644 dashboard-next/out/_next/static/chunks/0zo24_4e178qg.js
delete mode 100644 dashboard-next/out/_next/static/chunks/1inwntv0b4r-7.js
delete mode 100644 dashboard-next/out/_next/static/chunks/3_iofbsn7eau1.js
delete mode 100644 dashboard-next/out/_next/static/chunks/3wqi32p1v2fl1.css
delete mode 100644 dashboard-next/out/_next/static/chunks/turbopack-03obbfwpb8m_e.js
delete mode 100644 dashboard-next/out/_next/static/chunks/turbopack-0h5dlbl0gen72.js
delete mode 100644 dashboard-next/out/_next/static/media/13bf9871fe164e7f-s.2f7nqdagzwx2-.woff2
delete mode 100644 dashboard-next/out/_next/static/media/1bffadaabf893a1e-s.3-6t-g6q0vh0a.woff2
delete mode 100644 dashboard-next/out/_next/static/media/2bbe8d2671613f1f-s.0k62hbripvv8p.woff2
delete mode 100644 dashboard-next/out/_next/static/media/2c55a0e60120577a-s.0-dom-5bn10r2.woff2
delete mode 100644 dashboard-next/out/_next/static/media/3fe682a82f50d426-s.0vfdmo25voy_0.woff2
delete mode 100644 dashboard-next/out/_next/static/media/5476f68d60460930-s.2uwcyprjm3xu3.woff2
delete mode 100644 dashboard-next/out/_next/static/media/70bc3e132a0a741e-s.p.3t6q91iet4nsy.woff2
delete mode 100644 dashboard-next/out/_next/static/media/71b036adf157cdcf-s.0bp8oijd_gu96.woff2
delete mode 100644 dashboard-next/out/_next/static/media/83afe278b6a6bb3c-s.p.2bn3s6zvc0dyp.woff2
delete mode 100644 dashboard-next/out/_next/static/media/89b21bb081cb7469-s.1fby2rem9ngyr.woff2
delete mode 100644 dashboard-next/out/_next/static/media/9c72aa0f40e4eef8-s.1y4-pdgsjb-pw.woff2
delete mode 100644 dashboard-next/out/_next/static/media/ad66f9afd8947f86-s.3lvt2whj97whp.woff2
delete mode 100644 dashboard-next/out/_next/static/media/cc545e633e20c56d-s.176arc174-8zp.woff2
delete mode 100644 dashboard-next/out/_next/static/media/favicon.2vob68tjqpejf.ico
delete mode 100644 dashboard-next/out/favicon.ico
delete mode 100644 dashboard-next/out/file.svg
delete mode 100644 dashboard-next/out/globe.svg
delete mode 100644 dashboard-next/out/next.svg
delete mode 100644 dashboard-next/out/vercel.svg
delete mode 100644 dashboard-next/out/window.svg
diff --git a/cli.py b/cli.py
index a10a777..75bd7cc 100644
--- a/cli.py
+++ b/cli.py
@@ -215,8 +215,10 @@ def cmd_run(args):
import asyncio
from live.node_v2 import ProductionNode
+ coins = [c.strip().upper() for c in args.coins.split(",") if c.strip()]
+
node = ProductionNode(
- coins=args.coins,
+ coins=coins,
testnet=not args.mainnet,
mode=args.mode,
max_position_per_coin=args.max_position,
@@ -277,7 +279,7 @@ def main():
# run
pr = sp.add_parser("run", help="Start production node")
- pr.add_argument("--coins", nargs="+", default=["BTC", "ETH"])
+ pr.add_argument("--coins", default="BTC,ETH", help="Comma-separated coin list")
pr.add_argument("--mainnet", action="store_true")
pr.add_argument("--mode", default="paper", choices=["paper", "live"])
pr.add_argument("--max-position", type=float, default=0.003)
diff --git a/dashboard-next/next-env.d.ts b/dashboard-next/next-env.d.ts
new file mode 100644
index 0000000..ce4e94a
--- /dev/null
+++ b/dashboard-next/next-env.d.ts
@@ -0,0 +1,7 @@
+///
S1snRrK&)i%L(tjS+Cs0cWBOwGixCS|v^ewNPS+;32p zE+~DNC_`8Agq(vEf~1Kl2puTlp?LiIS4yg9y0`K*l3fOb3!rDrp$#s6|Ml6-^VF*D zr6rDQrz~ZKw7HOg)~1JohLMAj%mM&GlOTN7rZfDrL56a7AQBWw6Mb#&`^W#|MPgxQ z{Ut;(206nr7mRVet+&av;YE0L?oI(Ac`nb<( (N!|w^0hcErpC9tJyp0-{=QGj%c z1_;>v1N;=(n IBq(g%#QCT z6sk?D71c_zWI9QzT&4rs$(0Mob ){(fXW`5#dI6%&i6Id&NFR9AApj8z$Mml zF_z#+qcNIk9YiDDF) &L8^eHENz@HNE0oJnLfLM zbzw|Bt#FI;NbrUb{^0`2L02WNlpiBa6-I+u=sw(}O>-9@
tXPtpZ>JQ zLKl7Wl50_ipFQh;y!n~jeLXLxNFaa!fbL6)-5iLmJ#a*Zzml*Eew3 z|15jJbAWW93n36oFbn`AfZo$^xj-G}j yVYPRfmu9FiEJyC>3WvJ zX*`z+okkhG=(TIrP*y;?ofX@1X-nB*vfnn1^Tv&yYduHN6g8paTnD>eW(~b7$oXb# z7tMVY*R8z4-rZV kcsx@A|YLdhzFHgz@O--U(AuJGPX9lfWVMf2mp!?3l{N{1)PGi6xK1zp3 znRZS|owKY{+fersRqQe9L_1#;mqr)PJA@c%fl~f+Y2v0{m+DbEXB~3E(v^}H8*K!M z1Ai@sY7Icqnd_LgA@I5>TrGU>wdH9qhI%I(LMQceQL)P0ggJz!LwEmKLN=cbr8Z
uw6FG`p z$=_5_zJ!7tF)=^&J+k=(BGf5m%%bU&Sj0|9jL+a>=5YGJI;PEP^duJ(2M**DM4mvF z^6M?YdU$0})+1yed_W9eePZy@_%+_#@Ldwy3e;i PPJTC^XTQW2dP6h;Rpg*E`lU!n;&3V~&8Qu7{GT@#}GFigxcw zrapgrPrM<2gGr_O1LMY66*GcQtu8q{*{_6UOOkGAjioc| Q@a4#rG+Awf@ w?v`U{f zk&&e+7-M1~PSa8U#vW%z5U)gWz` vJjTDy96*$hoaBeY+f~6u1;$P=Ux0DwS4UL_H@8D@-!c2;G%$W8?fq zfeJkccj65-sEl{kM}P7>t?4J@&3pV)^f@@9-V>DT_P8FmOli!Hv%J&pQKGv=fw_oO z-(~UZ)y`_Hsg(A$d z^fy7N1zBH=M5Zn!YIAQL+fv`$bEUQ{*{iCXYk!k^_=fKSXb!D3bWW`0_nd@t zmW8sY#UbwJrXYnYoCRqbhuGzCr6^@dB2kTLQp5yEC+`@JpzHl|*Xv}(j9A@4^zw%W zE$X{vx3?b;2c<9s0f(Rw4l<&o@OmCeRfte`!7!Cdml~xW(v_kd{7S8uN-fpVzH21L zgp?v}Q)ZtEUmls00Cy< OzT< zhXFJ>wF$^r=M~o&h(PP^+o~rfC(m)Rq*xb{khJ)~vS-IG!Gp#8_PcvmK+p(IU|s{I zoc{f*XotUHa*>YTyl^OsSu{7{O_>X^{foR>W^QztDH;6F$(Ur_vG)cBv%B2)KMv9o z 37Gc>{Fpm)o_B6Lm^YLI{<)^RO4u$hF1! =PEbu}=5o`K0SKm!V yLX`z$z4&YJrC z$hpYQ)WEyypo^J-b8ce+tCs^Xy_4X=6a3IQ$%SXl%xJ@?c;L~KaT%wCdc(|#)sk@K zIY$m%`AuBwB{n|RF=5Q_vh&f1Aj^C=-UNpG$6?@;qud7(GrXQIAtt8ZXAWb2>|Alh z$u5VIfrD9-ixVji#(w15Vzfqi#g2vqnIb-x{$)FU!SKQ$|7JXVv)7MRJaw=)kCnU$ zYW%(T{N&|f9p8_w{kz@Krcm--W7wg@dfK;9Chp@F@0gr^G_zOoJ?!$
0;TdJCv z$yStX)|2pZzcfW29M$CZF>#$i{l5QEgP5Ov9vly>N}c$PadZjnv2mpCt+ecW8dH1CML^>qh0Sg4^dX|NXtZcakmN zFH!!>g}kYjE~?ZMwYT-;gP^C>$IPkZmE z@*Zf)6s0YE9y%<|csFYPZ4QS3k^g@AfTOcHhhJL5*j9^wkCQZz_AM!$J>J0%UaR(V zG75j`-u9NLzD0Fu?T3zbY 9E2l%b78$3#3|{VSYfYYR{$Bxl;_DJFq!Rm= zkhNupX?XiUmg~1BFnoAg8auJs>^rm0^AofXvDvu32gDsY6r~q-xP`Nu%6?(b_XJ&{ zul~tV?+p@07Pd4th(X+wfewY 0x zo1@>0oi9s<6^W6qI?;};zI`X_qS Xvi0K z8_|rOJlA(kzZeItetMU20>{5OiGO($iQgP|f((GQx>FL2+&z;Ll2;v`WwWupVb<(_ zuT9}5vqi53$XT?uE!8Y1w^s1Bxt_K9!yH4IU1P@vw1DXAvhgDX@d~*lBwi&!M3AJn z|2^Ha>kZ*?qNh#Y)rY~U*?ii?4mCef-+e4oOFV`3yAG@9If&6+2P~4YymxmX+|8vb z#ia#T7cDF`n9;n2M$#m?(lR;vK&rjy+Olu$q=OnQ-4wgbB}HDt(RLKQ%I@FtiN%y3 zyUIJ_{QOn}e!G1A#y6{)N4`F`(ducf&8H=dm6t~|W#dY(gVCyGkEq?alMr2_=Buwk zF}`H`7IjrQRqw$I(zx>*naRqV)=*f2N1w5`8XR!gS^Hqsq||J-xGHj&o2ai#uja}S zHwc*PNfzPZ@0Tgopv#*oiZeLv&O85aQ<4@Tm}+*t0p2^LsK`+;ngZJ05sX=Ba^w(J zds@{HsDiM6N=DYY$&0iokFqN&%8j07PUWrtDbk^=i*i4T$!kue%lC|QhGBsCwsga# z4Rfy#>{-|Xtx9+TxVe%DjY4Y8sX1#*6KL4vsUBu9*b$m;>$BKk;C;{KPCJkVwI!a9 zf4N-2p{$px6}3u j{r>(;L1XRdo!kC1QOi`f-uSgNrE_; z$acQitsz@2?ty&0a}ooY=aj$iiI+CReN)`=!G-Av<(z^ar#jNgS0e+RJj{sJ<}jl8 zU8(>?GNdNO15vtfWlC<7xVHSd5u-%g>ojdA5&TKwH<|K-Ab-xBT>s=c(-(zI;ctnU z7MR|6{YbifuD|B(zGIM25!<(ZHU4G`&&PI~nBJ`+d3XDtMRf1>8%OnF-^le&*bYXV zNCA{)#M0SlG0Tw;J@0`_&eH+!UOQLvLzdl_G I#QWz0m&Hyge@oC|T|BEH4pe6T;Fz052B z1LKwauD=&ZG=d2T$echzpMU^EBU4P8DIApt@_@g_#jy;*-}H+{Bq+Zzluc~rXMz}N zb5?(J0b?s=wRV+49un+XJx);?qje`Y?_s$m$}?~L8vX+$_saf6;_p} iLstW^=nXX5l7U86J>h2UPos=`%_vZ6-7_| zr<&yiVcfkF3DQwD=Ap?MH -O>EuOgch)hBfEY;Oi6xKxt3HjrRV32G3ezN7bHH{ z>1DhiAj1e98+F5puA2*_t=+(#o8OxBQFyRp07$eTIq8^3TYFYO%=WXMt4YpjjJm9d zFR+WQ%@%&>LCrUV<*S75%>D6#ToP*hpZ`{yKO3hI1BpsxHF@NfBMEd3TdJYyV0_Iw z|IspCwbgk)(`pVC+Cm2RX%+Q;kHC2C2ZwtOaGU1DyD+K`XW|XDIH7*mCHSkT uT}H&*=Caa&{-Rk) z0ZJiJ1+%!}08TQ7cG{9ZTFO>jgwhXK%8;`Kof;md;|_2db;x8>ArJNaFI&nQHO$;6 zI;@1Rg{DtoVVFg&K4mOv_3D7mtx2Sta#{1qH9`|D#W%G96{E27q`EUJ{Ut !stCCwdHzUNr^Q zth4#UaDVGa%wtF|_tT Ry~axLcmC- zRv0%-@M|~<@?405K jYb5FFJNs12a%_b7rp-;qN~s5NY;}s>dxMD-TcJ-G?BdX zd@p5ufAG-YG3cg3s-^@ vS zC+M9_6qqjyBE22;byKc1AQE99V5gX%qQ`CRQV)V*T|7d)9#e#3VRZSJm<(`1M@?S< zk>fqy{o$CcEBm=N9f=a^oD?pK&mt<*;Cb=j_11jtxT${H{BBmrNZ6XP9&lD2KZRae z8nza;d^WMT3Ar=*@=EH^hvtg|{uNP!?IG=aFYMH{vq11;q lJrZL;*8_W4b1XXKxL%l$5JKk6wy z<^K7v!OVc}W8h=2u11iN;7 a zjuLW?y*<=wCk{yrg-(`To3Xg{ynOI @|PFORZ;us;Xe=$ z2=~|uV!m$!rBrv{{ov2cv_`rn_3wbT_K2IR^64pMYmq(D;(^{ce#n^ztdv4OFHPGz zUfHwGC`Et;Fa})WCODlOcDH?Q62q|p;k*v;_dZKqUk&R6K(HNM5zMBd4==hcGmF=w z-$zV?i~GNq83q0bP&VD#N5+Sfqu@i{R~;g)f$x$2DR%U6_x{gb7m_&aK7;<)G8A+y zrJs9j`@Hr(G|gx51;6WY@ y#BEl|RAz!~MKa_i1*kcyxfTH6-}HZ@c#IxAXdN_ovt%4eg?Dztuq10B!g8 zcG=uoQ>oGhAZtC*Yxc(@&*TGZdjZE^ f46PdOo=V{2>gMh9Lg!z7 zYaDfuDTKH8bEF%;$o%Auxi{8>Ol05kobLW>*-5+v(O2MVG`IPU+_&ZPI_hcI%q-C( zDP6`I`5Vzh{)y5H^UEUI_SQx)#f^-iI4$)tY*(KQ;0|AISMJHZr;W^Te@hwn$7lUN zU+|TPt$a;0GW`ob){Bm2EQ|g;sap_xCr2_DU9X?hZp?T}+!7Vt@SeHK{;!q5TMd*p zkM;E`@P?8#hm9{%r!H>!sWRW^_jeEoM;xJXasd7=DPBr@8=foVQcJ^4`1Gv_Nv@5* zsTwiFmr^R)qAe-J>5K#GQeSOjTjZ_zZa5#q)*O<`$?-v#RP~u4|J|5^9DA3*x%EH( z?Lr?CRP-v+vBHK2Eh5+Q@x;gJ|I>zD)w?WSw8zKf34f&j$1XV#`&u^mT5