macd 수정
This commit is contained in:
@@ -844,14 +844,59 @@ export class ChartManager {
|
|||||||
return this._plotOrderForEntry(entry).map(plotId => {
|
return this._plotOrderForEntry(entry).map(plotId => {
|
||||||
const idx = entry.seriesMeta.findIndex(m => m.plotId === plotId);
|
const idx = entry.seriesMeta.findIndex(m => m.plotId === plotId);
|
||||||
if (idx < 0) return NaN;
|
if (idx < 0) return NaN;
|
||||||
const series = entry.seriesList[idx];
|
return this._seriesValueAtCrosshairTime(entry.seriesList[idx], params);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
||||||
const d = params.seriesData.get(series) as any;
|
|
||||||
if (!d) return NaN;
|
|
||||||
return typeof d.value === 'number' ? d.value : NaN;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 전용 priceScale 시리즈는 params.seriesData 에 없을 수 있어 time 기준 fallback 조회 */
|
||||||
|
private _seriesValueAtCrosshairTime(
|
||||||
|
series: ISeriesApi<SeriesType>,
|
||||||
|
params: MouseEventParams<Time>,
|
||||||
|
): number {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
const d = params.seriesData.get(series) as any;
|
||||||
|
if (d != null) {
|
||||||
|
if (typeof d.value === 'number' && Number.isFinite(d.value)) return d.value;
|
||||||
|
if (typeof d.close === 'number' && Number.isFinite(d.close)) return d.close;
|
||||||
|
}
|
||||||
|
if (params.time == null) return NaN;
|
||||||
|
return this._lookupSeriesValueAtTime(series, params.time as number);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _lookupSeriesValueAtTime(
|
||||||
|
series: ISeriesApi<SeriesType>,
|
||||||
|
time: number,
|
||||||
|
): number {
|
||||||
|
try {
|
||||||
|
const data = series.data() as ReadonlyArray<{ time: Time; value?: number; close?: number }>;
|
||||||
|
if (!data.length) return NaN;
|
||||||
|
for (let i = data.length - 1; i >= 0; i--) {
|
||||||
|
const t = data[i].time as number;
|
||||||
|
if (t <= time) {
|
||||||
|
const v = data[i].value ?? data[i].close;
|
||||||
|
return typeof v === 'number' && Number.isFinite(v) ? v : NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const v = data[0].value ?? data[0].close;
|
||||||
|
return typeof v === 'number' && Number.isFinite(v) ? v : NaN;
|
||||||
|
} catch {
|
||||||
|
return NaN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 보조지표 전용 sub-pane (볼륨 숨김 시 pane 1 포함) */
|
||||||
|
private _isIndicatorSubPane(paneIndex: number): boolean {
|
||||||
|
return paneIndex >= this._minIndicatorSubPane();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _showSeriesTitleOnChart(paneIndex: number): boolean {
|
||||||
|
return !this._isIndicatorSubPane(paneIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hlineAxisLabelVisible(): boolean {
|
||||||
|
return this._indicatorAreaPriceLabelsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
/** OBV — plot0·plot1 항상 쌍으로 생성 (메인 차트와 동일, DUAL_LINE repair 경로 회피) */
|
/** OBV — plot0·plot1 항상 쌍으로 생성 (메인 차트와 동일, DUAL_LINE repair 경로 회피) */
|
||||||
private _addObvIndicatorSeries(
|
private _addObvIndicatorSeries(
|
||||||
seriesList: ISeriesApi<SeriesType>[],
|
seriesList: ISeriesApi<SeriesType>[],
|
||||||
@@ -918,7 +963,7 @@ export class ChartManager {
|
|||||||
|
|
||||||
const isPlotVisible = !indicatorHidden;
|
const isPlotVisible = !indicatorHidden;
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(enriched, true, pane);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(enriched, true, pane);
|
||||||
const showSeriesTitle = pane < 2 && showPriceLabel;
|
const showSeriesTitle = this._showSeriesTitleOnChart(pane) && showPriceLabel;
|
||||||
const regPlot = def?.plots?.find(p => p.id === plotId);
|
const regPlot = def?.plots?.find(p => p.id === plotId);
|
||||||
|
|
||||||
const resolvedColor = resolvePlotLineColor(
|
const resolvedColor = resolvePlotLineColor(
|
||||||
@@ -995,13 +1040,14 @@ export class ChartManager {
|
|||||||
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
||||||
: config.plotVisibility?.[plotDef.id] !== false);
|
: config.plotVisibility?.[plotDef.id] !== false);
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
||||||
const showSeriesTitle = pane < 2 && showPriceLabel;
|
const showSeriesTitle = this._showSeriesTitleOnChart(pane) && showPriceLabel;
|
||||||
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
||||||
const series = this.chart.addSeries(LineSeries, {
|
const series = this.chart.addSeries(LineSeries, {
|
||||||
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
||||||
lineWidth: Math.max(1, plotDef.lineWidth ?? regPlot?.lineWidth ?? 1) as 1 | 2 | 3 | 4,
|
lineWidth: Math.max(1, plotDef.lineWidth ?? regPlot?.lineWidth ?? 1) as 1 | 2 | 3 | 4,
|
||||||
lineStyle: plotSeriesLineStyle(plotDef.lineStyle),
|
lineStyle: plotSeriesLineStyle(plotDef.lineStyle),
|
||||||
priceLineVisible: false,
|
priceLineVisible: false,
|
||||||
|
crosshairMarkerVisible: true,
|
||||||
lastValueVisible: showPriceLabel,
|
lastValueVisible: showPriceLabel,
|
||||||
title: showSeriesTitle ? this.seriesTitleForPlot(config, plotDef) : '',
|
title: showSeriesTitle ? this.seriesTitleForPlot(config, plotDef) : '',
|
||||||
visible: isPlotVisible,
|
visible: isPlotVisible,
|
||||||
@@ -1045,7 +1091,7 @@ export class ChartManager {
|
|||||||
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
||||||
: config.plotVisibility?.[plotDef.id] !== false);
|
: config.plotVisibility?.[plotDef.id] !== false);
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
||||||
const showSeriesTitle = pane < 2 && showPriceLabel;
|
const showSeriesTitle = this._showSeriesTitleOnChart(pane) && showPriceLabel;
|
||||||
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
||||||
const series = this.chart.addSeries(LineSeries, {
|
const series = this.chart.addSeries(LineSeries, {
|
||||||
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
||||||
@@ -1225,13 +1271,14 @@ export class ChartManager {
|
|||||||
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
? isCustomPlotSelected(this._getAppliedCustomOverlaySelection(), config.type, plotDef.id)
|
||||||
: config.plotVisibility?.[plotDef.id] !== false);
|
: config.plotVisibility?.[plotDef.id] !== false);
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
||||||
const showSeriesTitle = pane < 2 && showPriceLabel;
|
const showSeriesTitle = this._showSeriesTitleOnChart(pane) && showPriceLabel;
|
||||||
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
const regPlot = def?.plots?.find(p => p.id === plotDef.id);
|
||||||
series = this.chart.addSeries(LineSeries, {
|
series = this.chart.addSeries(LineSeries, {
|
||||||
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
color: resolvePlotLineColor(plotDef.color, regPlot?.color ?? plotDef.color ?? '#2962FF'),
|
||||||
lineWidth: Math.max(1, plotDef.lineWidth ?? regPlot?.lineWidth ?? 1) as 1 | 2 | 3 | 4,
|
lineWidth: Math.max(1, plotDef.lineWidth ?? regPlot?.lineWidth ?? 1) as 1 | 2 | 3 | 4,
|
||||||
lineStyle: plotSeriesLineStyle(plotDef.lineStyle),
|
lineStyle: plotSeriesLineStyle(plotDef.lineStyle),
|
||||||
priceLineVisible: false,
|
priceLineVisible: false,
|
||||||
|
crosshairMarkerVisible: true,
|
||||||
lastValueVisible: showPriceLabel,
|
lastValueVisible: showPriceLabel,
|
||||||
title: showSeriesTitle ? this.seriesTitleForPlot(config, plotDef) : '',
|
title: showSeriesTitle ? this.seriesTitleForPlot(config, plotDef) : '',
|
||||||
visible: isPlotVisible,
|
visible: isPlotVisible,
|
||||||
@@ -1281,7 +1328,7 @@ export class ChartManager {
|
|||||||
color: hl.color,
|
color: hl.color,
|
||||||
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
||||||
lineStyle: toLineStyle(hl.lineStyle),
|
lineStyle: toLineStyle(hl.lineStyle),
|
||||||
axisLabelVisible: false,
|
axisLabelVisible: this._hlineAxisLabelVisible(),
|
||||||
});
|
});
|
||||||
hlineRefs.push(pl);
|
hlineRefs.push(pl);
|
||||||
}
|
}
|
||||||
@@ -3561,9 +3608,9 @@ export class ChartManager {
|
|||||||
plotAllowsLastValue = true,
|
plotAllowsLastValue = true,
|
||||||
paneIndex = 0,
|
paneIndex = 0,
|
||||||
): boolean {
|
): boolean {
|
||||||
const areaEnabled = paneIndex < 2
|
const areaEnabled = this._isIndicatorSubPane(paneIndex)
|
||||||
? this._candleAreaPriceLabelsEnabled
|
? this._indicatorAreaPriceLabelsEnabled
|
||||||
: this._indicatorAreaPriceLabelsEnabled;
|
: this._candleAreaPriceLabelsEnabled;
|
||||||
return areaEnabled
|
return areaEnabled
|
||||||
&& plotAllowsLastValue
|
&& plotAllowsLastValue
|
||||||
&& config.lastValueVisible !== false;
|
&& config.lastValueVisible !== false;
|
||||||
@@ -3632,13 +3679,14 @@ export class ChartManager {
|
|||||||
: Math.max(1, plot.lineWidth ?? regPlot?.lineWidth ?? 1)) as 1 | 2 | 3 | 4)
|
: Math.max(1, plot.lineWidth ?? regPlot?.lineWidth ?? 1)) as 1 | 2 | 3 | 4)
|
||||||
: Math.max(1, plot.lineWidth ?? regPlot?.lineWidth ?? 1);
|
: Math.max(1, plot.lineWidth ?? regPlot?.lineWidth ?? 1);
|
||||||
opts['lineStyle'] = plotSeriesLineStyle(plot.lineStyle);
|
opts['lineStyle'] = plotSeriesLineStyle(plot.lineStyle);
|
||||||
|
opts['crosshairMarkerVisible'] = true;
|
||||||
let plotAllows = true;
|
let plotAllows = true;
|
||||||
if (entry.type === 'IchimokuCloud') {
|
if (entry.type === 'IchimokuCloud') {
|
||||||
plotAllows = entry.seriesMeta[i]?.plotId !== 'plot2';
|
plotAllows = entry.seriesMeta[i]?.plotId !== 'plot2';
|
||||||
}
|
}
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, plotAllows, paneIdx);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, plotAllows, paneIdx);
|
||||||
opts['lastValueVisible'] = showPriceLabel && visible;
|
opts['lastValueVisible'] = showPriceLabel && visible;
|
||||||
opts['title'] = paneIdx < 2 && showPriceLabel && visible
|
opts['title'] = this._showSeriesTitleOnChart(paneIdx) && showPriceLabel && visible
|
||||||
? this.seriesTitleForPlot(config, plot, plotAllows, paneIdx)
|
? this.seriesTitleForPlot(config, plot, plotAllows, paneIdx)
|
||||||
: '';
|
: '';
|
||||||
} else {
|
} else {
|
||||||
@@ -3678,7 +3726,7 @@ export class ChartManager {
|
|||||||
color: hl.color,
|
color: hl.color,
|
||||||
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
||||||
lineStyle: toLineStyle2(hl.lineStyle),
|
lineStyle: toLineStyle2(hl.lineStyle),
|
||||||
axisLabelVisible: false,
|
axisLabelVisible: this._hlineAxisLabelVisible(),
|
||||||
});
|
});
|
||||||
entry.hlineRefs.push(pl);
|
entry.hlineRefs.push(pl);
|
||||||
}
|
}
|
||||||
@@ -4821,15 +4869,11 @@ export class ChartManager {
|
|||||||
getIndicatorValuesFromParams(params: MouseEventParams<Time>): Record<string, number[]> {
|
getIndicatorValuesFromParams(params: MouseEventParams<Time>): Record<string, number[]> {
|
||||||
const result: Record<string, number[]> = {};
|
const result: Record<string, number[]> = {};
|
||||||
for (const [, entry] of this.indicators) {
|
for (const [, entry] of this.indicators) {
|
||||||
const values: number[] = [];
|
const values = this._plotOrderForEntry(entry).map(plotId => {
|
||||||
for (const series of entry.seriesList) {
|
const idx = entry.seriesMeta.findIndex(m => m.plotId === plotId);
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
if (idx < 0) return NaN;
|
||||||
const d = params.seriesData.get(series) as any;
|
return this._seriesValueAtCrosshairTime(entry.seriesList[idx], params);
|
||||||
const v = d != null
|
});
|
||||||
? (typeof d.value === 'number' ? d.value : d.close ?? NaN)
|
|
||||||
: NaN;
|
|
||||||
values.push(v);
|
|
||||||
}
|
|
||||||
if (values.some(v => !isNaN(v))) {
|
if (values.some(v => !isNaN(v))) {
|
||||||
result[entry.type] = values;
|
result[entry.type] = values;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user