크로스헤어 수정

This commit is contained in:
Macbook
2026-06-16 01:46:09 +09:00
parent ddd6ecef80
commit 615e1164a6
+12 -45
View File
@@ -164,10 +164,6 @@ interface IndicatorEntry {
bbFillPrimitive?: BollingerBandFillPrimitive;
config: IndicatorConfig;
cloudPlugin?: IchimokuCloudPlugin; // 일목균형표 구름 플러그인
/** pane 'right' 축 오염 방지용 전용 priceScaleId (OBV 제외 서브 pane 지표) */
isolatedScaleId?: string;
/** isolatedScale autoscaleInfoProvider 초기 min/max */
plotAutoscaleBounds?: { min: number; max: number };
}
interface AlertEntry { price: number; label: string; line: IPriceLine; }
@@ -1022,7 +1018,7 @@ export class ChartManager {
pane: number,
indicatorHidden: boolean,
def: ReturnType<typeof getIndicatorDef>,
scaleOpts: ReturnType<ChartManager['_isolatedScaleSeriesOptions']> = null,
scaleOpts: ReturnType<ChartManager['_autoscaleSeriesOptions']> = null,
): void {
const plotDefs = this._dualLinePlotDefsForRender(config, def);
const indicatorPriceFormat = priceFormatForIndicatorSeries(def);
@@ -1222,7 +1218,7 @@ export class ChartManager {
const plotDefsRaw = config.plots ?? def?.plots ?? [];
const plotRange = this._computePlotsValueRange(result.plots as Record<string, PlotData>);
const scaleOpts = this._isolatedScaleSeriesOptions(config, plotRange);
const scaleOpts = this._autoscaleSeriesOptions(config, plotRange);
const indicatorPriceFormat = priceFormatForIndicatorSeries(def);
if (config.type === 'OBV') {
@@ -1350,15 +1346,10 @@ export class ChartManager {
const entry: IndicatorEntry = {
id: config.id, type: config.type, seriesList, seriesMeta,
paneIndex: pane, alertLines: [], hlineRefs, fillPrimitive, config,
isolatedScaleId: scaleOpts?.priceScaleId,
plotAutoscaleBounds: plotRange ?? undefined,
};
const actualPane = this._readSeriesPaneIndex(seriesList[0]);
const minSub = this._minIndicatorSubPane();
if (actualPane >= minSub) entry.paneIndex = actualPane;
if (entry.isolatedScaleId != null && entry.paneIndex != null && entry.paneIndex >= minSub) {
this._applyIsolatedScalePaneOptions(entry.isolatedScaleId, entry.paneIndex);
}
if (this._indicatorLoadStale(dataGenAtStart) || this.indicators.has(config.id)) {
this._discardIndicatorSeries(seriesList, { fillPrimitive });
return;
@@ -2226,11 +2217,7 @@ export class ChartManager {
}
}
private _indicatorScaleId(configId: string): string {
return `ind-${configId}`;
}
/** plot 데이터 min/max — 전용 가격축 autoscale 용 */
/** plot 데이터 min/max — autoscaleInfoProvider 용 */
private _computePlotsValueRange(
plots: Record<string, PlotData>,
plotIds?: string[],
@@ -2250,14 +2237,14 @@ export class ChartManager {
return { min: lo, max: hi };
}
/** OBV 제외 서브 pane 지표 — pane 공유 'right' 축 오염(종가·타 지표 값 혼입) 방지 */
private _usesIsolatedPriceScale(type: string): boolean {
/** OBV 제외 서브 pane — pane 기본 'right' 축 + autoscale (overlay priceScaleId 는 UI·크로스헤어 라벨 없음) */
private _usesAutoscaleProvider(type: string): boolean {
if (type === 'OBV') return false;
const def = getIndicatorDef(type);
return !!(def && !def.overlay && !def.returnsMarkers);
}
private _makeIsolatedAutoscaleProvider(lo: number, hi: number) {
private _makeAutoscaleProvider(lo: number, hi: number) {
return (baseImpl: () => { priceRange: { minValue: number; maxValue: number } } | null) => {
let minV = lo;
let maxV = hi;
@@ -2273,37 +2260,19 @@ export class ChartManager {
};
}
private _isolatedScaleSeriesOptions(
private _autoscaleSeriesOptions(
config: IndicatorConfig,
plotRange: { min: number; max: number } | null,
): {
priceScaleId: string;
autoscaleInfoProvider?: ReturnType<ChartManager['_makeIsolatedAutoscaleProvider']>;
} | null {
if (!this._usesIsolatedPriceScale(config.type)) return null;
const scaleId = this._indicatorScaleId(config.id);
if (!plotRange || plotRange.max <= plotRange.min) {
return { priceScaleId: scaleId };
}
): { autoscaleInfoProvider: ReturnType<ChartManager['_makeAutoscaleProvider']> } | null {
if (!this._usesAutoscaleProvider(config.type)) return null;
if (!plotRange || plotRange.max <= plotRange.min) return null;
let { min, max } = plotRange;
const def = getIndicatorDef(config.type);
if (def?.hlines?.some(h => h.price === 0)) {
min = Math.min(min, 0);
max = Math.max(max, 0);
}
return {
priceScaleId: scaleId,
autoscaleInfoProvider: this._makeIsolatedAutoscaleProvider(min, max),
};
}
private _applyIsolatedScalePaneOptions(scaleId: string, pane: number): void {
try {
this.chart.priceScale(scaleId, pane).applyOptions({
visible: true,
scaleMargins: { top: 0.12, bottom: 0.12 },
});
} catch { /* ok */ }
return { autoscaleInfoProvider: this._makeAutoscaleProvider(min, max) };
}
/** 볼륨 pane(1)이 실제로 표시되는지 여부 */
@@ -2430,7 +2399,7 @@ export class ChartManager {
if (!moved && entry.paneIndex === target) continue;
entry.paneIndex = target;
// 통일된 pane 에서 OBV·전용축 지표 옵션 재확정 (이동 중 손실 방지)
// 통일된 pane 에서 OBV 전용 축 옵션 재확정 (이동 중 손실 방지)
if (entry.type === 'OBV' && entry.config) {
try {
this.chart.priceScale(`obv-${entry.config.id}`, target).applyOptions({
@@ -2438,8 +2407,6 @@ export class ChartManager {
scaleMargins: { top: 0.12, bottom: 0.12 },
});
} catch { /* ok */ }
} else if (entry.isolatedScaleId) {
this._applyIsolatedScalePaneOptions(entry.isolatedScaleId, target);
}
}
}