수정
This commit is contained in:
@@ -739,6 +739,41 @@ export class ChartManager {
|
||||
}
|
||||
|
||||
/** 이중 plot 지표 — addIndicator 루프에서 누락된 plot 시리즈 추가 */
|
||||
/**
|
||||
* OBV pane y축 스케일을 최근 N봉 실제 값 기준으로 강제 고정.
|
||||
* 과거에 OBV가 큰 값을 기록했어도 현재 구간이 y축 하단에 압축되지 않도록 방지.
|
||||
*/
|
||||
private _applyObvTightScale(
|
||||
seriesList: ISeriesApi<SeriesType>[],
|
||||
plots: Record<string, PlotData>,
|
||||
recentCount = 60,
|
||||
): void {
|
||||
const allRecent: number[] = [];
|
||||
for (const key of ['plot0', 'plot1']) {
|
||||
const pts = (plots[key] ?? []).filter(p => p.value != null && isFinite(p.value as number));
|
||||
const slice = pts.slice(-recentCount).map(p => p.value as number);
|
||||
allRecent.push(...slice);
|
||||
}
|
||||
if (allRecent.length === 0) return;
|
||||
const minV = Math.min(...allRecent);
|
||||
const maxV = Math.max(...allRecent);
|
||||
const span = Math.max(1, maxV - minV);
|
||||
const pad = span * 0.3;
|
||||
const tMin = minV - pad;
|
||||
const tMax = maxV + pad;
|
||||
for (const s of seriesList) {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(s as ISeriesApi<any>).applyOptions({
|
||||
autoscaleInfoProvider: () => ({
|
||||
priceRange: { minValue: tMin, maxValue: tMax },
|
||||
margins: { above: 0, below: 0 },
|
||||
}),
|
||||
});
|
||||
} catch { /* ok */ }
|
||||
}
|
||||
}
|
||||
|
||||
private _appendMissingPlotSeriesToLists(
|
||||
seriesList: ISeriesApi<SeriesType>[],
|
||||
seriesMeta: IndicatorEntry['seriesMeta'],
|
||||
@@ -812,6 +847,9 @@ export class ChartManager {
|
||||
indicatorHidden,
|
||||
def,
|
||||
);
|
||||
if (config.type === 'OBV' && !indicatorHidden && entry.seriesList.length > 0) {
|
||||
this._applyObvTightScale(entry.seriesList, result.plots as Record<string, PlotData>);
|
||||
}
|
||||
entry.config = config;
|
||||
if (entry.seriesList.length > 0) {
|
||||
const actualPane = this._readSeriesPaneIndex(entry.seriesList[0]);
|
||||
@@ -911,14 +949,6 @@ export class ChartManager {
|
||||
}, pane);
|
||||
series.setData(filtered.map(p => ({ time: p.time as Time, value: p.value })));
|
||||
seriesMeta.push({ plotId: plotDef.id, isHistogram: false, color: plotDef.color });
|
||||
|
||||
// OBV 디버그: 마지막 5개 값 출력
|
||||
if (config.type === 'OBV') {
|
||||
const last5 = filtered.slice(-5).map(p => p.value.toFixed(2));
|
||||
const minV = Math.min(...filtered.map(p => p.value));
|
||||
const maxV = Math.max(...filtered.map(p => p.value));
|
||||
console.warn(`[OBV-DATA] ${plotDef.id} | last5=${last5.join(',')} | min=${minV.toFixed(2)} max=${maxV.toFixed(2)} | totalPts=${filtered.length}`);
|
||||
}
|
||||
}
|
||||
|
||||
seriesList.push(series);
|
||||
@@ -936,6 +966,10 @@ export class ChartManager {
|
||||
);
|
||||
}
|
||||
|
||||
// OBV: 최근 50봉 값 기준으로 y축 고정 → 과거 큰 값에 의한 스케일 압축 방지
|
||||
if (config.type === 'OBV' && !indicatorHidden && seriesList.length > 0) {
|
||||
this._applyObvTightScale(seriesList, result.plots as Record<string, PlotData>);
|
||||
}
|
||||
|
||||
// hlines(과열선/중앙선/침체선)는 첫 번째 시리즈에만 한 번 생성 (중복 방지)
|
||||
const hlineRefs: IPriceLine[] = [];
|
||||
@@ -1052,6 +1086,13 @@ export class ChartManager {
|
||||
if (!DUAL_LINE_INDICATOR_TYPES.has(entry.type)) continue;
|
||||
await this._ensureDualLinePlotSeriesForEntry(entry);
|
||||
if (entry.config) this.applyIndicatorStyle(entry.config);
|
||||
// OBV: tight scale 재적용 (스타일 갱신 후 autoscaleInfoProvider 덮어써질 수 있음)
|
||||
if (entry.type === 'OBV' && entry.seriesList.length > 0 && this.rawBars.length > 0) {
|
||||
try {
|
||||
const result = await calculateIndicator('OBV', this.rawBars.slice(), entry.config?.params ?? {});
|
||||
this._applyObvTightScale(entry.seriesList, result.plots as Record<string, PlotData>);
|
||||
} catch { /* ok */ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user