fix: 修复主站自动刷新内存泄漏,并完善 chan_tv 图表体验

主站重建前完整 dispose、去掉重复 sync 监听,自动刷新默认增量更新;顺带消除首屏重复 analyze、复用 ChanMACD,以及全版 TV 指标/未完成中枢/布局本地缓存。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jackyu66git
2026-08-06 16:09:48 +08:00
co-authored by Cursor
parent 6b0f3b5837
commit 9f1e7361b6
14 changed files with 457 additions and 669 deletions
+56 -5
View File
@@ -121,6 +121,7 @@
}
// 中枢填充:区间内每根 bar 写入 top/bottom
// 未完成中枢:右边界拉到最新 K(与主站 uncompleted_zs 一致)
function fillZs(t0, t1, high, low, topField, botField) {
var lo = lowerBound(sortedBarTimes, t0)
var hi = upperBound(sortedBarTimes, t1)
@@ -131,14 +132,30 @@
}
}
var lastBarT = sortedBarTimes.length ? sortedBarTimes[sortedBarTimes.length - 1] : null
if (slice.zs) {
slice.zs.forEach(function (z) {
fillZs(z.t0, z.t1, z.high || z.zg, z.low || z.zd, 'zs_top', 'zs_bottom')
var t1 = z.t1
var sure = z.is_sure !== false && z.is_sure !== 0
if (!sure && lastBarT != null) t1 = Math.max(t1 || 0, lastBarT)
if (sure) {
fillZs(z.t0, t1, z.high || z.zg, z.low || z.zd, 'zs_top', 'zs_bottom')
} else {
fillZs(z.t0, t1, z.high || z.zg, z.low || z.zd, 'zs_pending_top', 'zs_pending_bottom')
}
})
}
if (slice.segzs) {
slice.segzs.forEach(function (z) {
fillZs(z.t0, z.t1, z.high || z.zg, z.low || z.zd, 'segzs_top', 'segzs_bottom')
var t1 = z.t1
var sure = z.is_sure !== false && z.is_sure !== 0
if (!sure && lastBarT != null) t1 = Math.max(t1 || 0, lastBarT)
if (sure) {
fillZs(z.t0, t1, z.high || z.zg, z.low || z.zd, 'segzs_top', 'segzs_bottom')
} else {
fillZs(z.t0, t1, z.high || z.zg, z.low || z.zd, 'segzs_pending_top', 'segzs_pending_bottom')
}
})
}
@@ -233,6 +250,10 @@
{ id: 'zs_bottom', type: 'line' },
{ id: 'segzs_top', type: 'line' },
{ id: 'segzs_bottom', type: 'line' },
{ id: 'zs_pending_top', type: 'line' },
{ id: 'zs_pending_bottom', type: 'line' },
{ id: 'segzs_pending_top', type: 'line' },
{ id: 'segzs_pending_bottom', type: 'line' },
]
BSP_SUBTYPES.forEach(function (t) {
@@ -279,6 +300,22 @@
linestyle: 0, linewidth: 0, plottype: 0, trackPrice: false,
transparency: 100, visible: false, color: '#ef6c00', display: 0,
}),
zs_pending_top: mergeStyle('zs_pending_top', {
linestyle: 0, linewidth: 0, plottype: 0, trackPrice: false,
transparency: 100, visible: false, color: '#f1c40f', display: 0,
}),
zs_pending_bottom: mergeStyle('zs_pending_bottom', {
linestyle: 0, linewidth: 0, plottype: 0, trackPrice: false,
transparency: 100, visible: false, color: '#f1c40f', display: 0,
}),
segzs_pending_top: mergeStyle('segzs_pending_top', {
linestyle: 0, linewidth: 0, plottype: 0, trackPrice: false,
transparency: 100, visible: false, color: '#9b59b6', display: 0,
}),
segzs_pending_bottom: mergeStyle('segzs_pending_bottom', {
linestyle: 0, linewidth: 0, plottype: 0, trackPrice: false,
transparency: 100, visible: false, color: '#9b59b6', display: 0,
}),
}
// BSP 样式
@@ -311,6 +348,10 @@
zs_bottom: { title: '中枢下沿', histogramBase: 0, isHidden: true },
segzs_top: { title: '段中枢上沿', histogramBase: 0, isHidden: true },
segzs_bottom: { title: '段中枢下沿', histogramBase: 0, isHidden: true },
zs_pending_top: { title: '未完成中枢上沿', histogramBase: 0, isHidden: true },
zs_pending_bottom: { title: '未完成中枢下沿', histogramBase: 0, isHidden: true },
segzs_pending_top: { title: '未完成段中枢上沿', histogramBase: 0, isHidden: true },
segzs_pending_bottom: { title: '未完成段中枢下沿', histogramBase: 0, isHidden: true },
}
BSP_SUBTYPES.forEach(function (t) {
@@ -358,7 +399,7 @@
name: '缠论',
metainfo: {
_metainfoVersion: 53,
id: 'Chan@tv-basicstudies-5',
id: 'Chan@tv-basicstudies-6',
scriptIdPart: '',
description: 'Chan 缠论',
shortDescription: '缠论',
@@ -373,12 +414,18 @@
title: '中枢', isHidden: false },
{ id: 'segzs_fill', objAId: 'segzs_top', objBId: 'segzs_bottom', type: 'plot_plot',
title: '段中枢', isHidden: false },
{ id: 'zs_pending_fill', objAId: 'zs_pending_top', objBId: 'zs_pending_bottom', type: 'plot_plot',
title: '未完成中枢', isHidden: false },
{ id: 'segzs_pending_fill', objAId: 'segzs_pending_top', objBId: 'segzs_pending_bottom', type: 'plot_plot',
title: '未完成段中枢', isHidden: false },
],
defaults: {
styles: styles,
filledAreasStyle: {
zs_fill: mergeFill('zs_fill', { color: '#f1d96a', visible: true, transparency: 75 }),
segzs_fill: mergeFill('segzs_fill', { color: '#6361f7', visible: true, transparency: 75 }),
zs_pending_fill: mergeFill('zs_pending_fill', { color: '#f1c40f', visible: true, transparency: 55 }),
segzs_pending_fill: mergeFill('segzs_pending_fill', { color: '#9b59b6', visible: true, transparency: 55 }),
},
precision: 2,
inputs: { epoch: 0 },
@@ -394,8 +441,8 @@
self._context = ctx
}
this.main = function (context) {
// 32 个 plot: 8 结构 + 24 BSP
var NANS = new Array(32).fill(NaN)
// 36 个 plot: 12 结构 + 24 BSP
var NANS = new Array(36).fill(NaN)
// v31: sniffing pass 时 context.symbol.time 为 NaN
var t = context.symbol.time
if (isNaN(t)) return NANS
@@ -415,6 +462,10 @@
e.zs_bottom != null ? e.zs_bottom : NaN,
e.segzs_top != null ? e.segzs_top : NaN,
e.segzs_bottom != null ? e.segzs_bottom : NaN,
e.zs_pending_top != null ? e.zs_pending_top : NaN,
e.zs_pending_bottom != null ? e.zs_pending_bottom : NaN,
e.segzs_pending_top != null ? e.segzs_pending_top : NaN,
e.segzs_pending_bottom != null ? e.segzs_pending_bottom : NaN,
]
BSP_SUBTYPES.forEach(function (sub) {