diff --git a/app.py b/app.py index c77899b..957150e 100644 --- a/app.py +++ b/app.py @@ -1581,6 +1581,9 @@ def init_db(): from lib.options.options_db import init_options_tables init_options_tables(conn) + from lib.instance.instance_cash_sample_lib import init_cash_sample_table + + init_cash_sample_table(conn) from lib.sim.db_lib import init_sim_tables init_sim_tables(conn) from lib.trade.account_risk_lib import ensure_account_risk_schema @@ -4277,7 +4280,10 @@ def records_page(): @app.route("/stats") @login_required def stats_page(): - return redirect("/options") + redir = redirect_to_embed_shell_if_enabled("stats") + if redir is not None: + return redir + return render_main_page("stats") @app.route("/dashboard") @@ -5730,6 +5736,10 @@ from lib.options.options_review_register import install_options_review install_options_review(app, _REPO_ROOT, app_module=sys.modules[__name__]) +from lib.instance.instance_data_stats_register import install_instance_data_stats + +install_instance_data_stats(app, sys.modules[__name__]) + from lib.hub.hub_bridge_register import register_hub_bridge_routes register_hub_bridge_routes(app, sys.modules[__name__]) diff --git a/lib/common/static/options_data_stats.js b/lib/common/static/options_data_stats.js new file mode 100644 index 0000000..f08b825 --- /dev/null +++ b/lib/common/static/options_data_stats.js @@ -0,0 +1,345 @@ +/** + * 实例数据统计:复盘 KPI + 资金曲线. + */ +(function (global) { + "use strict"; + + var currentRange = "7d"; + var booted = false; + + function $(id) { + return document.getElementById(id); + } + + function root() { + return $("options-data-stats"); + } + + function escapeHtml(s) { + return String(s == null ? "" : s) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """); + } + + function fmtPnl(v) { + if (v == null || v === "") return "—"; + var n = Number(v); + if (Number.isNaN(n)) return "—"; + return (n >= 0 ? "+" : "") + n.toFixed(2) + "U"; + } + + function fmtHold(sec) { + if (sec == null) return "—"; + var s = Math.max(0, Number(sec) || 0); + if (s < 3600) return Math.round(s / 60) + "m"; + if (s < 86400) return (s / 3600).toFixed(1) + "h"; + return (s / 86400).toFixed(1) + "d"; + } + + function pnlClass(v) { + var n = Number(v); + if (Number.isNaN(n) || n === 0) return ""; + return n > 0 ? "ods-pnl-pos" : "ods-pnl-neg"; + } + + function closeReasonLabel(r) { + var map = { + perp_tp: "永续止盈", + perp_sl: "永续止损", + oo_expiry_loss: "期期到期亏损", + oo_expiry_win: "期期到期盈利", + target_win_leg: "期期平盈利腿", + profit_rr_win_leg: "期期盈亏比达标·平盈利腿", + }; + return map[r] || String(r || "未填"); + } + + function sourceType() { + var el = root(); + return (el && el.getAttribute("data-source-type")) || "option_spot"; + } + + function setStatus(text) { + var el = $("ods-status"); + if (el) el.textContent = text || ""; + } + + function renderGroup(title, items) { + if (!items || !items.length) return ""; + var lines = items + .slice(0, 8) + .map(function (g) { + var keyLabel = + title === "对冲结束原因" ? closeReasonLabel(g.key) : String(g.key || ""); + return ( + '
与「期权复盘」页统计同源;复盘页内统计仍保留。
+ + +现金余额(交易账户+资金账户,不含权利金与浮盈);后台定时采样。
+ +