수정
This commit is contained in:
@@ -739,6 +739,41 @@ export class ChartManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 이중 plot 지표 — addIndicator 루프에서 누락된 plot 시리즈 추가 */
|
/** 이중 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(
|
private _appendMissingPlotSeriesToLists(
|
||||||
seriesList: ISeriesApi<SeriesType>[],
|
seriesList: ISeriesApi<SeriesType>[],
|
||||||
seriesMeta: IndicatorEntry['seriesMeta'],
|
seriesMeta: IndicatorEntry['seriesMeta'],
|
||||||
@@ -812,6 +847,9 @@ export class ChartManager {
|
|||||||
indicatorHidden,
|
indicatorHidden,
|
||||||
def,
|
def,
|
||||||
);
|
);
|
||||||
|
if (config.type === 'OBV' && !indicatorHidden && entry.seriesList.length > 0) {
|
||||||
|
this._applyObvTightScale(entry.seriesList, result.plots as Record<string, PlotData>);
|
||||||
|
}
|
||||||
entry.config = config;
|
entry.config = config;
|
||||||
if (entry.seriesList.length > 0) {
|
if (entry.seriesList.length > 0) {
|
||||||
const actualPane = this._readSeriesPaneIndex(entry.seriesList[0]);
|
const actualPane = this._readSeriesPaneIndex(entry.seriesList[0]);
|
||||||
@@ -911,14 +949,6 @@ export class ChartManager {
|
|||||||
}, pane);
|
}, pane);
|
||||||
series.setData(filtered.map(p => ({ time: p.time as Time, value: p.value })));
|
series.setData(filtered.map(p => ({ time: p.time as Time, value: p.value })));
|
||||||
seriesMeta.push({ plotId: plotDef.id, isHistogram: false, color: plotDef.color });
|
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);
|
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(과열선/중앙선/침체선)는 첫 번째 시리즈에만 한 번 생성 (중복 방지)
|
// hlines(과열선/중앙선/침체선)는 첫 번째 시리즈에만 한 번 생성 (중복 방지)
|
||||||
const hlineRefs: IPriceLine[] = [];
|
const hlineRefs: IPriceLine[] = [];
|
||||||
@@ -1052,6 +1086,13 @@ export class ChartManager {
|
|||||||
if (!DUAL_LINE_INDICATOR_TYPES.has(entry.type)) continue;
|
if (!DUAL_LINE_INDICATOR_TYPES.has(entry.type)) continue;
|
||||||
await this._ensureDualLinePlotSeriesForEntry(entry);
|
await this._ensureDualLinePlotSeriesForEntry(entry);
|
||||||
if (entry.config) this.applyIndicatorStyle(entry.config);
|
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