添加动能理论,修改klc整体显示

This commit is contained in:
jackyu66git
2026-04-10 13:01:07 +08:00
parent 957ef62407
commit 7815eada00
5 changed files with 124 additions and 91 deletions
+70 -89
View File
@@ -2049,72 +2049,24 @@
const periodChanged = (curPeriod !== _lastKlinePeriod);
_lastKlinePeriod = curPeriod;
// 保存当前的可见逻辑范围(周期切换时不保留,避免范围越界)
let logicalRange = null;
let visibleRange = null;
// 保存当前的可见范围(周期切换时不保留,避免范围越界)
if (!periodChanged && tvWidget && tvWidget.mainChart) {
logicalRange = tvWidget.mainChart.timeScale().getVisibleLogicalRange();
visibleRange = tvWidget.mainChart.timeScale().getVisibleRange();
try {
const ts = tvWidget.mainChart.timeScale();
window._pendingRestoreView = {
barSpacing: ts.options().barSpacing,
scrollPosition: ts.scrollPosition(),
rightOffset: ts.options().rightOffset
};
} catch (e) {
window._pendingRestoreView = null;
}
}
console.log('更新图表显示');
console.log('BI中枢输入状态:', {
main: $('#showMainBiZs').is(':checked'),
element: $('#showElementBiZs').is(':checked')
});
console.log('- 显示K线:', $('#showOriginalKline').is(':checked'));
console.log('- 显示笔:', $('#showMainBi').is(':checked'));
console.log('- 显示线段:', $('#showMainSeg').is(':checked'));
console.log('- 显示中枢:', $('#showMainZs').is(':checked'));
console.log('- 显示BI中枢(主):', $('#showMainBiZs').is(':checked'));
console.log('- 显示BI中枢(次):', $('#showElementBiZs').is(':checked'));
console.log('- 显示MACD:', true);
console.log('- 显示成交量:', false);
console.log('- 显示分型类型:', $('#showKlcFxType').is(':checked'));
console.log('- 显示小周期分型:', $('#showElementKlcFxType').is(':checked'));
console.log('- 显示KLU分型:', $('#showKluFxType').is(':checked'));
console.log('- 显示小周期KLU分型:', $('#showElementKluFxType').is(':checked'));
console.log('- 显示买卖点:', $('#showTradePoints').is(':checked'));
console.log('- 显示原始K线:', $('#showOriginalKline').is(':checked'));
console.log('- 显示主周期布林带:', $('#showMainBollinger').is(':checked'));
console.log('- 显示次周期布林带:', $('#showElementBollinger').is(':checked'));
// 重新初始化图表,这将清除旧图形并重新绘制
// 重新初始化图表initTradingView 内部会在最终同步时读取 _pendingRestoreView
initTradingView($('#symbol').val(), $('#timeframe').val());
// 如果有保存的范围,恢复它
setTimeout(() => {
if (tvWidget) {
if (logicalRange) {
// 应用保存的逻辑范围到所有图表
tvWidget.mainChart.timeScale().setVisibleLogicalRange(logicalRange);
tvWidget.volumeChart.timeScale().setVisibleLogicalRange(logicalRange);
if (tvWidget.atrChart) {
tvWidget.atrChart.timeScale().setVisibleLogicalRange(logicalRange);
}
if (tvWidget.macdChart) {
tvWidget.macdChart.timeScale().setVisibleLogicalRange(logicalRange);
}
if (tvWidget.chanMacdChart) {
tvWidget.chanMacdChart.timeScale().setVisibleLogicalRange(logicalRange);
}
} else if (visibleRange) {
// 如果没有逻辑范围,使用时间戳范围
tvWidget.mainChart.timeScale().setVisibleRange(visibleRange);
tvWidget.volumeChart.timeScale().setVisibleRange(visibleRange);
if (tvWidget.atrChart) {
tvWidget.atrChart.timeScale().setVisibleRange(visibleRange);
}
if (tvWidget.macdChart) {
tvWidget.macdChart.timeScale().setVisibleRange(visibleRange);
}
if (tvWidget.chanMacdChart) {
tvWidget.chanMacdChart.timeScale().setVisibleRange(visibleRange);
}
}
}
}, 100);
}
}
// 确保所有时间处理都使用UTC时间,包括表格数据显示
@@ -6742,11 +6694,11 @@
}
const defaultMAs = [
{ type: 'EMA', length: 52, color: '#800080', name: 'EMA52' }, // 紫色
{ type: 'EMA', length: 26, color: '#008000', name: 'EMA26' }, // 深绿
{ type: 'EMA', length: 104, color: '#FF8C00', name: 'EMA104' }, // 橙色
{ type: 'EMA', length: 156, color: '#1E90FF', name: 'EMA156' }, // 蓝色
{ type: 'EMA', length: 208, color: '#1F004F', name: 'EMA312' } //
{ type: 'EMA', length: 13, color: '#800080', name: 'EMA13', visible: true }, // 紫色
{ type: 'EMA', length: 26, color: '#000000', name: 'EMA26', visible: true }, //
{ type: 'EMA', length: 52, color: '#FF8C00', name: 'EMA52', visible: false }, // 橙色
{ type: 'EMA', length: 104, color: '#1E90FF', name: 'EMA104', visible: false }, // 蓝色
{ type: 'EMA', length: 156, color: '#F700FF', name: 'EMA156', visible: false } //
];
defaultMAs.forEach(ma => {
@@ -6760,7 +6712,7 @@
lineWidth: 1, // 1px线宽
lineStyle: 0, // 实线
color: ma.color,
visible: true
visible: ma.visible
};
movingAverages.push(config);
@@ -6775,7 +6727,7 @@
upperMultiplier: 2,
lowerMultiplier: 2,
source: 'close',
lineWidth: 2,
lineWidth: 1,
lineStyle: 0,
upperColor: '#ff6b6b',
middleColor: '#ffffff',
@@ -6802,24 +6754,39 @@
// 绑定同步事件
bindSyncEvents(mainChartContainer, volumeChartContainer, atrChartContainer, macdChartContainer, chanMacdChartContainer, mainChart, volumeChart, atrChart, macdChart, chanMacdChart, showMacd);
// 最终确保所有图表时间轴对齐
// 最终确保所有图表时间轴对齐(同时恢复刷新前保存的缩放/位置)
setTimeout(() => {
const visibleRange = mainChart.timeScale().getVisibleRange();
if (visibleRange) {
console.log('🔧 最终同步可见范围:', visibleRange);
// 强制重新设置所有图表的可见范围
volumeChart.timeScale().setVisibleRange(visibleRange);
atrChart.timeScale().setVisibleRange(visibleRange);
if (showMacd && macdChart) {
macdChart.timeScale().setVisibleRange(visibleRange);
const allCharts = [mainChart, volumeChart, atrChart];
if (showMacd && macdChart) allCharts.push(macdChart);
if (showMacd && chanMacdChart) allCharts.push(chanMacdChart);
// 检查是否有待恢复的视图(barSpacing + scrollPosition
const pending = window._pendingRestoreView;
window._pendingRestoreView = null;
if (pending && pending.barSpacing) {
// 恢复刷新前的缩放和滚动位置
console.log('📌 恢复图表视图 - barSpacing:', pending.barSpacing, 'scrollPosition:', pending.scrollPosition);
allCharts.forEach(c => {
try {
c.timeScale().applyOptions({ barSpacing: pending.barSpacing });
c.timeScale().scrollToPosition(pending.scrollPosition, false);
} catch(e) {}
});
} else {
// 无保存视图,正常同步主图到子图
const visibleRange = mainChart.timeScale().getVisibleRange();
if (visibleRange) {
console.log('🔧 最终同步可见范围:', visibleRange);
[volumeChart, atrChart].concat(
showMacd && macdChart ? [macdChart] : [],
showMacd && chanMacdChart ? [chanMacdChart] : []
).forEach(c => {
try { c.timeScale().setVisibleRange(visibleRange); } catch(e) {}
});
}
if (showMacd && chanMacdChart) {
chanMacdChart.timeScale().setVisibleRange(visibleRange);
}
console.log('🔧 最终时间轴对齐完成');
}
console.log('🔧 最终时间轴对齐完成');
}, 150);
// 只有在时间输入框都为空时才设置图表默认时间范围
if (!$('#start_time').val() && !$('#end_time').val()) {
@@ -8410,14 +8377,28 @@
$('#elementTimeframe').val(data.element_timeframe);
}
// 保存当前缩放(barSpacing)和滚动位置(scrollPosition)到 window
// tvWidget 会在 initTradingView 内被重建,所以必须存到 window 上
if (tvWidget && tvWidget.mainChart) {
try {
const ts = tvWidget.mainChart.timeScale();
window._pendingRestoreView = {
barSpacing: ts.options().barSpacing,
scrollPosition: ts.scrollPosition(),
rightOffset: ts.options().rightOffset
};
console.log('📌 保存图表视图:', JSON.stringify(window._pendingRestoreView));
} catch (e) {
console.warn('保存图表视图失败:', e);
window._pendingRestoreView = null;
}
}
initTradingView($('#symbol').val(), $('#timeframe').val());
// 更新表格数据
updateTables(data);
// 只有在图表已初始化且调用了updateTradingViewData时才不需要重复调用EMA52显示
// 如果图表未初始化,调用了initTradingView,那么EMA52显示已经在initTradingView中处理了
// 但为了确保在所有情况下都能正确显示,这里统一调用一次
if (currentData && currentData.ema52_dict) {
updateEMA52Display(currentData);
}
@@ -10574,13 +10555,13 @@
<div class="macd-config-form">
<div class="macd-config-group">
<label class="macd-config-label">快线周期 (Fast)</label>
<input type="number" id="macdFastPeriod" class="macd-config-input" value="24" min="2" max="200">
<div class="macd-config-hint">默认: 24 (12×2)</div>
<input type="number" id="macdFastPeriod" class="macd-config-input" value="13" min="2" max="200">
<div class="macd-config-hint">默认: 13</div>
</div>
<div class="macd-config-group">
<label class="macd-config-label">慢线周期 (Slow)</label>
<input type="number" id="macdSlowPeriod" class="macd-config-input" value="52" min="2" max="500">
<div class="macd-config-hint">默认: 52 (26×2)</div>
<input type="number" id="macdSlowPeriod" class="macd-config-input" value="26" min="2" max="500">
<div class="macd-config-hint">默认: 26</div>
</div>
<div class="macd-config-group">
<label class="macd-config-label">信号线周期 (Signal)</label>