feat数据统计曲线改为权益采样,现金加现货币权利金与浮盈。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-13 12:52:00 +08:00
parent fc0d76d174
commit 11c67b3c44
5 changed files with 291 additions and 36 deletions
+68 -11
View File
@@ -1,4 +1,4 @@
"""实例数据统计:复盘 KPI + 资金曲线 API,以及后台现金采样."""
"""实例数据统计:复盘 KPI + 权益曲线 API,以及后台权益采样."""
from __future__ import annotations
from typing import Any, Callable
@@ -10,13 +10,72 @@ def install_instance_data_stats(app: Flask, app_module: Any) -> None:
get_db: Callable = app_module.get_db
login_required = app_module.login_required
def _fetch_balances() -> dict[str, Any]:
ex = getattr(app_module, "exchange_options", None)
if ex is None:
return {}
from lib.exchange.okx_options_lib import fetch_options_balances
def _fetch_equity_snapshot() -> dict[str, Any]:
from lib.instance.instance_cash_sample_lib import (
cash_usdt_from_balances,
equity_usdt_from_snapshot,
)
return fetch_options_balances(ex, force=False) or {}
ex = getattr(app_module, "exchange_options", None)
bal: dict[str, Any] = {}
if ex is not None:
try:
from lib.exchange.okx_options_lib import fetch_options_balances
bal = fetch_options_balances(ex, force=False) or {}
except Exception:
bal = {}
cash = cash_usdt_from_balances(bal if isinstance(bal, dict) else None)
positions: list[dict[str, Any]] = []
cfg = None
try:
cfg = app.extensions.get("options_cfg")
except Exception:
cfg = None
if isinstance(cfg, dict) and cfg.get("enabled"):
try:
from lib.options.options_dashboard_lib import (
fetch_light_option_positions_for_dashboard,
)
positions = fetch_light_option_positions_for_dashboard(cfg) or []
except Exception:
positions = []
btc_px = eth_px = None
if ex is not None:
try:
from lib.options.options_stats_lib import _underlying_index_usdt
btc_px = _underlying_index_usdt(ex, "BTC")
eth_px = _underlying_index_usdt(ex, "ETH")
except Exception:
btc_px = eth_px = None
if (btc_px is None or eth_px is None) and positions:
for p in positions:
if not isinstance(p, dict):
continue
under = str(p.get("underlying") or "").upper()
idx = None
try:
idx = float(p.get("idx_px") or p.get("index_px") or 0)
except (TypeError, ValueError):
idx = None
if idx is None or idx <= 0:
continue
if under == "BTC" and btc_px is None:
btc_px = idx
elif under == "ETH" and eth_px is None:
eth_px = idx
equity = equity_usdt_from_snapshot(
bal if isinstance(bal, dict) else None,
positions,
btc_px=btc_px,
eth_px=eth_px,
)
return {"cash_usdt": cash, "equity_usdt": equity}
@app.route("/api/instance/cash_curve")
@login_required
@@ -26,9 +85,8 @@ def install_instance_data_stats(app: Flask, app_module: Any) -> None:
sample_once,
)
# 打开页面时尽量补一笔最新点(失败忽略)
try:
sample_once(get_db, _fetch_balances)
sample_once(get_db, _fetch_equity_snapshot)
except Exception:
pass
range_key = (request.args.get("range") or "7d").strip()
@@ -40,10 +98,9 @@ def install_instance_data_stats(app: Flask, app_module: Any) -> None:
finally:
conn.close()
# 后台采样(daemon);无密钥时会空转跳过
try:
from lib.instance.instance_cash_sample_lib import start_cash_sample_loop
start_cash_sample_loop(get_db, _fetch_balances)
start_cash_sample_loop(get_db, _fetch_equity_snapshot)
except Exception as e:
print(f"[instance_cash_sample] start skipped: {e}", flush=True)