|
@@ -186,6 +186,13 @@
|
|
|
border-radius: 10px;
|
|
border-radius: 10px;
|
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ .events-container h2 {
|
|
|
|
|
+ margin-bottom: 15px;
|
|
|
|
|
+ color: #333;
|
|
|
|
|
+ border-bottom: 2px solid #667eea;
|
|
|
|
|
+ padding-bottom: 10px;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
.events-table {
|
|
.events-table {
|
|
|
width: 100%;
|
|
width: 100%;
|
|
@@ -315,6 +322,15 @@
|
|
|
|
|
|
|
|
<div class="events-container">
|
|
<div class="events-container">
|
|
|
<h2>📋 交易事件记录</h2>
|
|
<h2>📋 交易事件记录</h2>
|
|
|
|
|
+ <div style="background: #e7f3ff; padding: 10px; border-radius: 5px; margin-bottom: 15px; border-left: 4px solid #667eea;">
|
|
|
|
|
+ <strong>💡 提示:</strong>
|
|
|
|
|
+ <span style="color: #555;">
|
|
|
|
|
+ 图表上的标记点显示所有交易事件。点击标记可查看详情。
|
|
|
|
|
+ <span style="margin-left: 10px;">
|
|
|
|
|
+ 📈开多 | 📉开空 | 🔼平多 | 🔽平空
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </span>
|
|
|
|
|
+ </div>
|
|
|
<div id="eventsContent">
|
|
<div id="eventsContent">
|
|
|
<div class="loading">正在加载数据...</div>
|
|
<div class="loading">正在加载数据...</div>
|
|
|
</div>
|
|
</div>
|
|
@@ -330,6 +346,7 @@
|
|
|
let thumbnailData = null;
|
|
let thumbnailData = null;
|
|
|
let selectedTimeRange = null;
|
|
let selectedTimeRange = null;
|
|
|
let resizeHandler = null;
|
|
let resizeHandler = null;
|
|
|
|
|
+ let tradingEventsData = []; // 存储交易事件数据
|
|
|
|
|
|
|
|
// 初始化页面
|
|
// 初始化页面
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
@@ -555,6 +572,23 @@
|
|
|
result += `${param.marker} ${param.name}: ${value.toFixed(6)}<br/>`;
|
|
result += `${param.marker} ${param.name}: ${value.toFixed(6)}<br/>`;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // 检查是否有交易事件在这个时间点附近(±5秒)
|
|
|
|
|
+ if (tradingEventsData && tradingEventsData.length > 0) {
|
|
|
|
|
+ const timestampSec = timestamp / 1000;
|
|
|
|
|
+ const nearbyEvents = tradingEventsData.filter(event =>
|
|
|
|
|
+ Math.abs(event.timestamp - timestampSec) < 5
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (nearbyEvents.length > 0) {
|
|
|
|
|
+ result += '<br/><strong style="color: #667eea;">📌 交易事件:</strong><br/>';
|
|
|
|
|
+ nearbyEvents.forEach(event => {
|
|
|
|
|
+ const icon = getEventIcon(event.event_type);
|
|
|
|
|
+ const eventName = formatEventType(event.event_type);
|
|
|
|
|
+ result += `${icon} ${eventName} @ ${event.price ? event.price.toFixed(6) : '-'}<br/>`;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
@@ -641,6 +675,11 @@
|
|
|
|
|
|
|
|
// 同步两个图表的缩放
|
|
// 同步两个图表的缩放
|
|
|
syncChartsZoom();
|
|
syncChartsZoom();
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有交易事件数据,添加标记
|
|
|
|
|
+ if (tradingEventsData && tradingEventsData.length > 0) {
|
|
|
|
|
+ addEventMarkersToCharts();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 显示BPS图表
|
|
// 显示BPS图表
|
|
@@ -695,6 +734,23 @@
|
|
|
result += `${param.marker} ${param.name}: ${value.toFixed(2)}<br/>`;
|
|
result += `${param.marker} ${param.name}: ${value.toFixed(2)}<br/>`;
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+ // 检查是否有交易事件在这个时间点附近(±5秒)
|
|
|
|
|
+ if (tradingEventsData && tradingEventsData.length > 0) {
|
|
|
|
|
+ const timestampSec = timestamp / 1000;
|
|
|
|
|
+ const nearbyEvents = tradingEventsData.filter(event =>
|
|
|
|
|
+ Math.abs(event.timestamp - timestampSec) < 5
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ if (nearbyEvents.length > 0) {
|
|
|
|
|
+ result += '<br/><strong style="color: #667eea;">📌 交易事件:</strong><br/>';
|
|
|
|
|
+ nearbyEvents.forEach(event => {
|
|
|
|
|
+ const icon = getEventIcon(event.event_type);
|
|
|
|
|
+ const eventName = formatEventType(event.event_type);
|
|
|
|
|
+ result += `${icon} ${eventName} @ ${event.price ? event.price.toFixed(6) : '-'}<br/>`;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
@@ -763,6 +819,14 @@
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
bpsChart.setOption(option);
|
|
bpsChart.setOption(option);
|
|
|
|
|
+
|
|
|
|
|
+ // 如果有交易事件数据,添加标记
|
|
|
|
|
+ if (tradingEventsData && tradingEventsData.length > 0) {
|
|
|
|
|
+ // 延迟添加标记,确保图表已完全渲染
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ addEventMarkersToCharts();
|
|
|
|
|
+ }, 100);
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 同步两个图表的缩放
|
|
// 同步两个图表的缩放
|
|
@@ -820,6 +884,243 @@
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 添加交易事件标记到图表
|
|
|
|
|
+ function addEventMarkersToCharts() {
|
|
|
|
|
+ if (!priceChart || !bpsChart || !tradingEventsData || tradingEventsData.length === 0) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 准备标记线数据
|
|
|
|
|
+ const priceMarkLines = [];
|
|
|
|
|
+ const priceMarkPoints = [];
|
|
|
|
|
+ const bpsMarkLines = [];
|
|
|
|
|
+ const bpsMarkPoints = [];
|
|
|
|
|
+
|
|
|
|
|
+ tradingEventsData.forEach(event => {
|
|
|
|
|
+ const timestamp = event.timestamp * 1000; // 转换为毫秒
|
|
|
|
|
+ const eventType = event.event_type;
|
|
|
|
|
+
|
|
|
|
|
+ // 确定颜色和符号
|
|
|
|
|
+ let color, symbol, symbolSize, label;
|
|
|
|
|
+
|
|
|
|
|
+ if (eventType.includes('open_long')) {
|
|
|
|
|
+ color = '#28a745'; // 绿色
|
|
|
|
|
+ symbol = 'arrow'; // 向上箭头
|
|
|
|
|
+ symbolSize = 15;
|
|
|
|
|
+ label = '开多';
|
|
|
|
|
+ } else if (eventType.includes('open_short')) {
|
|
|
|
|
+ color = '#dc3545'; // 红色
|
|
|
|
|
+ symbol = 'arrow'; // 向下箭头(会旋转180度)
|
|
|
|
|
+ symbolSize = 15;
|
|
|
|
|
+ label = '开空';
|
|
|
|
|
+ } else if (eventType.includes('close_long')) {
|
|
|
|
|
+ color = '#007bff'; // 蓝色
|
|
|
|
|
+ symbol = 'triangle'; // 三角形
|
|
|
|
|
+ symbolSize = 12;
|
|
|
|
|
+ label = '平多';
|
|
|
|
|
+ } else if (eventType.includes('close_short')) {
|
|
|
|
|
+ color = '#6f42c1'; // 紫色
|
|
|
|
|
+ symbol = 'triangle'; // 三角形
|
|
|
|
|
+ symbolSize = 12;
|
|
|
|
|
+ label = '平空';
|
|
|
|
|
+ } else {
|
|
|
|
|
+ color = '#6c757d'; // 灰色
|
|
|
|
|
+ symbol = 'circle';
|
|
|
|
|
+ symbolSize = 10;
|
|
|
|
|
+ label = '其他';
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 创建标记线(垂直线)
|
|
|
|
|
+ const markLine = {
|
|
|
|
|
+ xAxis: timestamp,
|
|
|
|
|
+ lineStyle: {
|
|
|
|
|
+ color: color,
|
|
|
|
|
+ type: 'dashed',
|
|
|
|
|
+ width: 1,
|
|
|
|
|
+ opacity: 0.6
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: false
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // 创建标记点
|
|
|
|
|
+ const markPoint = {
|
|
|
|
|
+ coord: [timestamp, event.price || 0],
|
|
|
|
|
+ value: label,
|
|
|
|
|
+ symbol: symbol,
|
|
|
|
|
+ symbolSize: symbolSize,
|
|
|
|
|
+ symbolRotate: eventType.includes('short') ? 180 : 0, // 空头箭头向下
|
|
|
|
|
+ itemStyle: {
|
|
|
|
|
+ color: color,
|
|
|
|
|
+ borderColor: '#fff',
|
|
|
|
|
+ borderWidth: 2
|
|
|
|
|
+ },
|
|
|
|
|
+ label: {
|
|
|
|
|
+ show: true,
|
|
|
|
|
+ position: 'top',
|
|
|
|
|
+ formatter: function(params) {
|
|
|
|
|
+ return label;
|
|
|
|
|
+ },
|
|
|
|
|
+ fontSize: 10,
|
|
|
|
|
+ color: color,
|
|
|
|
|
+ fontWeight: 'bold'
|
|
|
|
|
+ },
|
|
|
|
|
+ // 添加tooltip数据
|
|
|
|
|
+ eventData: event
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ priceMarkLines.push(markLine);
|
|
|
|
|
+ priceMarkPoints.push(markPoint);
|
|
|
|
|
+ bpsMarkLines.push(markLine);
|
|
|
|
|
+
|
|
|
|
|
+ // BPS图表的标记点(使用ask_bps或bid_bps)
|
|
|
|
|
+ const bpsValue = event.ask_bps || event.bid_bps || 0;
|
|
|
|
|
+ const bpsMarkPoint = {
|
|
|
|
|
+ ...markPoint,
|
|
|
|
|
+ coord: [timestamp, bpsValue]
|
|
|
|
|
+ };
|
|
|
|
|
+ bpsMarkPoints.push(bpsMarkPoint);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ // 更新价格图表,添加标记
|
|
|
|
|
+ const priceOption = priceChart.getOption();
|
|
|
|
|
+ if (priceOption.series && priceOption.series.length > 0) {
|
|
|
|
|
+ // 在第一个系列(Binance价格)上添加标记
|
|
|
|
|
+ priceOption.series[0].markLine = {
|
|
|
|
|
+ silent: false,
|
|
|
|
|
+ data: priceMarkLines,
|
|
|
|
|
+ animation: false
|
|
|
|
|
+ };
|
|
|
|
|
+ priceOption.series[0].markPoint = {
|
|
|
|
|
+ silent: false,
|
|
|
|
|
+ data: priceMarkPoints,
|
|
|
|
|
+ animation: false
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ priceChart.setOption(priceOption);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 更新BPS图表,添加标记
|
|
|
|
|
+ const bpsOption = bpsChart.getOption();
|
|
|
|
|
+ if (bpsOption.series && bpsOption.series.length > 0) {
|
|
|
|
|
+ // 在第一个系列(Ask BPS)上添加标记
|
|
|
|
|
+ bpsOption.series[0].markLine = {
|
|
|
|
|
+ silent: false,
|
|
|
|
|
+ data: bpsMarkLines,
|
|
|
|
|
+ animation: false
|
|
|
|
|
+ };
|
|
|
|
|
+ bpsOption.series[0].markPoint = {
|
|
|
|
|
+ silent: false,
|
|
|
|
|
+ data: bpsMarkPoints,
|
|
|
|
|
+ animation: false
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ bpsChart.setOption(bpsOption);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 添加点击事件监听
|
|
|
|
|
+ priceChart.off('click'); // 移除旧的监听器
|
|
|
|
|
+ priceChart.on('click', function(params) {
|
|
|
|
|
+ if (params.componentType === 'markPoint' && params.data.eventData) {
|
|
|
|
|
+ showEventDetails(params.data.eventData);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ bpsChart.off('click');
|
|
|
|
|
+ bpsChart.on('click', function(params) {
|
|
|
|
|
+ if (params.componentType === 'markPoint' && params.data.eventData) {
|
|
|
|
|
+ showEventDetails(params.data.eventData);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 显示事件详情
|
|
|
|
|
+ function showEventDetails(event) {
|
|
|
|
|
+ const details = `
|
|
|
|
|
+ <div style="background: white; padding: 20px; border-radius: 10px; box-shadow: 0 4px 20px rgba(0,0,0,0.2); max-width: 500px; margin: 20px auto;">
|
|
|
|
|
+ <h3 style="margin-top: 0; color: #667eea; border-bottom: 2px solid #667eea; padding-bottom: 10px;">
|
|
|
|
|
+ ${getEventIcon(event.event_type)} ${formatEventType(event.event_type)}
|
|
|
|
|
+ </h3>
|
|
|
|
|
+ <table style="width: 100%; border-collapse: collapse;">
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">时间:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${new Date(event.timestamp * 1000).toLocaleString()}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr style="background: #f8f9fa;">
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">交易对:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.symbol || '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">价格:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.price ? event.price.toFixed(6) : '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr style="background: #f8f9fa;">
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">数量:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.quantity || '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">方向:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.side || '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr style="background: #f8f9fa;">
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">策略状态:</td>
|
|
|
|
|
+ <td style="padding: 8px;" class="${getStrategyStateClass(event.strategy_state)}">${event.strategy_state || '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">Ask价差:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.ask_bps ? event.ask_bps.toFixed(2) + ' bps' : '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ <tr style="background: #f8f9fa;">
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">Bid价差:</td>
|
|
|
|
|
+ <td style="padding: 8px;">${event.bid_bps ? event.bid_bps.toFixed(2) + ' bps' : '-'}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ ${event.tx_hash ? `
|
|
|
|
|
+ <tr>
|
|
|
|
|
+ <td style="padding: 8px; font-weight: bold; color: #555;">交易哈希:</td>
|
|
|
|
|
+ <td style="padding: 8px; word-break: break-all; font-size: 12px;">${event.tx_hash}</td>
|
|
|
|
|
+ </tr>
|
|
|
|
|
+ ` : ''}
|
|
|
|
|
+ </table>
|
|
|
|
|
+ <button onclick="closeEventDetails()" style="margin-top: 15px; width: 100%; padding: 10px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; border: none; border-radius: 5px; cursor: pointer; font-weight: bold;">
|
|
|
|
|
+ 关闭
|
|
|
|
|
+ </button>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ `;
|
|
|
|
|
+
|
|
|
|
|
+ // 创建模态框
|
|
|
|
|
+ const modal = document.createElement('div');
|
|
|
|
|
+ modal.id = 'eventDetailsModal';
|
|
|
|
|
+ modal.style.cssText = `
|
|
|
|
|
+ position: fixed;
|
|
|
|
|
+ top: 0;
|
|
|
|
|
+ left: 0;
|
|
|
|
|
+ right: 0;
|
|
|
|
|
+ bottom: 0;
|
|
|
|
|
+ background: rgba(0, 0, 0, 0.5);
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ z-index: 10000;
|
|
|
|
|
+ `;
|
|
|
|
|
+ modal.innerHTML = details;
|
|
|
|
|
+ modal.onclick = function(e) {
|
|
|
|
|
+ if (e.target === modal) {
|
|
|
|
|
+ closeEventDetails();
|
|
|
|
|
+ }
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ document.body.appendChild(modal);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 关闭事件详情
|
|
|
|
|
+ function closeEventDetails() {
|
|
|
|
|
+ const modal = document.getElementById('eventDetailsModal');
|
|
|
|
|
+ if (modal) {
|
|
|
|
|
+ modal.remove();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
// 加载缩略图数据(24小时,只显示币安价格,每秒最多一条)
|
|
// 加载缩略图数据(24小时,只显示币安价格,每秒最多一条)
|
|
|
async function loadThumbnailData(symbol) {
|
|
async function loadThumbnailData(symbol) {
|
|
|
try {
|
|
try {
|
|
@@ -934,12 +1235,17 @@
|
|
|
const params = new URLSearchParams({ hours });
|
|
const params = new URLSearchParams({ hours });
|
|
|
if (symbol) params.append('symbol', symbol);
|
|
if (symbol) params.append('symbol', symbol);
|
|
|
if (currentDbPath) params.append('db_path', currentDbPath);
|
|
if (currentDbPath) params.append('db_path', currentDbPath);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
const response = await fetch(`/api/trading_events?${params}`);
|
|
const response = await fetch(`/api/trading_events?${params}`);
|
|
|
const result = await response.json();
|
|
const result = await response.json();
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (result.success) {
|
|
if (result.success) {
|
|
|
|
|
+ tradingEventsData = result.data; // 保存事件数据
|
|
|
displayTradingEvents(result.data);
|
|
displayTradingEvents(result.data);
|
|
|
|
|
+ // 重新绘制图表以添加事件标记
|
|
|
|
|
+ if (priceChart && bpsChart) {
|
|
|
|
|
+ addEventMarkersToCharts();
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
throw new Error(result.error);
|
|
throw new Error(result.error);
|
|
|
}
|
|
}
|
|
@@ -949,16 +1255,24 @@
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 显示交易事件
|
|
|
|
|
|
|
+ // 显示交易事件 - 简化版,只显示最近10条
|
|
|
function displayTradingEvents(events) {
|
|
function displayTradingEvents(events) {
|
|
|
const eventsContent = document.getElementById('eventsContent');
|
|
const eventsContent = document.getElementById('eventsContent');
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
if (events.length === 0) {
|
|
if (events.length === 0) {
|
|
|
eventsContent.innerHTML = '<div class="loading">暂无交易事件</div>';
|
|
eventsContent.innerHTML = '<div class="loading">暂无交易事件</div>';
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 只显示最近10条
|
|
|
|
|
+ const recentEvents = events.slice(0, 10);
|
|
|
|
|
+ const totalCount = events.length;
|
|
|
|
|
+
|
|
|
const table = `
|
|
const table = `
|
|
|
|
|
+ <div style="margin-bottom: 10px; color: #666;">
|
|
|
|
|
+ <strong>最近10条交易事件</strong> (共 ${totalCount} 条)
|
|
|
|
|
+ ${totalCount > 10 ? `<span style="color: #999;"> - 更多事件请查看图表标记</span>` : ''}
|
|
|
|
|
+ </div>
|
|
|
<table class="events-table">
|
|
<table class="events-table">
|
|
|
<thead>
|
|
<thead>
|
|
|
<tr>
|
|
<tr>
|
|
@@ -975,11 +1289,13 @@
|
|
|
</tr>
|
|
</tr>
|
|
|
</thead>
|
|
</thead>
|
|
|
<tbody>
|
|
<tbody>
|
|
|
- ${events.map(event => `
|
|
|
|
|
|
|
+ ${recentEvents.map(event => `
|
|
|
<tr>
|
|
<tr>
|
|
|
<td>${new Date(event.timestamp * 1000).toLocaleString()}</td>
|
|
<td>${new Date(event.timestamp * 1000).toLocaleString()}</td>
|
|
|
<td>${event.symbol || '-'}</td>
|
|
<td>${event.symbol || '-'}</td>
|
|
|
- <td class="${getEventClass(event.event_type)}">${formatEventType(event.event_type)}</td>
|
|
|
|
|
|
|
+ <td class="${getEventClass(event.event_type)}">
|
|
|
|
|
+ ${getEventIcon(event.event_type)} ${formatEventType(event.event_type)}
|
|
|
|
|
+ </td>
|
|
|
<td>${event.price ? event.price.toFixed(6) : '-'}</td>
|
|
<td>${event.price ? event.price.toFixed(6) : '-'}</td>
|
|
|
<td>${event.quantity || '-'}</td>
|
|
<td>${event.quantity || '-'}</td>
|
|
|
<td>${event.side || '-'}</td>
|
|
<td>${event.side || '-'}</td>
|
|
@@ -989,8 +1305,8 @@
|
|
|
<td>${event.ask_bps ? event.ask_bps.toFixed(2) : '-'}</td>
|
|
<td>${event.ask_bps ? event.ask_bps.toFixed(2) : '-'}</td>
|
|
|
<td>${event.bid_bps ? event.bid_bps.toFixed(2) : '-'}</td>
|
|
<td>${event.bid_bps ? event.bid_bps.toFixed(2) : '-'}</td>
|
|
|
<td>
|
|
<td>
|
|
|
- ${event.tx_hash ?
|
|
|
|
|
- `<a href="#" title="${event.tx_hash}">${event.tx_hash.substring(0, 10)}...</a>` :
|
|
|
|
|
|
|
+ ${event.tx_hash ?
|
|
|
|
|
+ `<a href="#" title="${event.tx_hash}">${event.tx_hash.substring(0, 10)}...</a>` :
|
|
|
'-'
|
|
'-'
|
|
|
}
|
|
}
|
|
|
</td>
|
|
</td>
|
|
@@ -999,7 +1315,7 @@
|
|
|
</tbody>
|
|
</tbody>
|
|
|
</table>
|
|
</table>
|
|
|
`;
|
|
`;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
eventsContent.innerHTML = table;
|
|
eventsContent.innerHTML = table;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -1009,6 +1325,17 @@
|
|
|
if (eventType.includes('close')) return 'event-close';
|
|
if (eventType.includes('close')) return 'event-close';
|
|
|
return '';
|
|
return '';
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 获取事件图标
|
|
|
|
|
+ function getEventIcon(eventType) {
|
|
|
|
|
+ if (eventType.includes('open_long')) return '📈';
|
|
|
|
|
+ if (eventType.includes('open_short')) return '📉';
|
|
|
|
|
+ if (eventType.includes('close_long')) return '🔼';
|
|
|
|
|
+ if (eventType.includes('close_short')) return '🔽';
|
|
|
|
|
+ if (eventType.includes('open')) return '🟢';
|
|
|
|
|
+ if (eventType.includes('close')) return '🔴';
|
|
|
|
|
+ return '⚪';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 获取策略状态的CSS类
|
|
// 获取策略状态的CSS类
|
|
|
function getStrategyStateClass(state) {
|
|
function getStrategyStateClass(state) {
|
|
@@ -1156,9 +1483,16 @@
|
|
|
displayPriceChart(filteredData);
|
|
displayPriceChart(filteredData);
|
|
|
// 更新BPS图表
|
|
// 更新BPS图表
|
|
|
displayBpsChart(filteredData);
|
|
displayBpsChart(filteredData);
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
// 更新时间范围显示
|
|
// 更新时间范围显示
|
|
|
updateTimeRangeDisplay();
|
|
updateTimeRangeDisplay();
|
|
|
|
|
+
|
|
|
|
|
+ // 重新添加事件标记
|
|
|
|
|
+ if (tradingEventsData && tradingEventsData.length > 0) {
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ addEventMarkersToCharts();
|
|
|
|
|
+ }, 200);
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
console.log('过滤后没有数据');
|
|
console.log('过滤后没有数据');
|
|
|
}
|
|
}
|