diff --git a/frontend/src/components/AdminDashboard.jsx b/frontend/src/components/AdminDashboard.jsx
index d92ba3b..4b93cc1 100644
--- a/frontend/src/components/AdminDashboard.jsx
+++ b/frontend/src/components/AdminDashboard.jsx
@@ -50,7 +50,7 @@ export default function AdminDashboard() {
{(summary.total_assets_usdt ?? 0).toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}
- 各账号快照汇总,不调币安接口
+ 各账号 account_snapshots 快照汇总,不调币安。由定时任务 sync_binance_orders.py 每 3 小时同步时写入;若为 0 请先跑一次该脚本
总盈亏 (USDT)
diff --git a/scripts/SYNC_BINANCE_README.md b/scripts/SYNC_BINANCE_README.md
index 1a91067..10b553f 100644
--- a/scripts/SYNC_BINANCE_README.md
+++ b/scripts/SYNC_BINANCE_README.md
@@ -51,3 +51,7 @@ python scripts/sync_binance_orders.py --delay-between-accounts 60
## 5. 数据管理
管理后台「数据管理」-「币安订单/成交查询」从 DB 读取,不再调用币安 API。
+
+## 6. 账户余额快照(总资产缓存)
+
+同步脚本在拉取每个账号的订单/成交后,会顺带调用一次该账号的 `futures_account` 取余额,并写入 `account_snapshots` 表。管理员仪表板「总资产 (USDT)」即对各账号该表最近一条快照的 `total_balance` 汇总,**不每次请求币安**。若从未跑过本脚本(或脚本报错未写入快照),总资产会显示 0;跑一次后即可有数据。
diff --git a/scripts/sync_binance_orders.py b/scripts/sync_binance_orders.py
index af6b7a1..b90b90f 100644
--- a/scripts/sync_binance_orders.py
+++ b/scripts/sync_binance_orders.py
@@ -198,6 +198,24 @@ async def sync_account(account_id: int, hours: int = 6) -> tuple:
except Exception as e:
return len(trade_params), 0, f"写入 orders 失败: {e}"
+ # 写入账户余额快照,供管理员仪表板「总资产」汇总(不每次调币安)
+ try:
+ balance = await client.get_account_balance()
+ if balance and balance.get("ok") and (balance.get("total") is not None or balance.get("margin") is not None):
+ total_balance = float(balance.get("total") or balance.get("margin") or 0)
+ available_balance = float(balance.get("available") or balance.get("availableBalance") or 0)
+ from database.models import AccountSnapshot
+ AccountSnapshot.create(
+ total_balance=total_balance,
+ available_balance=available_balance,
+ total_position_value=0,
+ total_pnl=0,
+ open_positions=0,
+ account_id=account_id,
+ )
+ except Exception as e:
+ pass # 快照失败不影响主流程,仅总资产可能暂为 0
+
return len(trade_params), len(order_params), None
finally:
if client.client: