매매 시그널 디테일 팝업 기능 적용

This commit is contained in:
Macbook
2026-06-10 21:13:53 +09:00
parent bf5554d375
commit 0ff1992b64
19 changed files with 1507 additions and 58 deletions
+80 -2
View File
@@ -344,6 +344,9 @@ export class ChartManager {
/** 캔들+거래량 그룹 vs 보조 pane 그룹 stretch 비율 (투자관리·백테스트 분석 차트) */
private _paneAreaRatio: { candle: number; aux: number } | null = null;
/** 보조지표 전용 패널 — 캔들 pane 최소화·선형 지표만 표시 (시그널 상세 등) */
private _auxIndicatorOnlyLayout = false;
constructor(
container: HTMLElement,
theme: Theme,
@@ -502,14 +505,22 @@ export class ChartManager {
this.volumeSeries.applyOptions({ visible: false } as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
} catch { /* ok */ }
}
} else if (panesInit[0]) {
} else if (panesInit[0] && !this._auxIndicatorOnlyLayout) {
panesInit[0].setStretchFactor(1);
}
this._reapplyAllPatternMarkers();
// 종목 전환·초기 로드 — bar 수가 적을 때 음수 logical from 은 캔들이 우측으로 몰림
this._applyDefaultVisibleRange(200, 0);
if (this._auxIndicatorOnlyLayout && bars.length <= 21) {
try { this.chart.timeScale().fitContent(); } catch { /* ok */ }
} else {
this._applyDefaultVisibleRange(200, 0);
}
if (this._auxIndicatorOnlyLayout) {
this.syncChartOverlayVisibility();
}
}
/**
@@ -4692,6 +4703,24 @@ export class ChartManager {
}
}
/**
* 보조지표 전용 레이아웃 — 캔들·오버레이 숨김, 하단 pane 선형 지표만 표시.
*/
applyAuxIndicatorOnlyLayout(enabled: boolean): void {
this._auxIndicatorOnlyLayout = enabled;
if (enabled) {
this.setChartOverlayVisibility({
ma: false,
bollinger: false,
ichimoku: false,
candle: false,
});
} else {
this.setChartOverlayVisibility({ ...DEFAULT_CHART_OVERLAY_VISIBILITY });
}
this.resetPaneHeights();
}
private _volumeFrac(H: number): number {
if (!this._volumePaneEnabled || !this._volumeVisible || this._candleOnlyLayout) return 0;
return Math.min(Math.max(60 / H, 0.04), 0.12);
@@ -4808,6 +4837,51 @@ export class ChartManager {
return H;
}
/** 보조지표 전용 — pane 0(캔들) 최소화, 보조 pane 균등 확장 */
private _resetPaneHeightsAuxIndicatorOnly(availableHeight?: number): number {
const panes = this.chart.panes();
if (panes.length === 0) return availableHeight ?? this.container.clientHeight;
const ORPHAN_STRETCH = 0.0001;
const IND_EQUAL_WEIGHT = 1;
const H = (availableHeight && availableHeight > 0)
? availableHeight
: (this._lastLayoutAvailableHeight && this._lastLayoutAvailableHeight > 0
? this._lastLayoutAvailableHeight
: this.container.clientHeight);
const activeIndPanes = this._activeIndicatorPaneIndices();
const volumeShown = this._volumePaneEnabled && this._volumeVisible && !this._candleOnlyLayout;
try {
this.volumeSeries?.applyOptions({ visible: false } as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
} catch { /* ok */ }
for (let i = 0; i < panes.length; i++) {
const paneIndex = panes[i].paneIndex();
if (paneIndex === 0) {
panes[i].setStretchFactor(ORPHAN_STRETCH);
} else if (paneIndex === 1) {
if (volumeShown) {
panes[i].setStretchFactor(ORPHAN_STRETCH);
} else if (activeIndPanes.has(1)) {
panes[i].setStretchFactor(IND_EQUAL_WEIGHT);
} else {
panes[i].setStretchFactor(ORPHAN_STRETCH);
}
} else if (activeIndPanes.has(paneIndex)) {
panes[i].setStretchFactor(IND_EQUAL_WEIGHT);
} else {
panes[i].setStretchFactor(ORPHAN_STRETCH);
}
}
this.syncChartOverlayVisibility();
this._restoreSubPaneIndicatorVisibility();
this._scheduleIndicatorLastUpdate();
return H;
}
resetPaneHeights(availableHeight?: number): number {
const panes = this.chart.panes();
if (panes.length === 0) return availableHeight ?? this.container.clientHeight;
@@ -4820,6 +4894,10 @@ export class ChartManager {
return this._resetPaneHeightsCandleFullscreen(availableHeight);
}
if (this._auxIndicatorOnlyLayout) {
return this._resetPaneHeightsAuxIndicatorOnly(availableHeight);
}
const H = (availableHeight && availableHeight > 0)
? availableHeight
: (this._lastLayoutAvailableHeight && this._lastLayoutAvailableHeight > 0