add fx strentth

This commit is contained in:
jackyu66git
2025-05-23 21:19:50 +08:00
parent a1e033432b
commit a9d24233b0
14 changed files with 2067 additions and 399 deletions
+289 -124
View File
@@ -2612,9 +2612,44 @@
const timeStr = param.time;
const markers = [...buyMarkers, ...sellMarkers].filter(m => m.time === timeStr);
if (markers.length > 0) {
// 有买卖点标记,显示自定义提示
const tooltips = markers.map(m => m.tooltip).join('<br>');
// 同时检查分型标记
const fxMarkers = (window.fxMarkers || []).filter(m => m.time === timeStr);
const allMarkers = [...markers, ...fxMarkers];
// 显示时区调试信息
if (window.debugMode) {
const timezone = $('#timezone').val();
const formattedTime = formatTimeWithTimezone(timeStr * 1000, timezone);
// 获取当前价格 - 通过param.seriesPrices获取
let priceInfo = '';
if (param.seriesPrices && param.seriesPrices.size > 0) {
// 尝试从蜡烛图系列获取价格
if (tvWidget.series.candleSeries && param.seriesPrices.get(tvWidget.series.candleSeries)) {
const price = param.seriesPrices.get(tvWidget.series.candleSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
}
// 如果没有蜡烛图系列价格,尝试从线图系列获取
else if (tvWidget.series.lineSeries && param.seriesPrices.get(tvWidget.series.lineSeries)) {
const price = param.seriesPrices.get(tvWidget.series.lineSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
}
}
// 仅记录最简短的调试信息
console.debug(`十字线: ${timeStr} -> ${formattedTime} (${timezone})`);
// 显示自定义时区工具提示,包含价格信息
crosshairTooltip.innerHTML = `<div style="font-weight:bold">时间: ${formattedTime}</div>` +
(priceInfo ? `<div>${priceInfo}</div>` : '');
crosshairTooltip.style.display = 'block';
crosshairTooltip.style.left = (param.point.x + 15) + 'px';
crosshairTooltip.style.top = (param.point.y - 30) + 'px';
}
if (allMarkers.length > 0) {
// 有买卖点或分型标记,显示自定义提示
const tooltips = allMarkers.map(m => m.tooltip).join('<br><hr style="margin: 5px 0;">');
tooltipElement.innerHTML = tooltips;
tooltipElement.style.display = 'block';
tooltipElement.style.left = (param.point.x + 15) + 'px';
@@ -2626,28 +2661,53 @@
} else {
// 隐藏提示
tooltipElement.style.display = 'none';
crosshairTooltip.style.display = 'none';
}
});
// 处理图表缩放、平移等事件,隐藏提示
mainChart.timeScale().subscribeVisibleTimeRangeChange(() => {
tooltipElement.style.display = 'none';
crosshairTooltip.style.display = 'none';
});
}
} else {
console.log('绘制买卖点 - 已禁用');
}
// 显示分型类型标签
// 绘制分型类型标签
console.log('=== 开始检查分型显示条件 ===');
console.log('showKlcFxType勾选状态:', $('#showKlcFxType').is(':checked'));
console.log('currentData.klc_fx_info存在:', !!currentData.klc_fx_info);
console.log('currentData.klc_fx_info长度:', currentData.klc_fx_info ? currentData.klc_fx_info.length : 'undefined');
if (currentData.klc_fx_info && currentData.klc_fx_info.length > 0) {
console.log('前3个分型数据样本:', currentData.klc_fx_info.slice(0, 3));
}
if ($('#showKlcFxType').is(':checked') && currentData.klc_fx_info && currentData.klc_fx_info.length > 0) {
console.log(`绘制K线分型类型标签,共${currentData.klc_fx_info.length}`);
// 收集所有分型标记
const allFxMarkers = [];
// 存储分型标记,用于tooltip功能
const fxMarkers = [];
currentData.klc_fx_info.forEach(function(fx) {
try {
// 直接使用UTC时间戳(秒)
const timestamp = Math.floor(new Date(fx.time).getTime() / 1000);
const price = parseFloat(fx.price);
// 添加时间和价格调试信息
console.log('处理分型:', {
原始时间: fx.time,
转换时间戳: timestamp,
原始价格: fx.price,
转换价格: price,
时间有效: !isNaN(timestamp),
价格有效: !isNaN(price)
});
if (isNaN(timestamp) || isNaN(price)) {
console.error('分型类型时间或价格转换错误:', fx.time, fx.price);
return;
@@ -2656,47 +2716,92 @@
// 确定颜色和位置
const color = fx.is_bottom ? '#28a745' : '#dc3545'; // 底分型绿色,顶分型红色
// 创建标记系列
const markerSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
// 根据强度等级调整颜色强度
let strengthColor = color;
if (fx.is_strong_fx) {
// 强分型使用更亮的颜色
strengthColor = fx.is_bottom ? '#00ff00' : '#ff0000';
}
// 构建显示文本,包含分型类型和强度信息
// 添加调试信息
console.log('分型数据:', {
fx_type: fx.fx_type,
fx_strength: fx.fx_strength,
fx_strength_level: fx.fx_strength_level,
is_strong_fx: fx.is_strong_fx
});
// 设置文本标记
markerSeries.setMarkers([
{
time: timestamp,
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
color: color,
shape: 'circle',
text: fx.fx_type,
size: 1
}
]);
const displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`;
console.log('显示文本:', displayText);
// 可选:添加更加明显的文本标签
const textSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
});
// 添加标记配置调试
const markerConfig = {
time: timestamp,
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
color: strengthColor,
shape: fx.is_strong_fx ? 'square' : 'circle',
text: displayText,
size: fx.is_strong_fx ? 2 : 1
};
console.log('标记配置:', markerConfig);
textSeries.setData([{
time: timestamp,
value: price + (fx.is_bottom ? -0.0005 * price : 0.0005 * price) // 小偏移,避免遮挡
}]);
// 添加到标记数组
allFxMarkers.push(markerConfig);
// 创建分型标记对象,包含tooltip信息
const fxMarker = {
time: timestamp,
tooltip: `<div style="color: ${strengthColor}; font-weight: bold;">
${fx.is_bottom ? '底分型' : '顶分型'}: ${fx.fx_type}<br>
强度分数: ${fx.fx_strength}分<br>
强度等级: ${fx.fx_strength_level}<br>
是否强分型: ${fx.is_strong_fx ? '是' : '否'}<br>
价格: ${price.toFixed(4)}<br>
时间: ${fx.time}
</div>`
};
// 添加到分型标记数组
fxMarkers.push(fxMarker);
} catch (e) {
console.error('绘制分型类型标签出错:', e);
}
});
// 一次性设置所有分型标记到主数据系列
if (allFxMarkers.length > 0) {
console.log('一次性设置', allFxMarkers.length, '个分型标记');
// 暂存主周期分型标记,等待与小周期合并
window.mainFxMarkers = allFxMarkers;
} else {
window.mainFxMarkers = [];
}
// 将分型标记添加到全局markers中以支持tooltip功能
if (window.fxMarkers) {
window.fxMarkers = [...window.fxMarkers, ...fxMarkers];
} else {
window.fxMarkers = fxMarkers;
}
} else {
console.log('绘制分型类型标签 - 已禁用或无数据');
// 清空分型标记
window.fxMarkers = [];
window.mainFxMarkers = [];
}
// 绘制小周期分型标记
if ($('#showElementKlcFxType').is(':checked') && currentData.element_klc_fx_info && currentData.element_klc_fx_info.length > 0) {
console.log(`绘制小周期分型标记,共${currentData.element_klc_fx_info.length}`);
// 收集所有小周期分型标记
const allElementFxMarkers = [];
const elementFxMarkers = []; // 用于tooltip支持
currentData.element_klc_fx_info.forEach(function(fx) {
try {
// 直接使用UTC时间戳(秒)
@@ -2708,49 +2813,92 @@
return;
}
// 小周期分型使用红色标记,不同于主周期分
const redColor = '#FF0000'; // 红色
// 小周期分型使用不同的颜色和样式,与主周期
let strengthColor = fx.is_bottom ? '#FF6B6B' : '#4ECDC4'; // 底分型用珊瑚红,顶分型用薄荷绿
if (fx.is_strong_fx) {
// 强分型使用更亮的颜色
strengthColor = fx.is_bottom ? '#FF0000' : '#00CED1';
}
// 创建标记系列
const markerSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
});
// 构建小周期分型显示文本
const displayText = `${fx.fx_strength_level} ${fx.fx_strength.toFixed(1)}`;
// 设置文本标记
markerSeries.setMarkers([
{
time: timestamp,
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
color: redColor,
shape: 'arrowUp', // 使用箭头形状,与主周期分型区分
text: fx.is_bottom ? '↓' : '↑', // 显示箭头
size: 1
}
]);
// 小周期分型标记配置 - 根据分型类型使用正确的箭头形状
const markerConfig = {
time: timestamp,
position: fx.is_bottom ? 'belowBar' : 'aboveBar',
color: strengthColor,
shape: fx.is_bottom ? 'arrowUp' : 'arrowDown', // 底分型向上箭头,顶分型向下箭头
text: displayText,
size: fx.is_strong_fx ? 2 : 1
};
// 为小周期分型添加明显的箭头标记
const arrowSeries = mainChart.addLineSeries({
lastValueVisible: false,
priceLineVisible: false,
lineWidth: 1,
color: redColor
});
console.log('小周期分型标记配置:', markerConfig);
allElementFxMarkers.push(markerConfig);
// 计算标记位置,底分型在价格下方,顶分型在价格上方
const offset = fx.is_bottom ? -0.001 * price : 0.001 * price;
// 创建小周期分型标记对象,包含tooltip信息
const elementFxMarker = {
time: timestamp,
tooltip: `<div style="color: ${strengthColor}; font-weight: bold;">
小周期${fx.is_bottom ? '底分型' : '顶分型'}: ${fx.fx_type}<br>
强度分数: ${fx.fx_strength}分<br>
强度等级: ${fx.fx_strength_level}<br>
是否强分型: ${fx.is_strong_fx ? '是' : '否'}<br>
价格: ${price.toFixed(4)}<br>
时间: ${fx.time}
</div>`
};
arrowSeries.setData([{
time: timestamp,
value: price + offset
}]);
// 添加到小周期分型标记数组
elementFxMarkers.push(elementFxMarker);
} catch (e) {
console.error('绘制小周期分型标记出错:', e);
}
});
// 将小周期分型标记添加到全局markers中以支持tooltip功能
if (window.fxMarkers) {
window.fxMarkers = [...window.fxMarkers, ...elementFxMarkers];
} else {
window.fxMarkers = elementFxMarkers;
}
// 合并主周期和小周期分型标记,统一设置到K线数据系列
const combinedMarkers = [...(window.mainFxMarkers || []), ...allElementFxMarkers];
if (combinedMarkers.length > 0) {
console.log('合并设置', combinedMarkers.length, '个分型标记(主周期:', (window.mainFxMarkers || []).length, '个,小周期:', allElementFxMarkers.length, '个)');
// 尝试在K线系列上设置合并后的标记
if (showOriginalKline && tvWidget.series.candleSeries) {
tvWidget.series.candleSeries.setMarkers(combinedMarkers);
console.log('合并标记已设置到蜡烛图系列');
} else if (!showOriginalKline && tvWidget.series.lineSeries) {
tvWidget.series.lineSeries.setMarkers(combinedMarkers);
console.log('合并标记已设置到线图系列');
} else {
console.log('未找到主数据系列,无法设置标记');
}
}
} else {
console.log('绘制小周期分型标记 - 已禁用或无数据');
// 只设置主周期分型标记
if (window.mainFxMarkers && window.mainFxMarkers.length > 0) {
console.log('仅设置', window.mainFxMarkers.length, '个主周期分型标记');
// 尝试在K线系列上设置标记
if (showOriginalKline && tvWidget.series.candleSeries) {
tvWidget.series.candleSeries.setMarkers(window.mainFxMarkers);
console.log('主周期标记已设置到蜡烛图系列');
} else if (!showOriginalKline && tvWidget.series.lineSeries) {
tvWidget.series.lineSeries.setMarkers(window.mainFxMarkers);
console.log('主周期标记已设置到线图系列');
} else {
console.log('未找到主数据系列,无法设置标记');
}
}
}
// 调整所有图表以适应数据
@@ -2767,13 +2915,13 @@
tvWidget.state.isInitialized = true;
// 绑定同步事件
bindSyncEvents();
bindSyncEvents(mainChartContainer, volumeChartContainer, macdChartContainer, mainChart, volumeChart, macdChart, showMacd);
// 设置图表默认时间范围
setDefaultTimeRange();
// 添加买卖点提示
setupTooltip();
setupTooltip(mainChart);
// 显示买卖点
if ($('#showTradePoints').is(':checked')) {
@@ -2932,7 +3080,10 @@
}
}
function bindSyncEvents() {
function bindSyncEvents(mainChartContainer, volumeChartContainer, macdChartContainer, mainChart, volumeChart, macdChart, showMacd) {
// 防止同步过程中的无限循环
let syncInProgress = false;
// 同步图表的时间范围
function syncCharts(sourceChart, sourceContainer) {
// 防止无限循环
@@ -2989,9 +3140,13 @@
};
// 添加事件监听
addChartSyncEvents(mainChartContainer, mainChart);
addChartSyncEvents(volumeChartContainer, volumeChart);
if (showMacd && macdChart) {
if (mainChartContainer && mainChart) {
addChartSyncEvents(mainChartContainer, mainChart);
}
if (volumeChartContainer && volumeChart) {
addChartSyncEvents(volumeChartContainer, volumeChart);
}
if (showMacd && macdChartContainer && macdChart) {
addChartSyncEvents(macdChartContainer, macdChart);
}
@@ -3003,19 +3158,23 @@
// 窗口大小变化时重绘图表
window.addEventListener('resize', () => {
// 调整主图大小
mainChart.applyOptions({
width: mainChartContainer.clientWidth,
height: mainChartContainer.clientHeight
});
if (mainChart && mainChartContainer) {
mainChart.applyOptions({
width: mainChartContainer.clientWidth,
height: mainChartContainer.clientHeight
});
}
// 调整成交量图大小
volumeChart.applyOptions({
width: volumeChartContainer.clientWidth,
height: volumeChartContainer.clientHeight
});
if (volumeChart && volumeChartContainer) {
volumeChart.applyOptions({
width: volumeChartContainer.clientWidth,
height: volumeChartContainer.clientHeight
});
}
// 调整MACD图大小
if (showMacd && macdChart) {
if (showMacd && macdChart && macdChartContainer) {
macdChart.applyOptions({
width: macdChartContainer.clientWidth,
height: macdChartContainer.clientHeight
@@ -3027,7 +3186,7 @@
});
}
function setupTooltip() {
function setupTooltip(mainChart, buyMarkers = [], sellMarkers = []) {
// 调试变量
window.debugMode = true;
@@ -3051,65 +3210,71 @@
document.body.appendChild(crosshairTooltip);
// 添加鼠标悬停事件显示提示
mainChart.subscribeCrosshairMove(param => {
if (param.time && param.point) {
const timeStr = param.time;
const markers = [...buyMarkers, ...sellMarkers].filter(m => m.time === timeStr);
// 显示时区调试信息
if (window.debugMode) {
const timezone = $('#timezone').val();
const formattedTime = formatTimeWithTimezone(timeStr * 1000, timezone);
if (mainChart) {
mainChart.subscribeCrosshairMove(param => {
if (param.time && param.point) {
const timeStr = param.time;
const markers = [...buyMarkers, ...sellMarkers].filter(m => m.time === timeStr);
// 获取当前价格 - 通过param.seriesPrices获取
let priceInfo = '';
if (param.seriesPrices && param.seriesPrices.size > 0) {
// 尝试从蜡烛图系列获取价格
if (tvWidget.series.candleSeries && param.seriesPrices.get(tvWidget.series.candleSeries)) {
const price = param.seriesPrices.get(tvWidget.series.candleSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
}
// 如果没有蜡烛图系列价格,尝试从线图系列获取
else if (tvWidget.series.lineSeries && param.seriesPrices.get(tvWidget.series.lineSeries)) {
const price = param.seriesPrices.get(tvWidget.series.lineSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
// 同时检查分型标记
const fxMarkers = (window.fxMarkers || []).filter(m => m.time === timeStr);
const allMarkers = [...markers, ...fxMarkers];
// 显示时区调试信息
if (window.debugMode) {
const timezone = $('#timezone').val();
const formattedTime = formatTimeWithTimezone(timeStr * 1000, timezone);
// 获取当前价格 - 通过param.seriesPrices获取
let priceInfo = '';
if (param.seriesPrices && param.seriesPrices.size > 0) {
// 尝试从蜡烛图系列获取价格
if (tvWidget.series.candleSeries && param.seriesPrices.get(tvWidget.series.candleSeries)) {
const price = param.seriesPrices.get(tvWidget.series.candleSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
}
// 如果没有蜡烛图系列价格,尝试从线图系列获取
else if (tvWidget.series.lineSeries && param.seriesPrices.get(tvWidget.series.lineSeries)) {
const price = param.seriesPrices.get(tvWidget.series.lineSeries);
priceInfo = `价格: ${price.toFixed(2)}`;
}
}
// 仅记录最简短的调试信息
console.debug(`十字线: ${timeStr} -> ${formattedTime} (${timezone})`);
// 显示自定义时区工具提示,包含价格信息
crosshairTooltip.innerHTML = `<div style="font-weight:bold">时间: ${formattedTime}</div>` +
(priceInfo ? `<div>${priceInfo}</div>` : '');
crosshairTooltip.style.display = 'block';
crosshairTooltip.style.left = (param.point.x + 15) + 'px';
crosshairTooltip.style.top = (param.point.y - 30) + 'px';
}
// 仅记录最简短的调试信息
console.debug(`十字线: ${timeStr} -> ${formattedTime} (${timezone})`);
// 显示自定义时区工具提示,包含价格信息
crosshairTooltip.innerHTML = `<div style="font-weight:bold">时间: ${formattedTime}</div>` +
(priceInfo ? `<div>${priceInfo}</div>` : '');
crosshairTooltip.style.display = 'block';
crosshairTooltip.style.left = (param.point.x + 15) + 'px';
crosshairTooltip.style.top = (param.point.y - 30) + 'px';
}
if (markers.length > 0) {
// 有买卖点标记,显示自定义提示
const tooltips = markers.map(m => m.tooltip).join('<br>');
tooltipElement.innerHTML = tooltips;
tooltipElement.style.display = 'block';
tooltipElement.style.left = (param.point.x + 15) + 'px';
tooltipElement.style.top = (param.point.y + 15) + 'px';
if (allMarkers.length > 0) {
// 有买卖点或分型标记,显示自定义提示
const tooltips = allMarkers.map(m => m.tooltip).join('<br><hr style="margin: 5px 0;">');
tooltipElement.innerHTML = tooltips;
tooltipElement.style.display = 'block';
tooltipElement.style.left = (param.point.x + 15) + 'px';
tooltipElement.style.top = (param.point.y + 15) + 'px';
} else {
// 隐藏提示
tooltipElement.style.display = 'none';
}
} else {
// 隐藏提示
tooltipElement.style.display = 'none';
crosshairTooltip.style.display = 'none';
}
} else {
// 隐藏提示
});
// 处理图表缩放、平移等事件,隐藏提示
mainChart.timeScale().subscribeVisibleTimeRangeChange(() => {
tooltipElement.style.display = 'none';
crosshairTooltip.style.display = 'none';
}
});
// 处理图表缩放、平移等事件,隐藏提示
mainChart.timeScale().subscribeVisibleTimeRangeChange(() => {
tooltipElement.style.display = 'none';
crosshairTooltip.style.display = 'none';
});
});
}
}
// 辅助函数:使用指定时区格式化时间戳