크로스헤어 수정
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user