diff --git a/frontend/app/about/page.tsx b/frontend/app/about/page.tsx index 87d143a..778d8db 100644 --- a/frontend/app/about/page.tsx +++ b/frontend/app/about/page.tsx @@ -2,19 +2,19 @@ export default function AboutPage() { return (
-

策略说明

-

资金费率套利原理与历史数据

+

策略说明

+

资金费率套利原理与历史数据

-
-

策略原理

-

+

+

策略原理

+

永续合约每8小时结算一次资金费率。多头多时,多头付钱给空头(费率为正);空头多时,空头付钱给多头(费率为负)。

-

- 套利做法:现货买入 + 永续做空,完全对冲币价风险,净收资金费率(USDT结算)。 +

+ 套利做法:现货买入 + 永续做空,完全对冲币价风险,净收资金费率(USDT结算)。

-
+
买入 1 BTC 现货($96,000)
做空 1 BTC 永续($96,000,1倍杠杆)
───────────────────────
@@ -23,25 +23,25 @@ export default function AboutPage() {
-
-

历史年化数据(2019-2026,露露×小周15轮验证)

+
+

历史年化数据(2019-2026,露露×小周15轮验证)

- - - - - + + + + + - - - + + + - + @@ -55,11 +55,11 @@ export default function AboutPage() {
资产全周期毛年化PM净年化负费率占比
资产全周期毛年化PM净年化负费率占比
BTC
BTC 12.33% 11.67% 13.07%
ETH 14.87% 14.09%
-

PM = Portfolio Margin模式,资金利用率约95%。数据来源:Binance fapi/v1/fundingRate官方API

+

PM = Portfolio Margin模式,资金利用率约95%。数据来源:Binance fapi/v1/fundingRate官方API

-
-

风险说明

+
+

风险说明

{[ { level: "🟡 中", risk: "市场周期", desc: "熊市年化可降至0-4%,但不亏本金" }, @@ -68,10 +68,10 @@ export default function AboutPage() { { level: "🟢 低", risk: "爆仓风险", desc: "1倍杠杆+对冲,理论需BTC翻倍才触发" }, { level: "🟢 低", risk: "基差波动", desc: "长期持有不影响,只影响平仓时机" }, ].map((r, i) => ( -
+
{r.level} - {r.risk} - {r.desc} + {r.risk} + {r.desc}
))}
diff --git a/frontend/app/dashboard/page.tsx b/frontend/app/dashboard/page.tsx index 289ee66..da3c5f0 100644 --- a/frontend/app/dashboard/page.tsx +++ b/frontend/app/dashboard/page.tsx @@ -41,36 +41,36 @@ export default function DashboardPage() { const logout = () => { localStorage.removeItem("arb_token"); router.push("/"); }; - if (!user) return
加载中...
; + if (!user) return
加载中...
; const tierLabel: Record = { free: "免费版", pro: "Pro", premium: "Premium" }; return (
-

我的账户

- +

我的账户

+
-
-

账户信息

+
+

账户信息

-
邮箱
-
{user.email}
-
订阅等级
-
{tierLabel[user.tier] || user.tier}
-
到期时间
-
{user.expires_at ? new Date(user.expires_at).toLocaleDateString("zh-CN") : "永久免费"}
+
邮箱
+
{user.email}
+
订阅等级
+
{tierLabel[user.tier] || user.tier}
+
到期时间
+
{user.expires_at ? new Date(user.expires_at).toLocaleDateString("zh-CN") : "永久免费"}
-
-

Discord 信号推送

-

绑定Discord ID后,当套利信号触发时会自动@你

+
+

Discord 信号推送

+

绑定Discord ID后,当套利信号触发时会自动@你

setDiscordId(e.target.value)} - className="flex-1 bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="flex-1 bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" placeholder="Discord用户ID(18位数字)" />
{msg &&

{msg}

} -

如何获取Discord ID:设置 → 外观 → 开发者模式 → 右键个人头像 → 复制用户ID

+

如何获取Discord ID:设置 → 外观 → 开发者模式 → 右键个人头像 → 复制用户ID

-
-

升级订阅

+
+

升级订阅

{[ { tier: "free", label: "免费版", price: "¥0", features: ["实时费率面板"] }, { tier: "pro", label: "Pro", price: "¥99/月", features: ["实时费率面板", "信号Discord推送", "历史数据"] }, { tier: "premium", label: "Premium", price: "¥299/月", features: ["Pro全部功能", "定制阈值", "优先客服"] }, ].map(p => ( -
-
{p.label}
-
{p.price}
+
+
{p.label}
+
{p.price}
    {p.features.map(f =>
  • • {f}
  • )}
{user.tier !== p.tier && p.tier !== "free" && ( - )} diff --git a/frontend/app/globals.css b/frontend/app/globals.css index bd4d1e6..6382e08 100644 --- a/frontend/app/globals.css +++ b/frontend/app/globals.css @@ -1,13 +1,14 @@ @import "tailwindcss"; :root { - --background: #0f172a; - --foreground: #e2e8f0; - --card: #1e293b; - --card-foreground: #e2e8f0; - --border: #334155; - --muted: #475569; - --cyan: #06b6d4; + --background: #ffffff; + --foreground: #0f172a; + --card: #f8fafc; + --card-foreground: #0f172a; + --border: #e2e8f0; + --muted: #64748b; + --primary: #2563eb; + --primary-foreground: #ffffff; } @theme inline { diff --git a/frontend/app/history/page.tsx b/frontend/app/history/page.tsx index a28c674..94da428 100644 --- a/frontend/app/history/page.tsx +++ b/frontend/app/history/page.tsx @@ -37,16 +37,16 @@ export default function HistoryPage() { return (
-

历史费率

-

过去7天 BTC / ETH 资金费率记录

+

历史费率

+

过去7天 BTC / ETH 资金费率记录

{loading ? ( -
加载中...
+
加载中...
) : ( <> -
-

费率走势(过去7天)

+
+

费率走势(过去7天)

@@ -60,19 +60,19 @@ export default function HistoryPage() {
-
+
- - - + + + {tableData.map((row, i) => ( - - + + diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index 88ed7bd..b96c217 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -3,31 +3,18 @@ import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import Navbar from "@/components/Navbar"; -const geistSans = Geist({ - variable: "--font-geist-sans", - subsets: ["latin"], -}); - -const geistMono = Geist_Mono({ - variable: "--font-geist-mono", - subsets: ["latin"], -}); +const geistSans = Geist({ variable: "--font-geist-sans", subsets: ["latin"] }); +const geistMono = Geist_Mono({ variable: "--font-geist-mono", subsets: ["latin"] }); export const metadata: Metadata = { title: "Arbitrage Engine", description: "Funding rate arbitrage monitoring system", }; -export default function RootLayout({ - children, -}: Readonly<{ - children: React.ReactNode; -}>) { +export default function RootLayout({ children }: Readonly<{ children: React.ReactNode }>) { return ( - - + +
{children}
diff --git a/frontend/app/login/page.tsx b/frontend/app/login/page.tsx index 8324b13..b44f52d 100644 --- a/frontend/app/login/page.tsx +++ b/frontend/app/login/page.tsx @@ -36,28 +36,28 @@ function LoginForm() { return (
-
+
-

登录

+

登录

{params.get("registered") && (

✅ 注册成功,请登录

)} -

登录后查看信号和账户信息

+

登录后查看信号和账户信息

- + setEmail(e.target.value)} - className="w-full bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" placeholder="your@email.com" />
- + setPassword(e.target.value)} - className="w-full bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" />
{error &&

{error}

} @@ -68,8 +68,8 @@ function LoginForm() { {loading ? "登录中..." : "登录"} -

- 没有账号?注册 +

+ 没有账号?注册

diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index e3342d1..571fae7 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -37,8 +37,8 @@ export default function Dashboard() { useEffect(() => { fetchRates(); fetchAll(); - const rateInterval = setInterval(fetchRates, 2_000); // 价格 2秒刷新 - const slowInterval = setInterval(fetchAll, 120_000); // 统计 2分钟刷新 + const rateInterval = setInterval(fetchRates, 2_000); + const slowInterval = setInterval(fetchAll, 120_000); return () => { clearInterval(rateInterval); clearInterval(slowInterval); }; }, [fetchRates, fetchAll]); @@ -47,25 +47,18 @@ export default function Dashboard() { {/* Header */}
-

资金费率套利监控

-

实时监控 BTC / ETH 永续合约资金费率

+

资金费率套利监控

+

实时监控 BTC / ETH 永续合约资金费率

- - + + {status === "running" ? "运行中" : status === "error" ? "连接失败" : "加载中..."} - {lastUpdate && ( - 更新于 {lastUpdate} - )} + {lastUpdate && 更新于 {lastUpdate}}
@@ -78,38 +71,23 @@ export default function Dashboard() { {/* Stats Cards */} {stats && (
- - - + + +
)} {/* History Chart */} {history && ( -
-

过去7天资金费率走势

+
+

过去7天资金费率走势

)} {/* Strategy note */} -
- 策略原理: +
+ 策略原理: 持有现货多头 + 永续空头,每8小时收取资金费率,赚取无方向风险的稳定收益。
diff --git a/frontend/app/register/page.tsx b/frontend/app/register/page.tsx index a4e57c7..5c35748 100644 --- a/frontend/app/register/page.tsx +++ b/frontend/app/register/page.tsx @@ -32,34 +32,34 @@ export default function RegisterPage() { return (
-
+
-

注册账号

-

注册后可接收套利信号推送

+

注册账号

+

注册后可接收套利信号推送

- + setEmail(e.target.value)} - className="w-full bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" placeholder="your@email.com" />
- + setPassword(e.target.value)} - className="w-full bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" placeholder="至少8位" minLength={8} />
- + setDiscordId(e.target.value)} - className="w-full bg-slate-900 border border-slate-600 rounded-lg px-3 py-2 text-slate-100 text-sm focus:outline-none focus:border-cyan-500" + className="w-full bg-white border border-slate-200 rounded-lg px-3 py-2 text-slate-900 text-sm focus:outline-none focus:border-cyan-500" placeholder="例:123456789012345678" />
@@ -71,8 +71,8 @@ export default function RegisterPage() { {loading ? "注册中..." : "注册"} -

- 已有账号?登录 +

+ 已有账号?登录

diff --git a/frontend/app/signals/page.tsx b/frontend/app/signals/page.tsx new file mode 100644 index 0000000..a4249fb --- /dev/null +++ b/frontend/app/signals/page.tsx @@ -0,0 +1,61 @@ +"use client"; + +import { useEffect, useState } from "react"; +import { api, SignalHistoryItem } from "@/lib/api"; + +export default function SignalsPage() { + const [items, setItems] = useState([]); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(""); + + useEffect(() => { + const run = async () => { + try { + const data = await api.signalsHistory(); + setItems(data.items || []); + } catch { + setError("加载信号历史失败"); + } finally { + setLoading(false); + } + }; + run(); + }, []); + + return ( +
+

信号历史

+
+ {loading ?

加载中...

: null} + {error ?

{error}

: null} + {!loading && !error ? ( +
时间BTC 费率
时间BTC 费率 ETH 费率
{row.time}
{row.time} = 0 ? "text-emerald-400" : "text-red-400"}`}> {row.btc != null ? `${row.btc.toFixed(4)}%` : "--"}
+ + + + + + + + + + {items.map((row) => ( + + + + + + + ))} + {!items.length ? ( + + + + ) : null} + +
时间币种年化信号类型
{new Date(row.sent_at).toLocaleString("zh-CN")}{row.symbol}{row.annualized}%资金费率套利信号
暂无信号记录(费率超10%时自动触发)
+ ) : null} +
+
+ ); +} diff --git a/frontend/components/Navbar.tsx b/frontend/components/Navbar.tsx index 4e6d651..0352189 100644 --- a/frontend/components/Navbar.tsx +++ b/frontend/components/Navbar.tsx @@ -13,34 +13,30 @@ export default function Navbar() { const [open, setOpen] = useState(false); return ( -