fix(web): 开关缠论元素保留视窗;分周期 Trend 涨跌配色
本地重绘统一冻结视窗;次/次次周期 Trend 上涨下跌使用独立颜色。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -48,6 +48,52 @@ function alignMarkersToCandles(markers, candles) {
|
||||
return out;
|
||||
}
|
||||
|
||||
/** 解析后端 KLC trend(UP/DOWN/FLAT 或枚举名/数字) */
|
||||
function normalizeKlcTrendRaw(trend) {
|
||||
var raw = (trend == null ? '' : String(trend)).trim();
|
||||
if (!raw) return 'UNKNOWN';
|
||||
var upper = raw.toUpperCase();
|
||||
if (upper === 'UP' || raw === '1' || upper.indexOf('.UP') >= 0 || upper.endsWith('UP')) return 'UP';
|
||||
if (upper === 'DOWN' || raw === '2' || upper.indexOf('.DOWN') >= 0 || upper.endsWith('DOWN')) return 'DOWN';
|
||||
if (upper === 'FLAT' || raw === '3' || upper.indexOf('.FLAT') >= 0 || upper.endsWith('FLAT')) return 'FLAT';
|
||||
return upper;
|
||||
}
|
||||
|
||||
var MAIN_KLC_TREND_STYLE = {
|
||||
UP: { position: 'aboveBar', color: '#00C853', shape: 'arrowUp', size: 0.5 },
|
||||
DOWN: { position: 'belowBar', color: '#D32F2F', shape: 'arrowDown', size: 0.5 },
|
||||
FLAT: { position: 'inBar', color: '#9E9E9E', shape: 'circle', size: 0.8 },
|
||||
UNKNOWN: { position: 'inBar', color: '#2196F3', shape: 'square', size: 0.8 }
|
||||
};
|
||||
|
||||
/** 次周期 Trend:橙涨 / 靛蓝跌,与主周期绿红区分 */
|
||||
var ELEMENT_KLC_TREND_STYLE = {
|
||||
UP: { position: 'aboveBar', color: '#e67e22', shape: 'arrowUp', size: 0.5 },
|
||||
DOWN: { position: 'belowBar', color: '#5c6bc0', shape: 'arrowDown', size: 0.5 },
|
||||
FLAT: { position: 'inBar', color: '#bdbdbd', shape: 'circle', size: 0.8 },
|
||||
UNKNOWN: { position: 'inBar', color: '#8e44ad', shape: 'square', size: 0.8 }
|
||||
};
|
||||
|
||||
/** 次次周期 Trend:青绿涨 / 灰蓝跌(略小标记) */
|
||||
var SUB_SUB_KLC_TREND_STYLE = {
|
||||
UP: { position: 'aboveBar', color: '#00b894', shape: 'arrowUp', size: 0.4 },
|
||||
DOWN: { position: 'belowBar', color: '#546e7a', shape: 'arrowDown', size: 0.4 },
|
||||
FLAT: { position: 'inBar', color: '#00897b', shape: 'circle', size: 0.5 },
|
||||
UNKNOWN: { position: 'inBar', color: '#004d40', shape: 'square', size: 0.5 }
|
||||
};
|
||||
|
||||
function buildKlcTrendMarker(timeAligned, trendRaw, palette) {
|
||||
var kind = normalizeKlcTrendRaw(trendRaw);
|
||||
var style = palette[kind] || palette.UNKNOWN || palette.FLAT;
|
||||
return {
|
||||
time: timeAligned,
|
||||
position: style.position,
|
||||
color: style.color,
|
||||
shape: style.shape,
|
||||
size: style.size
|
||||
};
|
||||
}
|
||||
|
||||
function safeOverlayLineSetData(series, points) {
|
||||
if (!series || typeof series.setData !== 'function' || !Array.isArray(points) || points.length < 2) return;
|
||||
try {
|
||||
@@ -2229,20 +2275,8 @@ function chartTvRenderOverlays(ctx) {
|
||||
|
||||
klcTrendMarkers = currentData.klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
let timeAligned = seriesTimes.has(ts) ? ts : nearestTime(ts);
|
||||
let marker = { time: timeAligned, position: 'inBar', color: '#9E9E9E', shape: 'square', size: 0.8 };
|
||||
if (trendRaw === 'UP') {
|
||||
marker = { time: timeAligned, position: 'aboveBar', color: '#00C853', shape: 'arrowUp', size: 0.5 };
|
||||
} else if (trendRaw === 'DOWN') {
|
||||
marker = { time: timeAligned, position: 'belowBar', color: '#D32F2F', shape: 'arrowDown', size: 0.5 };
|
||||
} else if (trendRaw === 'FLAT') {
|
||||
marker = { time: timeAligned, position: 'inBar', color: '#9E9E9E', shape: 'circle', size: 0.8 };
|
||||
} else {
|
||||
// UNKNOWN 或其他
|
||||
marker = { time: timeAligned, position: 'inBar', color: '#2196F3', shape: 'square', size: 0.8 };
|
||||
}
|
||||
return marker;
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, MAIN_KLC_TREND_STYLE);
|
||||
});
|
||||
console.log('KLC趋势标记(对齐后)示例:', klcTrendMarkers.slice(0, 5));
|
||||
}
|
||||
@@ -2270,12 +2304,8 @@ function chartTvRenderOverlays(ctx) {
|
||||
};
|
||||
const elementMarkers = currentData.element_klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
const timeAligned = candlesTimes.has(ts) ? ts : nearestTime(ts);
|
||||
if (trendRaw === 'UP') return { time: timeAligned, position: 'aboveBar', color: '#00C853', shape: 'arrowUp', size: 0.5 };
|
||||
if (trendRaw === 'DOWN') return { time: timeAligned, position: 'belowBar', color: '#D32F2F', shape: 'arrowDown', size: 0.5 };
|
||||
if (trendRaw === 'FLAT') return { time: timeAligned, position: 'inBar', color: '#9E9E9E', shape: 'circle', size: 0.8 };
|
||||
return { time: timeAligned, position: 'inBar', color: '#2196F3', shape: 'square', size: 0.8 };
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, ELEMENT_KLC_TREND_STYLE);
|
||||
});
|
||||
trendMarkersToUse = trendMarkersToUse.concat(elementMarkers);
|
||||
}
|
||||
@@ -2290,15 +2320,10 @@ function chartTvRenderOverlays(ctx) {
|
||||
}
|
||||
return best;
|
||||
};
|
||||
const subSubColor = '#00897b';
|
||||
const subSubMarkers = currentData.sub_sub_klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
const timeAligned = candlesTimesSs.has(ts) ? ts : nearestTimeSs(ts);
|
||||
if (trendRaw === 'UP') return { time: timeAligned, position: 'aboveBar', color: subSubColor, shape: 'arrowUp', size: 0.4 };
|
||||
if (trendRaw === 'DOWN') return { time: timeAligned, position: 'belowBar', color: subSubColor, shape: 'arrowDown', size: 0.4 };
|
||||
if (trendRaw === 'FLAT') return { time: timeAligned, position: 'inBar', color: subSubColor, shape: 'circle', size: 0.5 };
|
||||
return { time: timeAligned, position: 'inBar', color: subSubColor, shape: 'square', size: 0.5 };
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, SUB_SUB_KLC_TREND_STYLE);
|
||||
});
|
||||
trendMarkersToUse = trendMarkersToUse.concat(subSubMarkers);
|
||||
}
|
||||
@@ -2369,17 +2394,8 @@ function chartTvRenderOverlays(ctx) {
|
||||
};
|
||||
klcTrendMarkers = currentData.klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
const timeAligned = seriesTimes.has(ts) ? ts : nearestTime(ts);
|
||||
if (trendRaw === 'UP') {
|
||||
return { time: timeAligned, position: 'aboveBar', color: '#00C853', shape: 'arrowUp', size: 0.5 };
|
||||
} else if (trendRaw === 'DOWN') {
|
||||
return { time: timeAligned, position: 'belowBar', color: '#D32F2F', shape: 'arrowDown', size: 0.5 };
|
||||
} else if (trendRaw === 'FLAT') {
|
||||
return { time: timeAligned, position: 'inBar', color: '#9E9E9E', shape: 'circle', size: 0.8 };
|
||||
} else {
|
||||
return { time: timeAligned, position: 'inBar', color: '#2196F3', shape: 'square', size: 0.8 };
|
||||
}
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, MAIN_KLC_TREND_STYLE);
|
||||
});
|
||||
console.log('KLC趋势标记(对齐后)示例:', klcTrendMarkers.slice(0, 5));
|
||||
}
|
||||
@@ -2406,12 +2422,8 @@ function chartTvRenderOverlays(ctx) {
|
||||
};
|
||||
const elementMarkers = currentData.element_klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
const timeAligned = candlesTimes.has(ts) ? ts : nearestTime(ts);
|
||||
if (trendRaw === 'UP') return { time: timeAligned, position: 'aboveBar', color: '#00C853', shape: 'arrowUp', size: 0.5 };
|
||||
if (trendRaw === 'DOWN') return { time: timeAligned, position: 'belowBar', color: '#D32F2F', shape: 'arrowDown', size: 0.5 };
|
||||
if (trendRaw === 'FLAT') return { time: timeAligned, position: 'inBar', color: '#9E9E9E', shape: 'circle', size: 0.8 };
|
||||
return { time: timeAligned, position: 'inBar', color: '#2196F3', shape: 'square', size: 0.8 };
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, ELEMENT_KLC_TREND_STYLE);
|
||||
});
|
||||
trendMarkersToUse = trendMarkersToUse.concat(elementMarkers);
|
||||
}
|
||||
@@ -2426,15 +2438,10 @@ function chartTvRenderOverlays(ctx) {
|
||||
}
|
||||
return best;
|
||||
};
|
||||
const subSubColor2 = '#00897b';
|
||||
const subSubMarkers2 = currentData.sub_sub_klc_trend.map(t => {
|
||||
const ts = Math.floor(new Date(t.time).getTime() / 1000);
|
||||
const trendRaw = (t.trend || '').toString().toUpperCase();
|
||||
const timeAligned = candlesTimesSs2.has(ts) ? ts : nearestTimeSs2(ts);
|
||||
if (trendRaw === 'UP') return { time: timeAligned, position: 'aboveBar', color: subSubColor2, shape: 'arrowUp', size: 0.4 };
|
||||
if (trendRaw === 'DOWN') return { time: timeAligned, position: 'belowBar', color: subSubColor2, shape: 'arrowDown', size: 0.4 };
|
||||
if (trendRaw === 'FLAT') return { time: timeAligned, position: 'inBar', color: subSubColor2, shape: 'circle', size: 0.5 };
|
||||
return { time: timeAligned, position: 'inBar', color: subSubColor2, shape: 'square', size: 0.5 };
|
||||
return buildKlcTrendMarker(timeAligned, t.trend, SUB_SUB_KLC_TREND_STYLE);
|
||||
});
|
||||
trendMarkersToUse = trendMarkersToUse.concat(subSubMarkers2);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user