diff --git a/crypto_monitor_binance/templates/index.html b/crypto_monitor_binance/templates/index.html
index 90d5b9f..443c22f 100644
--- a/crypto_monitor_binance/templates/index.html
+++ b/crypto_monitor_binance/templates/index.html
@@ -3,7 +3,7 @@
-
+
@@ -243,8 +243,8 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
-
-
+
+
-
+
+
@@ -243,8 +243,8 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
-
-
+
+
-
+
+
@@ -243,8 +243,8 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
-
-
+
+
-
+
+
@@ -243,8 +243,8 @@
.stats-period-block h3{font-size:1rem;color:#dbe4ff;margin-bottom:4px}
.stats-period-block .sub{font-size:.78rem;color:#8892b0;margin-bottom:10px;line-height:1.4}
-
-
+
+
-
+
+
-
-
+
+
{{ exchange_display }} · 加密货币 | 交易监控复盘系统
@@ -121,7 +121,7 @@
-
+
{% include 'embed_boot_scripts.html' %}
diff --git a/manual_trading_hub/static/index.html b/manual_trading_hub/static/index.html
index 27c2eef..4c43577 100644
--- a/manual_trading_hub/static/index.html
+++ b/manual_trading_hub/static/index.html
@@ -16,7 +16,7 @@
-
+
@@ -1058,7 +1058,7 @@
-
+
diff --git a/static/trade_stats_calendar.css b/static/trade_stats_calendar.css
index 30bd526..f928e3c 100644
--- a/static/trade_stats_calendar.css
+++ b/static/trade_stats_calendar.css
@@ -23,6 +23,29 @@
.stats-calendar-wrap {
margin-bottom: 14px;
}
+.trade-cal-wrap button.trade-cal-cell {
+ background: var(--trade-cal-cell-bg) !important;
+ background-image: none !important;
+ border: 1px solid transparent;
+ padding: 4px 3px;
+ min-height: 68px;
+ width: 100%;
+ box-shadow: none;
+ line-height: 1.15;
+ font-size: inherit;
+ text-align: center;
+}
+.trade-cal-wrap button.trade-cal-cell:disabled {
+ opacity: 1;
+ cursor: default;
+}
+.trade-cal-wrap .trade-cal-head .btn,
+.trade-cal-wrap .trade-cal-head button {
+ min-height: 0;
+ min-width: 34px;
+ padding: 4px 12px;
+ line-height: 1.2;
+}
.trade-cal-head {
display: flex;
align-items: center;
@@ -71,9 +94,10 @@
.trade-cal-cell.has-trade {
cursor: pointer;
}
-.trade-cal-cell.has-trade:hover {
+.trade-cal-wrap button.trade-cal-cell.has-trade:hover {
+ background: var(--trade-cal-cell-hover-bg) !important;
+ background-image: none !important;
border-color: var(--trade-cal-cell-hover-border);
- background: var(--trade-cal-cell-hover-bg);
}
.trade-cal-cell.is-selected {
border-color: var(--trade-cal-selected-border);
@@ -89,12 +113,6 @@
background: color-mix(in srgb, #3b82f6 14%, var(--trade-cal-sick-bg));
box-shadow: 0 0 0 2px var(--trade-cal-selected-shadow);
}
-.trade-cal-cell.pnl-pos .trade-cal-pnl {
- color: var(--trade-cal-pos);
-}
-.trade-cal-cell.pnl-neg .trade-cal-pnl {
- color: var(--trade-cal-neg);
-}
.trade-cal-day-num {
font-size: 0.78rem;
font-weight: 600;
@@ -104,10 +122,18 @@
font-size: 0.72rem;
font-weight: 600;
line-height: 1.1;
+ color: var(--text, #e8ecff);
+}
+.trade-cal-cell.pnl-pos .trade-cal-pnl {
+ color: var(--trade-cal-pos);
+}
+.trade-cal-cell.pnl-neg .trade-cal-pnl {
+ color: var(--trade-cal-neg);
}
.trade-cal-cnt {
font-size: 0.65rem;
color: var(--muted, #8892b0);
+ font-weight: 500;
}
.trade-cal-sick-tag {
font-size: 0.62rem;
diff --git a/static/trade_stats_calendar.js b/static/trade_stats_calendar.js
index 1c352dc..95f641c 100644
--- a/static/trade_stats_calendar.js
+++ b/static/trade_stats_calendar.js
@@ -18,6 +18,29 @@
return y + "年" + m + "月";
}
+ function formatCalPnl(pnl) {
+ var n = Number(pnl);
+ if (!Number.isFinite(n)) n = 0;
+ return (n >= 0 ? "+" : "") + n.toFixed(1) + "U";
+ }
+
+ function dayHasTrade(info) {
+ if (!info) return false;
+ var cnt = Number(info.open_count);
+ if (Number.isFinite(cnt) && cnt > 0) return true;
+ var pnl = Number(info.pnl_total);
+ return Number.isFinite(pnl) && Math.abs(pnl) > 0.0001;
+ }
+
+ function dayOpenCount(info) {
+ var cnt = Number(info && info.open_count);
+ return Number.isFinite(cnt) && cnt > 0 ? cnt : 0;
+ }
+
+ function dayPnl(info) {
+ return Number(info && info.pnl_total) || 0;
+ }
+
function TradeStatsCalendar(config) {
this.gridEl = config.gridEl;
this.titleEl = config.titleEl;
@@ -46,6 +69,8 @@
this.year = config.year || 0;
this.month = config.month || 0;
this.days = {};
+ this.monthPnlTotal = 0;
+ this.monthOpenCount = 0;
this._navBound = false;
this._bindNav();
}
@@ -72,7 +97,12 @@
TradeStatsCalendar.prototype.render = function () {
if (!this.gridEl || !this.titleEl) return;
if (this.year <= 0 || this.month <= 0) this.ensureMonth(new Date());
- this.titleEl.textContent = monthLabel(this.year, this.month);
+ var title = monthLabel(this.year, this.month);
+ if (this.monthOpenCount > 0) {
+ title +=
+ " · " + formatCalPnl(this.monthPnlTotal) + " · " + this.monthOpenCount + "笔";
+ }
+ this.titleEl.textContent = title;
var first = new Date(this.year, this.month - 1, 1);
var lastDay = new Date(this.year, this.month, 0).getDate();
var startWd = first.getDay();
@@ -94,10 +124,10 @@
"-" +
String(d).padStart(2, "0");
var info = this.days[dayStr];
- var hasTrade = info && info.open_count > 0;
+ var hasTrade = dayHasTrade(info);
var sick = this.showSick && info && info.has_sick;
- var pnl = hasTrade ? Number(info.pnl_total) : null;
- var cnt = hasTrade ? info.open_count : 0;
+ var pnl = hasTrade ? dayPnl(info) : null;
+ var cnt = hasTrade ? dayOpenCount(info) : 0;
var cls =
"trade-cal-cell" +
(hasTrade ? " has-trade" : "") +
@@ -110,10 +140,9 @@
: "");
var body = '' + d + "";
if (hasTrade) {
- var pnlTxt = (pnl >= 0 ? "+" : "") + pnl.toFixed(1);
body +=
'' +
- esc(pnlTxt) +
+ esc(formatCalPnl(pnl)) +
"" +
'' +
cnt +
@@ -168,6 +197,18 @@
data = await resp.json();
}
this.days = this.parseResponse(data) || {};
+ this.monthPnlTotal = Number(data && data.month_pnl_total) || 0;
+ this.monthOpenCount = Number(data && data.month_open_count) || 0;
+ if (!this.monthOpenCount) {
+ var self = this;
+ Object.keys(this.days).forEach(function (k) {
+ if (dayHasTrade(self.days[k])) {
+ self.monthOpenCount += dayOpenCount(self.days[k]);
+ self.monthPnlTotal += dayPnl(self.days[k]);
+ }
+ });
+ this.monthPnlTotal = Math.round(this.monthPnlTotal * 10000) / 10000;
+ }
this.render();
if (this.onMonthChange) this.onMonthChange(this.year, this.month, this.days);
} catch (e) {