From 04a1828f4cca58545725aef8fb6eb6312d3d1e83 Mon Sep 17 00:00:00 2001
From: Administrator <15274802129@163.com>
Date: Thu, 08 Oct 2026 11:57:19 +0800
Subject: [PATCH] feat(stations): 添加每轮止损次数统计功能
---
src/main/resources/static/station-dashboard.html | 61 ++++++++++++++++++++++++++++++
1 files changed, 61 insertions(+), 0 deletions(-)
diff --git a/src/main/resources/static/station-dashboard.html b/src/main/resources/static/station-dashboard.html
index 2ef4010..bf70675 100644
--- a/src/main/resources/static/station-dashboard.html
+++ b/src/main/resources/static/station-dashboard.html
@@ -415,6 +415,24 @@
<!-- 事件日志 Tab -->
<div class="tab-content" data-tab="events">
+ <div class="events-panel" style="margin-bottom:16px">
+ <div class="events-header">
+ <h3>🎯 每轮止损次数</h3>
+ <button class="btn btn-outline" onclick="refreshRoundStopLoss()" style="font-size:11px;padding:3px 10px">🔄 刷新</button>
+ </div>
+ <div style="max-height:300px;overflow-y:auto">
+ <table class="events-table">
+ <thead>
+ <tr>
+ <th style="width:120px">轮次</th>
+ <th style="width:120px">多仓止损</th>
+ <th>空仓止损</th>
+ </tr>
+ </thead>
+ <tbody id="roundStopLossBody"></tbody>
+ </table>
+ </div>
+ </div>
<div class="events-panel">
<div class="events-header">
<h3>📋 最近 100 条事件</h3>
@@ -680,6 +698,9 @@
// 加载事件(内部会渲染事件表格 + PNL 图表)
await loadEvents(md5);
+ // 加载每轮止损次数
+ loadRoundStopLoss(md5);
+
// 事件加载完成后重算统计卡:账户总权益依赖最新 PNL_SNAPSHOT
if (selectedMd5 === md5 && instances[md5]) {
renderStats(instances[md5]);
@@ -833,6 +854,38 @@
}).join('');
renderPnlChart();
+}
+
+// ==================== 每轮止损次数 ====================
+async function loadRoundStopLoss(md5) {
+ try {
+ const rows = await api(API + '/round-stop-loss?apiKeyMd5=' + encodeURIComponent(md5));
+ renderRoundStopLoss(rows || []);
+ } catch (e) {
+ renderRoundStopLoss([]);
+ }
+}
+
+function renderRoundStopLoss(rows) {
+ const tbody = $('roundStopLossBody');
+ if (!tbody) return;
+ if (!rows || rows.length === 0) {
+ tbody.innerHTML = `<tr><td colspan="3" style="text-align:center;padding:20px;color:var(--dim)">暂无止损记录</td></tr>`;
+ return;
+ }
+ tbody.innerHTML = rows.map(r => {
+ const roundLabel = (r.roundNum === null || r.roundNum === undefined) ? '进行中' : ('第 ' + r.roundNum + ' 轮');
+ return `
+ <tr>
+ <td>${esc(roundLabel)}</td>
+ <td>${r.longLossCount ?? 0}</td>
+ <td>${r.shortLossCount ?? 0}</td>
+ </tr>`;
+ }).join('');
+}
+
+function refreshRoundStopLoss() {
+ if (selectedMd5) loadRoundStopLoss(selectedMd5);
}
// ==================== PNL 图表 ====================
@@ -1041,6 +1094,10 @@
dualStopLossEnabled: false,
longStopLossPrice: '',
shortStopLossPrice: '',
+ tpTriggerOppositeAddEnabled: false,
+ tpTriggerOppositeAddQuantity: 0,
+ baseTakeProfitPerGrid: 0,
+ baseTakeProfitGridCount: 0,
};
async function loadConfig(md5) {
@@ -1073,6 +1130,8 @@
{ key: 'quantity', label: '每次下单张数', type: 'number', placeholder: '2', jtype: 'string', group: 'grid' },
{ key: 'maxPositionSize', label: '最大持仓张数', type: 'number', placeholder: '4', jtype: 'int', group: 'grid' },
{ key: 'takeProfitGridSpan', label: '止盈网格跨度', type: 'number', placeholder: '2', jtype: 'int', group: 'grid' },
+ { key: 'baseTakeProfitPerGrid', label: '单格止盈张数', type: 'number', step: 'any', placeholder: '0', jtype: 'decimal', group: 'grid', tip: '基础仓位止盈:每个网格挂的止盈张数(支持小数)' },
+ { key: 'baseTakeProfitGridCount', label: '止盈网格数量', type: 'number', placeholder: '0', jtype: 'int', group: 'grid', tip: '基础仓位止盈:挂止盈的网格数量' },
{ key: 'expectedProfit', label: '预期收益 (USDT)', type: 'number', step: '0.01', placeholder: '0.15', jtype: 'decimal', group: 'risk' },
{ key: 'maxLoss', label: '最大亏损 (USDT)', type: 'number', step: '0.01', placeholder: '1.5', jtype: 'decimal', group: 'risk' },
@@ -1083,6 +1142,8 @@
{ key: 'addPositionQuantity', label: '加仓数量 (张)', type: 'number', placeholder: '1', jtype: 'int', group: 'addon' },
{ key: 'maxPositionPerSide', label: '单边最大仓位 (0=不限)', type: 'number', placeholder: '0', jtype: 'int', group: 'addon' },
{ key: 'addPositionStartThreshold', label: '加仓启动阈值 (次)', type: 'number', placeholder: '1', jtype: 'int', group: 'addon', tip: '前 N 次止损不触发加仓' },
+ { key: 'tpTriggerOppositeAddEnabled', label: '止盈触发对向加仓', type: 'select', options: [{ v: 'false', l: '关闭' }, { v: 'true', l: '开启' }], group: 'addon', tip: '止盈单成交后触发对向加仓' },
+ { key: 'tpTriggerOppositeAddQuantity', label: '对向加仓挂单数量 (张)', type: 'number', placeholder: '0', jtype: 'int', group: 'addon', tip: '止盈成交后在对向挂出的加仓张数' },
{ key: 'rounds', label: '运行轮数 (0=不限)', type: 'number', placeholder: '0', jtype: 'int', group: 'run', tip: '盈利重启达此轮数后停止' },
{ key: 'placeExcessTakeProfit', label: '止盈模式', type: 'select', options: [{ v: 'off', l: '关闭' }, { v: 'concentrated', l: '集中止盈' }, { v: 'dispersed', l: '分散止盈' }], group: 'run', tip: '超出基础仓位的加仓部分如何挂止盈' },
--
Gitblit v1.9.1