a
This commit is contained in:
parent
bec62631cb
commit
6394701732
|
|
@ -135,7 +135,10 @@ async def get_realtime_account_data():
|
|||
|
||||
# 计算总仓位价值和总盈亏
|
||||
logger.info("步骤7: 计算仓位统计...")
|
||||
# total_position_value:历史上这里代表“名义仓位价值(notional)”(按标记价)
|
||||
total_position_value = 0
|
||||
# total_margin_value:更贴近风控配置语义(保证金占用)
|
||||
total_margin_value = 0
|
||||
total_pnl = 0
|
||||
open_positions_count = 0
|
||||
|
||||
|
|
@ -154,13 +157,23 @@ async def get_realtime_account_data():
|
|||
|
||||
position_value = abs(position_amt * mark_price)
|
||||
total_position_value += position_value
|
||||
|
||||
# 保证金占用(粗略口径):名义/杠杆(币安页面的展示会更复杂,但这个口径与 MAX_TOTAL_POSITION_PERCENT 对齐)
|
||||
try:
|
||||
lv = float(pos.get('leverage', 0) or 0)
|
||||
if lv <= 0:
|
||||
lv = 1.0
|
||||
except Exception:
|
||||
lv = 1.0
|
||||
total_margin_value += (position_value / lv)
|
||||
total_pnl += unrealized_pnl
|
||||
open_positions_count += 1
|
||||
|
||||
logger.debug(f" - {pos.get('symbol')}: 价值={position_value:.2f}, 盈亏={unrealized_pnl:.2f}")
|
||||
|
||||
logger.info(" ✓ 仓位统计计算完成")
|
||||
logger.info(f" - 总仓位价值: {total_position_value:.2f} USDT")
|
||||
logger.info(f" - 总名义仓位: {total_position_value:.2f} USDT")
|
||||
logger.info(f" - 总保证金占用(估算): {total_margin_value:.2f} USDT")
|
||||
logger.info(f" - 总盈亏: {total_pnl:.2f} USDT")
|
||||
logger.info(f" - 持仓数量: {open_positions_count}")
|
||||
|
||||
|
|
@ -176,7 +189,10 @@ async def get_realtime_account_data():
|
|||
result = {
|
||||
"total_balance": balance.get('total', 0) if balance else 0,
|
||||
"available_balance": balance.get('available', 0) if balance else 0,
|
||||
# 名义仓位(按标记价汇总)
|
||||
"total_position_value": total_position_value,
|
||||
# 保证金占用(名义/杠杆汇总)
|
||||
"total_margin_value": total_margin_value,
|
||||
"total_pnl": total_pnl,
|
||||
"open_positions": open_positions_count
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,21 +176,57 @@ async def get_dashboard_data():
|
|||
try:
|
||||
from database.models import TradingConfig
|
||||
total_balance = float(account_data.get('total_balance', 0))
|
||||
total_position_value = float(account_data.get('total_position_value', 0))
|
||||
max_total_position_percent = float(TradingConfig.get_value('MAX_TOTAL_POSITION_PERCENT', 0.30))
|
||||
|
||||
# 当前仓位占比
|
||||
current_position_percent = (total_position_value / total_balance * 100) if total_balance > 0 else 0
|
||||
# 名义仓位(notional)与保证金占用(margin)是两个口径:
|
||||
# - 名义仓位可以 > 100%(高杠杆下非常正常)
|
||||
# - MAX_TOTAL_POSITION_PERCENT 在当前系统语义里是“保证金占用比例”
|
||||
total_notional_value = float(account_data.get('total_position_value', 0))
|
||||
|
||||
# 最大仓位量(根据配置的最大占比计算)
|
||||
max_position_value = total_balance * max_total_position_percent
|
||||
# 优先使用 account_data 里的 total_margin_value;如果没有则从 open_trades 汇总兜底
|
||||
total_margin_value = account_data.get('total_margin_value', None)
|
||||
try:
|
||||
total_margin_value = float(total_margin_value) if total_margin_value is not None else None
|
||||
except Exception:
|
||||
total_margin_value = None
|
||||
|
||||
if total_margin_value is None:
|
||||
total_margin_value = 0.0
|
||||
for t in open_trades or []:
|
||||
try:
|
||||
mv = t.get("margin_usdt", None)
|
||||
if mv is None:
|
||||
# fallback:名义/杠杆
|
||||
nv = float(t.get("notional_usdt", 0) or 0)
|
||||
lv = float(t.get("leverage", 0) or 0)
|
||||
if lv <= 0:
|
||||
lv = 1.0
|
||||
mv = nv / lv
|
||||
total_margin_value += float(mv or 0)
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# 当前仓位占比(保证金口径,与你的 MAX_TOTAL_POSITION_PERCENT 对齐)
|
||||
current_margin_percent = (total_margin_value / total_balance * 100) if total_balance > 0 else 0
|
||||
# 名义占比(仅用于参考)
|
||||
current_notional_percent = (total_notional_value / total_balance * 100) if total_balance > 0 else 0
|
||||
|
||||
# 最大允许保证金(USDT)
|
||||
max_margin_value = total_balance * max_total_position_percent
|
||||
|
||||
position_stats = {
|
||||
"current_position_percent": round(current_position_percent, 2),
|
||||
# 兼容旧字段:current_position_percent 现在代表“保证金占比”
|
||||
"current_position_percent": round(current_margin_percent, 2),
|
||||
"current_position_percent_type": "margin",
|
||||
"current_notional_percent": round(current_notional_percent, 2),
|
||||
"max_position_percent": round(max_total_position_percent * 100, 2),
|
||||
"max_position_value": round(max_position_value, 2),
|
||||
# 兼容旧字段:max_position_value/total_position_value 现在代表“保证金(USDT)”
|
||||
"max_position_value": round(max_margin_value, 2),
|
||||
"total_balance": round(total_balance, 2),
|
||||
"total_position_value": round(total_position_value, 2)
|
||||
"total_position_value": round(total_margin_value, 2),
|
||||
# 额外信息:名义价值(USDT),用于解释“名义占比可能>100%”
|
||||
"total_notional_value": round(total_notional_value, 2),
|
||||
"total_margin_value": round(total_margin_value, 2),
|
||||
}
|
||||
except Exception as e:
|
||||
logger.warning(f"计算仓位占比信息失败: {e}")
|
||||
|
|
|
|||
|
|
@ -165,9 +165,15 @@ const StatsDashboard = () => {
|
|||
<span className="value">{parseFloat(account.available_balance).toFixed(2)} USDT</span>
|
||||
</div>
|
||||
<div className="info-item">
|
||||
<span className="label">总仓位:</span>
|
||||
<span className="label">总仓位(名义):</span>
|
||||
<span className="value">{parseFloat(account.total_position_value).toFixed(2)} USDT</span>
|
||||
</div>
|
||||
{account.total_margin_value !== undefined && account.total_margin_value !== null && (
|
||||
<div className="info-item">
|
||||
<span className="label">保证金占用(估算):</span>
|
||||
<span className="value">{parseFloat(account.total_margin_value).toFixed(2)} USDT</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="info-item">
|
||||
<span className="label">总盈亏:</span>
|
||||
<span className={`value ${parseFloat(account.total_pnl) >= 0 ? 'positive' : 'negative'}`}>
|
||||
|
|
@ -189,7 +195,7 @@ const StatsDashboard = () => {
|
|||
<h3>仓位占比</h3>
|
||||
<div className="account-info">
|
||||
<div className="info-item">
|
||||
<span className="label">当前仓位占比:</span>
|
||||
<span className="label">当前仓位占比(保证金):</span>
|
||||
<span className="value">
|
||||
<span>{dashboardData.position_stats.current_position_percent}%</span>
|
||||
<span className="position-bar-container">
|
||||
|
|
@ -211,16 +217,22 @@ const StatsDashboard = () => {
|
|||
<span className="label">最大仓位占比:</span>
|
||||
<span className="value">{dashboardData.position_stats.max_position_percent}%</span>
|
||||
</div>
|
||||
{dashboardData.position_stats.current_notional_percent !== undefined && (
|
||||
<div className="info-item">
|
||||
<span className="label">名义占比(参考):</span>
|
||||
<span className="value">{dashboardData.position_stats.current_notional_percent}%</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="info-item">
|
||||
<span className="label">最大仓位量:</span>
|
||||
<span className="label">最大保证金:</span>
|
||||
<span className="value">{dashboardData.position_stats.max_position_value.toFixed(2)} USDT</span>
|
||||
</div>
|
||||
<div className="info-item">
|
||||
<span className="label">已用仓位:</span>
|
||||
<span className="label">已用保证金:</span>
|
||||
<span className="value">{dashboardData.position_stats.total_position_value.toFixed(2)} USDT</span>
|
||||
</div>
|
||||
<div className="info-item">
|
||||
<span className="label">可用仓位:</span>
|
||||
<span className="label">可用保证金:</span>
|
||||
<span className="value">
|
||||
{(dashboardData.position_stats.max_position_value - dashboardData.position_stats.total_position_value).toFixed(2)} USDT
|
||||
</span>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user