실시간 차트 보조지표 값 소수점 표시
This commit is contained in:
@@ -97,7 +97,12 @@ public class GcAppSettings {
|
|||||||
@Builder.Default
|
@Builder.Default
|
||||||
private Boolean btShowPrice = true;
|
private Boolean btShowPrice = true;
|
||||||
|
|
||||||
/** 보조지표 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
/** 캔들 영역(오버레이) 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
||||||
|
@Column(name = "chart_candle_area_price_labels", nullable = false)
|
||||||
|
@Builder.Default
|
||||||
|
private Boolean chartCandleAreaPriceLabels = true;
|
||||||
|
|
||||||
|
/** 하단 보조지표 pane 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
||||||
@Column(name = "chart_series_price_labels", nullable = false)
|
@Column(name = "chart_series_price_labels", nullable = false)
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private Boolean chartSeriesPriceLabels = true;
|
private Boolean chartSeriesPriceLabels = true;
|
||||||
|
|||||||
@@ -90,6 +90,8 @@ public class AppSettingsService {
|
|||||||
Boolean.parseBoolean(d.get("btAutoPopup").toString()));
|
Boolean.parseBoolean(d.get("btAutoPopup").toString()));
|
||||||
if (d.containsKey("btShowPrice")) s.setBtShowPrice(
|
if (d.containsKey("btShowPrice")) s.setBtShowPrice(
|
||||||
Boolean.parseBoolean(d.get("btShowPrice").toString()));
|
Boolean.parseBoolean(d.get("btShowPrice").toString()));
|
||||||
|
if (d.containsKey("chartCandleAreaPriceLabels")) s.setChartCandleAreaPriceLabels(
|
||||||
|
Boolean.parseBoolean(d.get("chartCandleAreaPriceLabels").toString()));
|
||||||
if (d.containsKey("chartSeriesPriceLabels")) s.setChartSeriesPriceLabels(
|
if (d.containsKey("chartSeriesPriceLabels")) s.setChartSeriesPriceLabels(
|
||||||
Boolean.parseBoolean(d.get("chartSeriesPriceLabels").toString()));
|
Boolean.parseBoolean(d.get("chartSeriesPriceLabels").toString()));
|
||||||
if (d.containsKey("chartVolumeVisible")) s.setChartVolumeVisible(
|
if (d.containsKey("chartVolumeVisible")) s.setChartVolumeVisible(
|
||||||
@@ -198,6 +200,7 @@ public class AppSettingsService {
|
|||||||
m.put("syncOptions", parseJson(s.getSyncOptionsJson()));
|
m.put("syncOptions", parseJson(s.getSyncOptionsJson()));
|
||||||
m.put("btAutoPopup", s.getBtAutoPopup() != null ? s.getBtAutoPopup() : true);
|
m.put("btAutoPopup", s.getBtAutoPopup() != null ? s.getBtAutoPopup() : true);
|
||||||
m.put("btShowPrice", s.getBtShowPrice() != null ? s.getBtShowPrice() : true);
|
m.put("btShowPrice", s.getBtShowPrice() != null ? s.getBtShowPrice() : true);
|
||||||
|
m.put("chartCandleAreaPriceLabels", s.getChartCandleAreaPriceLabels() != null ? s.getChartCandleAreaPriceLabels() : true);
|
||||||
m.put("chartSeriesPriceLabels", s.getChartSeriesPriceLabels() != null ? s.getChartSeriesPriceLabels() : true);
|
m.put("chartSeriesPriceLabels", s.getChartSeriesPriceLabels() != null ? s.getChartSeriesPriceLabels() : true);
|
||||||
m.put("chartVolumeVisible", s.getChartVolumeVisible() != null ? s.getChartVolumeVisible() : true);
|
m.put("chartVolumeVisible", s.getChartVolumeVisible() != null ? s.getChartVolumeVisible() : true);
|
||||||
m.put("chartLiveReceiveHighlight", s.getChartLiveReceiveHighlight() != null ? s.getChartLiveReceiveHighlight() : true);
|
m.put("chartLiveReceiveHighlight", s.getChartLiveReceiveHighlight() != null ? s.getChartLiveReceiveHighlight() : true);
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- V49: 캔들 차트 영역(오버레이 지표) 가격축 라벨·설명 — 보조지표 pane 과 분리
|
||||||
|
-- chart_series_price_labels = 하단 보조지표 pane (기존)
|
||||||
|
-- chart_candle_area_price_labels = 캔들·거래량 pane 위 오버레이 (pane 0~1)
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
ALTER TABLE gc_app_settings
|
||||||
|
ADD COLUMN chart_candle_area_price_labels TINYINT(1) NOT NULL DEFAULT 1
|
||||||
|
COMMENT '캔들 영역 오버레이 지표 가격축 라벨·설명 (1=ON, 0=OFF)';
|
||||||
|
|
||||||
|
UPDATE gc_app_settings
|
||||||
|
SET chart_candle_area_price_labels = chart_series_price_labels;
|
||||||
+23
-6
@@ -634,6 +634,7 @@ function App() {
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [appSettingsLoaded, dbLoaded]);
|
}, [appSettingsLoaded, dbLoaded]);
|
||||||
|
|
||||||
|
const chartCandleAreaPriceLabels = appDefaults.chartCandleAreaPriceLabels ?? true;
|
||||||
const chartSeriesPriceLabels = appDefaults.chartSeriesPriceLabels ?? true;
|
const chartSeriesPriceLabels = appDefaults.chartSeriesPriceLabels ?? true;
|
||||||
const chartVolumeVisible = appDefaults.chartVolumeVisible ?? true;
|
const chartVolumeVisible = appDefaults.chartVolumeVisible ?? true;
|
||||||
const chartLiveReceiveHighlight = appDefaults.chartLiveReceiveHighlight ?? true;
|
const chartLiveReceiveHighlight = appDefaults.chartLiveReceiveHighlight ?? true;
|
||||||
@@ -1007,9 +1008,13 @@ function App() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!appSettingsLoaded) return;
|
if (!appSettingsLoaded) return;
|
||||||
managerRef.current?.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels);
|
managerRef.current?.setCandleAreaPriceLabelsEnabled(chartCandleAreaPriceLabels);
|
||||||
slotRefs.current.forEach(slot => slot?.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels));
|
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||||
}, [appSettingsLoaded, chartSeriesPriceLabels]);
|
slotRefs.current.forEach(slot => {
|
||||||
|
slot?.setCandleAreaPriceLabelsEnabled(chartCandleAreaPriceLabels);
|
||||||
|
slot?.setIndicatorAreaPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||||
|
});
|
||||||
|
}, [appSettingsLoaded, chartCandleAreaPriceLabels, chartSeriesPriceLabels]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!appSettingsLoaded) return;
|
if (!appSettingsLoaded) return;
|
||||||
@@ -1789,6 +1794,7 @@ function App() {
|
|||||||
<TrendSearchPage
|
<TrendSearchPage
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={(appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP') as ChartRealtimeSource}
|
chartRealtimeSource={(appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP') as ChartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={appDefaults.chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={appDefaults.chartSeriesPriceLabels}
|
chartSeriesPriceLabels={appDefaults.chartSeriesPriceLabels}
|
||||||
tickers={marketTickers}
|
tickers={marketTickers}
|
||||||
/>
|
/>
|
||||||
@@ -1858,11 +1864,17 @@ function App() {
|
|||||||
onAddIndicatorToChart={handleAddIndicator}
|
onAddIndicatorToChart={handleAddIndicator}
|
||||||
onRemoveIndicatorFromChart={handleRemoveByType}
|
onRemoveIndicatorFromChart={handleRemoveByType}
|
||||||
onIndicatorListOrderChange={handleIndicatorListOrderChange}
|
onIndicatorListOrderChange={handleIndicatorListOrderChange}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
|
onChartCandleAreaPriceLabels={v => {
|
||||||
|
saveAppDef({ chartCandleAreaPriceLabels: v });
|
||||||
|
managerRef.current?.setCandleAreaPriceLabelsEnabled(v);
|
||||||
|
slotRefs.current.forEach(slot => slot?.setCandleAreaPriceLabelsEnabled(v));
|
||||||
|
}}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
onChartSeriesPriceLabels={v => {
|
onChartSeriesPriceLabels={v => {
|
||||||
saveAppDef({ chartSeriesPriceLabels: v });
|
saveAppDef({ chartSeriesPriceLabels: v });
|
||||||
managerRef.current?.setSeriesPriceLabelsEnabled(v);
|
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(v);
|
||||||
slotRefs.current.forEach(slot => slot?.setSeriesPriceLabelsEnabled(v));
|
slotRefs.current.forEach(slot => slot?.setIndicatorAreaPriceLabelsEnabled(v));
|
||||||
}}
|
}}
|
||||||
chartVolumeVisible={chartVolumeVisible}
|
chartVolumeVisible={chartVolumeVisible}
|
||||||
onChartVolumeVisible={v => {
|
onChartVolumeVisible={v => {
|
||||||
@@ -2201,6 +2213,7 @@ function App() {
|
|||||||
onSymbolChange={activeSlot === 0 ? handleActiveSlotSymbolChange : undefined}
|
onSymbolChange={activeSlot === 0 ? handleActiveSlotSymbolChange : undefined}
|
||||||
magnetMode={magnetMode}
|
magnetMode={magnetMode}
|
||||||
onTradeOrderRequest={(req, idx) => applyTradeFill(req, idx)}
|
onTradeOrderRequest={(req, idx) => applyTradeFill(req, idx)}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartVolumeVisible={chartVolumeVisible}
|
chartVolumeVisible={chartVolumeVisible}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
@@ -2242,6 +2255,7 @@ function App() {
|
|||||||
onSymbolChange={activeSlot === i + 1 ? handleActiveSlotSymbolChange : undefined}
|
onSymbolChange={activeSlot === i + 1 ? handleActiveSlotSymbolChange : undefined}
|
||||||
magnetMode={magnetMode}
|
magnetMode={magnetMode}
|
||||||
onTradeOrderRequest={(req, idx) => applyTradeFill(req, idx)}
|
onTradeOrderRequest={(req, idx) => applyTradeFill(req, idx)}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartVolumeVisible={chartVolumeVisible}
|
chartVolumeVisible={chartVolumeVisible}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
@@ -2301,7 +2315,8 @@ function App() {
|
|||||||
} else {
|
} else {
|
||||||
pendingRealtimeBarRef.current = null;
|
pendingRealtimeBarRef.current = null;
|
||||||
}
|
}
|
||||||
mgr.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels);
|
mgr.setCandleAreaPriceLabelsEnabled(chartCandleAreaPriceLabels);
|
||||||
|
mgr.setIndicatorAreaPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||||
const wrapper = document.querySelector('.chart-wrapper') as HTMLElement | null;
|
const wrapper = document.querySelector('.chart-wrapper') as HTMLElement | null;
|
||||||
mgr.setVolumeVisible(chartVolumeVisible, wrapper?.clientHeight);
|
mgr.setVolumeVisible(chartVolumeVisible, wrapper?.clientHeight);
|
||||||
mgr.setPaneSeparatorOptions(chartPaneSeparator);
|
mgr.setPaneSeparatorOptions(chartPaneSeparator);
|
||||||
@@ -2347,6 +2362,8 @@ function App() {
|
|||||||
onToggleIndicatorHidden={handleToggleIndicatorHidden}
|
onToggleIndicatorHidden={handleToggleIndicatorHidden}
|
||||||
onOpenIndicatorSettings={id => setSettingsModalId(id)}
|
onOpenIndicatorSettings={id => setSettingsModalId(id)}
|
||||||
volumeVisible={chartVolumeVisible}
|
volumeVisible={chartVolumeVisible}
|
||||||
|
candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
|
||||||
|
indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
|
||||||
paneSeparatorOptions={chartPaneSeparator}
|
paneSeparatorOptions={chartPaneSeparator}
|
||||||
/>
|
/>
|
||||||
{isSingleLoadingMore && (
|
{isSingleLoadingMore && (
|
||||||
|
|||||||
@@ -117,8 +117,10 @@ export interface ChartSlotHandle {
|
|||||||
setIndicators: (inds: IndicatorConfig[]) => void;
|
setIndicators: (inds: IndicatorConfig[]) => void;
|
||||||
/** 크로스헤어 자석모드 설정 */
|
/** 크로스헤어 자석모드 설정 */
|
||||||
setCrosshairMagnet: (enabled: boolean) => void;
|
setCrosshairMagnet: (enabled: boolean) => void;
|
||||||
/** 가격축 라벨·설명 on/off */
|
/** 가격축 라벨·설명 on/off (캔들·보조지표 동일 값) */
|
||||||
setSeriesPriceLabelsEnabled: (enabled: boolean) => void;
|
setSeriesPriceLabelsEnabled: (enabled: boolean) => void;
|
||||||
|
setCandleAreaPriceLabelsEnabled: (enabled: boolean) => void;
|
||||||
|
setIndicatorAreaPriceLabelsEnabled: (enabled: boolean) => void;
|
||||||
/** 거래량 pane on/off */
|
/** 거래량 pane on/off */
|
||||||
setVolumeVisible: (visible: boolean) => void;
|
setVolumeVisible: (visible: boolean) => void;
|
||||||
setPaneSeparatorOptions: (opts: ChartPaneSeparatorOptions) => void;
|
setPaneSeparatorOptions: (opts: ChartPaneSeparatorOptions) => void;
|
||||||
@@ -172,7 +174,9 @@ export interface ChartSlotProps {
|
|||||||
magnetMode?: 'off' | 'weak' | 'strong';
|
magnetMode?: 'off' | 'weak' | 'strong';
|
||||||
/** 차트 우클릭 → 매수·매도 패널 자동 입력 */
|
/** 차트 우클릭 → 매수·매도 패널 자동 입력 */
|
||||||
onTradeOrderRequest?: (req: { market: string; price: number; side: 'buy' | 'sell' }, slotIndex: number) => void;
|
onTradeOrderRequest?: (req: { market: string; price: number; side: 'buy' | 'sell' }, slotIndex: number) => void;
|
||||||
/** 보조지표 우측 가격축 라벨·설명 표시 */
|
/** 캔들 영역 오버레이 지표 가격축 라벨·설명 */
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
|
/** 하단 보조지표 pane 가격축 라벨·설명 */
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
/** 차트 하단 거래량 바 표시 */
|
/** 차트 하단 거래량 바 표시 */
|
||||||
chartVolumeVisible?: boolean;
|
chartVolumeVisible?: boolean;
|
||||||
@@ -206,6 +210,7 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
|||||||
onSymbolChange,
|
onSymbolChange,
|
||||||
magnetMode = 'off',
|
magnetMode = 'off',
|
||||||
onTradeOrderRequest,
|
onTradeOrderRequest,
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartVolumeVisible = true,
|
chartVolumeVisible = true,
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
@@ -331,6 +336,12 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
|||||||
setSeriesPriceLabelsEnabled: (enabled: boolean) => {
|
setSeriesPriceLabelsEnabled: (enabled: boolean) => {
|
||||||
managerRef.current?.setSeriesPriceLabelsEnabled(enabled);
|
managerRef.current?.setSeriesPriceLabelsEnabled(enabled);
|
||||||
},
|
},
|
||||||
|
setCandleAreaPriceLabelsEnabled: (enabled: boolean) => {
|
||||||
|
managerRef.current?.setCandleAreaPriceLabelsEnabled(enabled);
|
||||||
|
},
|
||||||
|
setIndicatorAreaPriceLabelsEnabled: (enabled: boolean) => {
|
||||||
|
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(enabled);
|
||||||
|
},
|
||||||
setVolumeVisible: (visible: boolean) => {
|
setVolumeVisible: (visible: boolean) => {
|
||||||
managerRef.current?.setVolumeVisible(visible);
|
managerRef.current?.setVolumeVisible(visible);
|
||||||
},
|
},
|
||||||
@@ -349,7 +360,11 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
|||||||
}, [magnetMode]);
|
}, [magnetMode]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
managerRef.current?.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels);
|
managerRef.current?.setCandleAreaPriceLabelsEnabled(chartCandleAreaPriceLabels);
|
||||||
|
}, [chartCandleAreaPriceLabels]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||||
}, [chartSeriesPriceLabels]);
|
}, [chartSeriesPriceLabels]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -855,6 +870,8 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
|||||||
drawingsVisible={!compactMode}
|
drawingsVisible={!compactMode}
|
||||||
showHoverToolbar={!compactMode}
|
showHoverToolbar={!compactMode}
|
||||||
volumeVisible={chartVolumeVisible}
|
volumeVisible={chartVolumeVisible}
|
||||||
|
candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
|
||||||
|
indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
|
||||||
paneSeparatorOptions={chartPaneSeparator}
|
paneSeparatorOptions={chartPaneSeparator}
|
||||||
crosshairInfoVisible={chartCrosshairInfoVisible}
|
crosshairInfoVisible={chartCrosshairInfoVisible}
|
||||||
onCrosshair={data => {
|
onCrosshair={data => {
|
||||||
@@ -873,7 +890,8 @@ const ChartSlot = forwardRef<ChartSlotHandle, ChartSlotProps>(function ChartSlot
|
|||||||
} else {
|
} else {
|
||||||
pendingRealtimeBarRef.current = null;
|
pendingRealtimeBarRef.current = null;
|
||||||
}
|
}
|
||||||
mgr.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels);
|
mgr.setCandleAreaPriceLabelsEnabled(chartCandleAreaPriceLabels);
|
||||||
|
mgr.setIndicatorAreaPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||||
mgr.setVolumeVisible(chartVolumeVisible);
|
mgr.setVolumeVisible(chartVolumeVisible);
|
||||||
if (chartPaneSeparator) mgr.setPaneSeparatorOptions(chartPaneSeparator);
|
if (chartPaneSeparator) mgr.setPaneSeparatorOptions(chartPaneSeparator);
|
||||||
// Time sync: 가시 시간 범위 변화 구독
|
// Time sync: 가시 시간 범위 변화 구독
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ export const SettingsOutputFooter: React.FC<{
|
|||||||
<div className="ism-row ism-ichimoku-extra-row">
|
<div className="ism-row ism-ichimoku-extra-row">
|
||||||
<span className="ism-label">가격축 라벨·설명</span>
|
<span className="ism-label">가격축 라벨·설명</span>
|
||||||
<div className="ism-control">
|
<div className="ism-control">
|
||||||
<label className="ism-toggle" title="이 지표만 우측 가격축 금액·설명 표시 (차트 설정 전역 스위치가 켜져 있을 때 적용)">
|
<label className="ism-toggle" title="이 지표만 우측 가격축 금액·설명 표시 (해당 영역·차트 설정 전역 스위치가 켜져 있을 때 적용)">
|
||||||
<input
|
<input
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
checked={lastValueVisible}
|
checked={lastValueVisible}
|
||||||
|
|||||||
@@ -110,6 +110,8 @@ interface SettingsPageProps {
|
|||||||
onRemoveIndicatorFromChart?: (type: string) => void;
|
onRemoveIndicatorFromChart?: (type: string) => void;
|
||||||
/** 보조지표 설정 목록 순서 변경 → 차트 pane 순서 */
|
/** 보조지표 설정 목록 순서 변경 → 차트 pane 순서 */
|
||||||
onIndicatorListOrderChange?: (orderedTypes: string[]) => void;
|
onIndicatorListOrderChange?: (orderedTypes: string[]) => void;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
|
onChartCandleAreaPriceLabels?: (v: boolean) => void;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
onChartSeriesPriceLabels?: (v: boolean) => void;
|
onChartSeriesPriceLabels?: (v: boolean) => void;
|
||||||
chartVolumeVisible?: boolean;
|
chartVolumeVisible?: boolean;
|
||||||
@@ -732,6 +734,8 @@ interface ChartPanelProps {
|
|||||||
onChartRealtimeSource?: (v: string) => void;
|
onChartRealtimeSource?: (v: string) => void;
|
||||||
magnetMode?: 'off' | 'weak' | 'strong';
|
magnetMode?: 'off' | 'weak' | 'strong';
|
||||||
onMagnetMode?: (m: 'off' | 'weak' | 'strong') => void;
|
onMagnetMode?: (m: 'off' | 'weak' | 'strong') => void;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
|
onChartCandleAreaPriceLabels?: (v: boolean) => void;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
onChartSeriesPriceLabels?: (v: boolean) => void;
|
onChartSeriesPriceLabels?: (v: boolean) => void;
|
||||||
chartVolumeVisible?: boolean;
|
chartVolumeVisible?: boolean;
|
||||||
@@ -752,6 +756,8 @@ const ChartPanel: React.FC<ChartPanelProps> = ({
|
|||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
onChartRealtimeSource,
|
onChartRealtimeSource,
|
||||||
magnetMode = 'off', onMagnetMode,
|
magnetMode = 'off', onMagnetMode,
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
|
onChartCandleAreaPriceLabels,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
onChartSeriesPriceLabels,
|
onChartSeriesPriceLabels,
|
||||||
chartVolumeVisible = true,
|
chartVolumeVisible = true,
|
||||||
@@ -869,9 +875,33 @@ const ChartPanel: React.FC<ChartPanelProps> = ({
|
|||||||
<span className="stg-toggle-slider" />
|
<span className="stg-toggle-slider" />
|
||||||
</label>
|
</label>
|
||||||
</SettingRow>
|
</SettingRow>
|
||||||
|
</SettingSection>
|
||||||
|
|
||||||
|
<SettingSection title="지표 가격축 라벨·설명">
|
||||||
|
<div className="stg-subsection-label">
|
||||||
|
캔들 차트 영역
|
||||||
|
<span className="stg-subsection-desc">캔들·거래량 pane 위에 겹쳐 표시되는 지표(이동평균·일목 등)</span>
|
||||||
|
</div>
|
||||||
<SettingRow
|
<SettingRow
|
||||||
label="지표 가격축 라벨·설명"
|
label="가격축 라벨·설명"
|
||||||
desc="켜면 보조지표 선마다 우측 가격축에 금액 하이라이트와 설명(전환선, 기준선 등)이 표시됩니다. 끄면 선만 표시됩니다."
|
desc="켜면 오버레이 지표 선마다 우측 가격축에 금액과 설명(전환선, 기준선 등)이 표시됩니다."
|
||||||
|
>
|
||||||
|
<label className="stg-toggle">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={chartCandleAreaPriceLabels}
|
||||||
|
onChange={e => onChartCandleAreaPriceLabels?.(e.target.checked)}
|
||||||
|
/>
|
||||||
|
<span className="stg-toggle-slider" />
|
||||||
|
</label>
|
||||||
|
</SettingRow>
|
||||||
|
<div className="stg-subsection-label stg-subsection-label--spaced">
|
||||||
|
보조지표 영역
|
||||||
|
<span className="stg-subsection-desc">캔들 아래 별도 pane에 표시되는 RSI·MACD 등</span>
|
||||||
|
</div>
|
||||||
|
<SettingRow
|
||||||
|
label="가격축 라벨·설명"
|
||||||
|
desc="켜면 하단 보조지표 pane의 선마다 우측 가격축에 금액과 설명이 표시됩니다. 끄면 선만 표시됩니다."
|
||||||
>
|
>
|
||||||
<label className="stg-toggle">
|
<label className="stg-toggle">
|
||||||
<input
|
<input
|
||||||
@@ -1611,6 +1641,8 @@ const SettingsPage: React.FC<SettingsPageProps> = ({
|
|||||||
onAddIndicatorToChart,
|
onAddIndicatorToChart,
|
||||||
onRemoveIndicatorFromChart,
|
onRemoveIndicatorFromChart,
|
||||||
onIndicatorListOrderChange,
|
onIndicatorListOrderChange,
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
|
onChartCandleAreaPriceLabels,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
onChartSeriesPriceLabels,
|
onChartSeriesPriceLabels,
|
||||||
chartVolumeVisible = true,
|
chartVolumeVisible = true,
|
||||||
@@ -1709,6 +1741,8 @@ const SettingsPage: React.FC<SettingsPageProps> = ({
|
|||||||
onChartRealtimeSource={onChartRealtimeSource}
|
onChartRealtimeSource={onChartRealtimeSource}
|
||||||
magnetMode={magnetMode}
|
magnetMode={magnetMode}
|
||||||
onMagnetMode={onMagnetMode}
|
onMagnetMode={onMagnetMode}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
|
onChartCandleAreaPriceLabels={onChartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
onChartSeriesPriceLabels={onChartSeriesPriceLabels}
|
onChartSeriesPriceLabels={onChartSeriesPriceLabels}
|
||||||
chartVolumeVisible={chartVolumeVisible}
|
chartVolumeVisible={chartVolumeVisible}
|
||||||
|
|||||||
@@ -137,7 +137,11 @@ interface TradingChartProps {
|
|||||||
volumeVisible?: boolean;
|
volumeVisible?: boolean;
|
||||||
/** 하단 호버 줌·스크롤 툴바 (기본 true) */
|
/** 하단 호버 줌·스크롤 툴바 (기본 true) */
|
||||||
showHoverToolbar?: boolean;
|
showHoverToolbar?: boolean;
|
||||||
/** 보조지표 우측 가격축 라벨·설명 (차트 설정, 기본 true) */
|
/** 캔들 영역 오버레이 지표 가격축 라벨·설명 (기본 true) */
|
||||||
|
candleAreaPriceLabelsEnabled?: boolean;
|
||||||
|
/** 하단 보조지표 pane 가격축 라벨·설명 (기본 true) */
|
||||||
|
indicatorAreaPriceLabelsEnabled?: boolean;
|
||||||
|
/** @deprecated candleArea + indicatorArea 동일 값 */
|
||||||
seriesPriceLabelsEnabled?: boolean;
|
seriesPriceLabelsEnabled?: boolean;
|
||||||
/** 실시간 차트 화면 표시 여부 — false 이면 숨김 중 무거운 재로드 지연 */
|
/** 실시간 차트 화면 표시 여부 — false 이면 숨김 중 무거운 재로드 지연 */
|
||||||
chartVisible?: boolean;
|
chartVisible?: boolean;
|
||||||
@@ -185,7 +189,9 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
displayTimezone = DEFAULT_DISPLAY_TIMEZONE,
|
displayTimezone = DEFAULT_DISPLAY_TIMEZONE,
|
||||||
volumeVisible = true,
|
volumeVisible = true,
|
||||||
showHoverToolbar = true,
|
showHoverToolbar = true,
|
||||||
seriesPriceLabelsEnabled = true,
|
candleAreaPriceLabelsEnabled,
|
||||||
|
indicatorAreaPriceLabelsEnabled,
|
||||||
|
seriesPriceLabelsEnabled,
|
||||||
chartVisible = true,
|
chartVisible = true,
|
||||||
paneSeparatorOptions,
|
paneSeparatorOptions,
|
||||||
paneLayoutClamp = false,
|
paneLayoutClamp = false,
|
||||||
@@ -335,9 +341,16 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
mgr.setVolumeVisible(volumeVisible, wrapperH > 0 ? wrapperH : undefined);
|
mgr.setVolumeVisible(volumeVisible, wrapperH > 0 ? wrapperH : undefined);
|
||||||
}, [volumeVisible]);
|
}, [volumeVisible]);
|
||||||
|
|
||||||
|
const resolvedCandlePriceLabels = candleAreaPriceLabelsEnabled ?? seriesPriceLabelsEnabled ?? true;
|
||||||
|
const resolvedIndicatorPriceLabels = indicatorAreaPriceLabelsEnabled ?? seriesPriceLabelsEnabled ?? true;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
managerRef.current?.setSeriesPriceLabelsEnabled(seriesPriceLabelsEnabled);
|
managerRef.current?.setCandleAreaPriceLabelsEnabled(resolvedCandlePriceLabels);
|
||||||
}, [seriesPriceLabelsEnabled]);
|
}, [resolvedCandlePriceLabels]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
managerRef.current?.setIndicatorAreaPriceLabelsEnabled(resolvedIndicatorPriceLabels);
|
||||||
|
}, [resolvedIndicatorPriceLabels]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!paneSeparatorOptions) return;
|
if (!paneSeparatorOptions) return;
|
||||||
@@ -773,7 +786,8 @@ const TradingChart: React.FC<TradingChartProps> = ({
|
|||||||
const wrapperH = wrapperRef.current?.clientHeight ?? 0;
|
const wrapperH = wrapperRef.current?.clientHeight ?? 0;
|
||||||
mgr.setVolumeVisible(false, wrapperH > 0 ? wrapperH : undefined);
|
mgr.setVolumeVisible(false, wrapperH > 0 ? wrapperH : undefined);
|
||||||
}
|
}
|
||||||
mgr.setSeriesPriceLabelsEnabled(seriesPriceLabelsEnabled);
|
mgr.setCandleAreaPriceLabelsEnabled(resolvedCandlePriceLabels);
|
||||||
|
mgr.setIndicatorAreaPriceLabelsEnabled(resolvedIndicatorPriceLabels);
|
||||||
if (paneSeparatorOptions) mgr.setPaneSeparatorOptions(paneSeparatorOptions);
|
if (paneSeparatorOptions) mgr.setPaneSeparatorOptions(paneSeparatorOptions);
|
||||||
onManagerReady(mgr);
|
onManagerReady(mgr);
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import '../styles/virtualTradingDashboard.css';
|
|||||||
interface Props {
|
interface Props {
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
tickers?: Map<string, TickerData>;
|
tickers?: Map<string, TickerData>;
|
||||||
}
|
}
|
||||||
@@ -43,6 +44,7 @@ interface Props {
|
|||||||
const TrendSearchPage: React.FC<Props> = ({
|
const TrendSearchPage: React.FC<Props> = ({
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
tickers,
|
tickers,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -256,6 +258,7 @@ const TrendSearchPage: React.FC<Props> = ({
|
|||||||
flashMarkets={flashMarkets}
|
flashMarkets={flashMarkets}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={defaults.chartPaneSeparator}
|
chartPaneSeparator={defaults.chartPaneSeparator}
|
||||||
tickers={tickers}
|
tickers={tickers}
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ const VirtualTradingPage: React.FC<Props> = ({
|
|||||||
const appChartDefaults = resolveAppDefaults(appSettings);
|
const appChartDefaults = resolveAppDefaults(appSettings);
|
||||||
const chartRealtimeSource = (appChartDefaults.chartRealtimeSource
|
const chartRealtimeSource = (appChartDefaults.chartRealtimeSource
|
||||||
?? 'BACKEND_STOMP') as ChartRealtimeSource;
|
?? 'BACKEND_STOMP') as ChartRealtimeSource;
|
||||||
|
const chartCandleAreaPriceLabels = appChartDefaults.chartCandleAreaPriceLabels;
|
||||||
const chartSeriesPriceLabels = appChartDefaults.chartSeriesPriceLabels;
|
const chartSeriesPriceLabels = appChartDefaults.chartSeriesPriceLabels;
|
||||||
const chartPaneSeparator = appChartDefaults.chartPaneSeparator;
|
const chartPaneSeparator = appChartDefaults.chartPaneSeparator;
|
||||||
const chartLiveReceiveHighlight = appChartDefaults.chartLiveReceiveHighlight;
|
const chartLiveReceiveHighlight = appChartDefaults.chartLiveReceiveHighlight;
|
||||||
@@ -453,6 +454,7 @@ const VirtualTradingPage: React.FC<Props> = ({
|
|||||||
onSelectMarket={handleSelectMarket}
|
onSelectMarket={handleSelectMarket}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ interface Props {
|
|||||||
timeframe: string;
|
timeframe: string;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
}
|
}
|
||||||
@@ -42,6 +43,7 @@ const TrendSearchCardChart: React.FC<Props> = ({
|
|||||||
timeframe,
|
timeframe,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -197,7 +199,8 @@ const TrendSearchCardChart: React.FC<Props> = ({
|
|||||||
magnifierEnabled={false}
|
magnifierEnabled={false}
|
||||||
volumeVisible
|
volumeVisible
|
||||||
showHoverToolbar={false}
|
showHoverToolbar={false}
|
||||||
seriesPriceLabelsEnabled={chartSeriesPriceLabels}
|
candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
|
||||||
|
indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
|
||||||
paneSeparatorOptions={chartPaneSeparator}
|
paneSeparatorOptions={chartPaneSeparator}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ interface Props {
|
|||||||
timeframe: string;
|
timeframe: string;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
}
|
}
|
||||||
@@ -39,6 +40,7 @@ const TrendSearchChartPanel: React.FC<Props> = ({
|
|||||||
timeframe,
|
timeframe,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
}) => {
|
}) => {
|
||||||
@@ -184,7 +186,8 @@ const TrendSearchChartPanel: React.FC<Props> = ({
|
|||||||
magnifierEnabled={false}
|
magnifierEnabled={false}
|
||||||
volumeVisible
|
volumeVisible
|
||||||
showHoverToolbar={false}
|
showHoverToolbar={false}
|
||||||
seriesPriceLabelsEnabled={chartSeriesPriceLabels}
|
candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
|
||||||
|
indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
|
||||||
paneSeparatorOptions={chartPaneSeparator}
|
paneSeparatorOptions={chartPaneSeparator}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ interface Props {
|
|||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
ticker?: TickerData;
|
ticker?: TickerData;
|
||||||
@@ -58,6 +59,7 @@ const TrendSearchResultCard: React.FC<Props> = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
ticker,
|
ticker,
|
||||||
@@ -140,6 +142,7 @@ const TrendSearchResultCard: React.FC<Props> = ({
|
|||||||
timeframe={timeframe}
|
timeframe={timeframe}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ interface Props {
|
|||||||
flashMarkets?: Set<string>;
|
flashMarkets?: Set<string>;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
tickers?: Map<string, TickerData>;
|
tickers?: Map<string, TickerData>;
|
||||||
@@ -37,6 +38,7 @@ const TrendSearchResultsCardGrid: React.FC<Props> = ({
|
|||||||
flashMarkets,
|
flashMarkets,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
tickers,
|
tickers,
|
||||||
@@ -85,6 +87,7 @@ const TrendSearchResultsCardGrid: React.FC<Props> = ({
|
|||||||
onSelect={onSelect ? () => onSelect(row) : undefined}
|
onSelect={onSelect ? () => onSelect(row) : undefined}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
ticker={tickers?.get(row.market)}
|
ticker={tickers?.get(row.market)}
|
||||||
|
|||||||
@@ -28,7 +28,9 @@ const VirtualStrategyChartPopup: React.FC<Props> = ({
|
|||||||
onClose,
|
onClose,
|
||||||
}) => {
|
}) => {
|
||||||
const { settings: appSettings } = useAppSettings();
|
const { settings: appSettings } = useAppSettings();
|
||||||
const chartSeriesPriceLabels = resolveAppDefaults(appSettings).chartSeriesPriceLabels;
|
const chartDefaults = resolveAppDefaults(appSettings);
|
||||||
|
const chartCandleAreaPriceLabels = chartDefaults.chartCandleAreaPriceLabels;
|
||||||
|
const chartSeriesPriceLabels = chartDefaults.chartSeriesPriceLabels;
|
||||||
|
|
||||||
const ko = getKoreanName(market);
|
const ko = getKoreanName(market);
|
||||||
const sym = market.replace(/^KRW-/, '');
|
const sym = market.replace(/^KRW-/, '');
|
||||||
@@ -56,6 +58,7 @@ const VirtualStrategyChartPopup: React.FC<Props> = ({
|
|||||||
theme={theme}
|
theme={theme}
|
||||||
running={running}
|
running={running}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
/>
|
/>
|
||||||
</AppPopup>
|
</AppPopup>
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ interface Props {
|
|||||||
onSelect?: () => void;
|
onSelect?: () => void;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
chartLiveReceiveHighlight?: boolean;
|
chartLiveReceiveHighlight?: boolean;
|
||||||
@@ -72,6 +73,7 @@ const VirtualTargetCard: React.FC<Props> = ({
|
|||||||
onSelect,
|
onSelect,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
chartLiveReceiveHighlight = true,
|
chartLiveReceiveHighlight = true,
|
||||||
@@ -194,6 +196,7 @@ const VirtualTargetCard: React.FC<Props> = ({
|
|||||||
theme={theme}
|
theme={theme}
|
||||||
running={running}
|
running={running}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
chartTimeframe={chartTimeframe}
|
chartTimeframe={chartTimeframe}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ interface Props {
|
|||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
running?: boolean;
|
running?: boolean;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
/** 전체보기 분할 pane — 캔버스 높이 100% */
|
/** 전체보기 분할 pane — 캔버스 높이 100% */
|
||||||
@@ -46,6 +47,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
|||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
running = false,
|
running = false,
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
fillHeight = false,
|
fillHeight = false,
|
||||||
@@ -261,7 +263,8 @@ const VirtualTargetCardChart: React.FC<Props> = ({
|
|||||||
showPaneLegend={false}
|
showPaneLegend={false}
|
||||||
showCandlePaneControls={false}
|
showCandlePaneControls={false}
|
||||||
defaultCandleOnly
|
defaultCandleOnly
|
||||||
seriesPriceLabelsEnabled={chartSeriesPriceLabels}
|
candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
|
||||||
|
indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
|
||||||
paneSeparatorOptions={chartPaneSeparator}
|
paneSeparatorOptions={chartPaneSeparator}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ interface Props {
|
|||||||
onExit: () => void;
|
onExit: () => void;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
chartLiveReceiveHighlight?: boolean;
|
chartLiveReceiveHighlight?: boolean;
|
||||||
@@ -55,6 +56,7 @@ const VirtualTargetFocusView: React.FC<Props> = ({
|
|||||||
onExit,
|
onExit,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
chartLiveReceiveHighlight = true,
|
chartLiveReceiveHighlight = true,
|
||||||
@@ -114,6 +116,7 @@ const VirtualTargetFocusView: React.FC<Props> = ({
|
|||||||
theme={theme}
|
theme={theme}
|
||||||
running={running}
|
running={running}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
fillHeight
|
fillHeight
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ interface Props {
|
|||||||
onSelectMarket?: (market: string) => void;
|
onSelectMarket?: (market: string) => void;
|
||||||
theme?: Theme;
|
theme?: Theme;
|
||||||
chartRealtimeSource?: ChartRealtimeSource;
|
chartRealtimeSource?: ChartRealtimeSource;
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
|
||||||
chartLiveReceiveHighlight?: boolean;
|
chartLiveReceiveHighlight?: boolean;
|
||||||
@@ -48,6 +49,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
|||||||
onSelectMarket,
|
onSelectMarket,
|
||||||
theme = 'dark',
|
theme = 'dark',
|
||||||
chartRealtimeSource = 'BACKEND_STOMP',
|
chartRealtimeSource = 'BACKEND_STOMP',
|
||||||
|
chartCandleAreaPriceLabels = true,
|
||||||
chartSeriesPriceLabels = true,
|
chartSeriesPriceLabels = true,
|
||||||
chartPaneSeparator,
|
chartPaneSeparator,
|
||||||
chartLiveReceiveHighlight = true,
|
chartLiveReceiveHighlight = true,
|
||||||
@@ -133,6 +135,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
|||||||
onExit={() => setFocusMarket(null)}
|
onExit={() => setFocusMarket(null)}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
||||||
@@ -172,6 +175,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
|
|||||||
onSelect={onSelectMarket ? () => onSelectMarket(t.market) : undefined}
|
onSelect={onSelectMarket ? () => onSelectMarket(t.market) : undefined}
|
||||||
theme={theme}
|
theme={theme}
|
||||||
chartRealtimeSource={chartRealtimeSource}
|
chartRealtimeSource={chartRealtimeSource}
|
||||||
|
chartCandleAreaPriceLabels={chartCandleAreaPriceLabels}
|
||||||
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
chartSeriesPriceLabels={chartSeriesPriceLabels}
|
||||||
chartPaneSeparator={chartPaneSeparator}
|
chartPaneSeparator={chartPaneSeparator}
|
||||||
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ export function resolveAppDefaults(s: AppSettingsDto) {
|
|||||||
syncOptions: (s.syncOptions as unknown as SyncOptions | null) ?? DEFAULT_SYNC,
|
syncOptions: (s.syncOptions as unknown as SyncOptions | null) ?? DEFAULT_SYNC,
|
||||||
btAutoPopup: s.btAutoPopup ?? true,
|
btAutoPopup: s.btAutoPopup ?? true,
|
||||||
btShowPrice: s.btShowPrice ?? true,
|
btShowPrice: s.btShowPrice ?? true,
|
||||||
|
chartCandleAreaPriceLabels: s.chartCandleAreaPriceLabels ?? s.chartSeriesPriceLabels ?? true,
|
||||||
chartSeriesPriceLabels: s.chartSeriesPriceLabels ?? true,
|
chartSeriesPriceLabels: s.chartSeriesPriceLabels ?? true,
|
||||||
chartVolumeVisible: s.chartVolumeVisible ?? true,
|
chartVolumeVisible: s.chartVolumeVisible ?? true,
|
||||||
chartLiveReceiveHighlight: s.chartLiveReceiveHighlight ?? true,
|
chartLiveReceiveHighlight: s.chartLiveReceiveHighlight ?? true,
|
||||||
|
|||||||
@@ -245,8 +245,10 @@ export class ChartManager {
|
|||||||
/** 현재 크로스헤어가 위에 있는 시리즈의 entryId ('__main__' | indicatorId | null) */
|
/** 현재 크로스헤어가 위에 있는 시리즈의 entryId ('__main__' | indicatorId | null) */
|
||||||
private _crosshairEntryId: string | null = null;
|
private _crosshairEntryId: string | null = null;
|
||||||
|
|
||||||
/** 우측 가격축 라벨·plot 설명(전환선 등)·금액 색상 하이라이트 */
|
/** 캔들 pane(0~1) 오버레이 지표 — 우측 가격축 라벨·설명 */
|
||||||
private _seriesPriceLabelsEnabled = true;
|
private _candleAreaPriceLabelsEnabled = true;
|
||||||
|
/** 하단 보조지표 pane(2+) — 우측 가격축 라벨·설명 */
|
||||||
|
private _indicatorAreaPriceLabelsEnabled = true;
|
||||||
|
|
||||||
/** 차트 하단 거래량 pane 표시 */
|
/** 차트 하단 거래량 pane 표시 */
|
||||||
private _volumeVisible = true;
|
private _volumeVisible = true;
|
||||||
@@ -514,12 +516,31 @@ export class ChartManager {
|
|||||||
fmt,
|
fmt,
|
||||||
);
|
);
|
||||||
this.chart.applyOptions({
|
this.chart.applyOptions({
|
||||||
localization: { timeFormatter, priceFormatter: formatChartAxisPrice },
|
localization: { timeFormatter },
|
||||||
timeScale: { tickMarkFormatter: this._tickMarkFormatter() },
|
timeScale: { tickMarkFormatter: this._tickMarkFormatter() },
|
||||||
});
|
});
|
||||||
|
this._applyAllSeriesPriceFormats();
|
||||||
this._notifyPaneLayout();
|
this._notifyPaneLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** pane별 priceFormat — 전역 priceFormatter 는 보조지표 라벨 포맷을 덮어씀 */
|
||||||
|
private _applyAllSeriesPriceFormats(): void {
|
||||||
|
if (this.mainSeries) {
|
||||||
|
try {
|
||||||
|
this.mainSeries.applyOptions({ priceFormat: MAIN_PRICE_FORMAT } as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
|
||||||
|
} catch { /* ok */ }
|
||||||
|
}
|
||||||
|
for (const entry of this.indicators.values()) {
|
||||||
|
const fmt = priceFormatForIndicatorPane(entry.paneIndex ?? 0);
|
||||||
|
if (!fmt) continue;
|
||||||
|
for (const series of entry.seriesList) {
|
||||||
|
try {
|
||||||
|
series.applyOptions({ priceFormat: fmt } as Parameters<ISeriesApi<SeriesType>['applyOptions']>[0]);
|
||||||
|
} catch { /* ok */ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setDisplayTimezone(tz: string, timeframe?: Timeframe, chartTimeFormat?: string): void {
|
setDisplayTimezone(tz: string, timeframe?: Timeframe, chartTimeFormat?: string): void {
|
||||||
this.displayTimezone = tz || DEFAULT_DISPLAY_TIMEZONE;
|
this.displayTimezone = tz || DEFAULT_DISPLAY_TIMEZONE;
|
||||||
if (timeframe) this.displayTimeframe = timeframe;
|
if (timeframe) this.displayTimeframe = timeframe;
|
||||||
@@ -688,7 +709,7 @@ export class ChartManager {
|
|||||||
seriesMeta.push({ plotId: plotDef.id, isHistogram: true, color: plotDef.color });
|
seriesMeta.push({ plotId: plotDef.id, isHistogram: true, color: plotDef.color });
|
||||||
} else {
|
} else {
|
||||||
const isPlotVisible = !indicatorHidden && config.plotVisibility?.[plotDef.id] !== false;
|
const isPlotVisible = !indicatorHidden && config.plotVisibility?.[plotDef.id] !== false;
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, true, pane);
|
||||||
const showSeriesTitle = pane < 2 && showPriceLabel;
|
const showSeriesTitle = pane < 2 && showPriceLabel;
|
||||||
series = this.chart.addSeries(LineSeries, {
|
series = this.chart.addSeries(LineSeries, {
|
||||||
color: plotDef.color,
|
color: plotDef.color,
|
||||||
@@ -777,6 +798,7 @@ export class ChartManager {
|
|||||||
this._removeOrphanSubPanes();
|
this._removeOrphanSubPanes();
|
||||||
if (this._activeIndicatorPaneIndices().size > 0) {
|
if (this._activeIndicatorPaneIndices().size > 0) {
|
||||||
this._resyncIndicatorPaneIndices();
|
this._resyncIndicatorPaneIndices();
|
||||||
|
this._applyAllSeriesPriceFormats();
|
||||||
} else {
|
} else {
|
||||||
this._trimTrailingEmptySubPanes();
|
this._trimTrailingEmptySubPanes();
|
||||||
}
|
}
|
||||||
@@ -1253,7 +1275,7 @@ export class ChartManager {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(_config, info.lastVal);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(_config, info.lastVal, pane);
|
||||||
const series = this.chart.addSeries(LineSeries, {
|
const series = this.chart.addSeries(LineSeries, {
|
||||||
color: info.color,
|
color: info.color,
|
||||||
lineWidth: 1,
|
lineWidth: 1,
|
||||||
@@ -2275,16 +2297,35 @@ export class ChartManager {
|
|||||||
series.applyOptions(opts as any);
|
series.applyOptions(opts as any);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 차트 설정: 보조지표 우측 가격축 라벨·설명 on/off */
|
/** 차트 설정: 캔들·보조지표 영역 가격축 라벨·설명 (동일 값이면 기존 API 호환) */
|
||||||
setSeriesPriceLabelsEnabled(enabled: boolean): void {
|
setSeriesPriceLabelsEnabled(enabled: boolean): void {
|
||||||
this._seriesPriceLabelsEnabled = enabled;
|
this.setCandleAreaPriceLabelsEnabled(enabled);
|
||||||
|
this.setIndicatorAreaPriceLabelsEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
setCandleAreaPriceLabelsEnabled(enabled: boolean): void {
|
||||||
|
this._candleAreaPriceLabelsEnabled = enabled;
|
||||||
|
this._refreshPriceLabelStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
setIndicatorAreaPriceLabelsEnabled(enabled: boolean): void {
|
||||||
|
this._indicatorAreaPriceLabelsEnabled = enabled;
|
||||||
|
this._refreshPriceLabelStyles();
|
||||||
|
}
|
||||||
|
|
||||||
|
getCandleAreaPriceLabelsEnabled(): boolean {
|
||||||
|
return this._candleAreaPriceLabelsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndicatorAreaPriceLabelsEnabled(): boolean {
|
||||||
|
return this._indicatorAreaPriceLabelsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _refreshPriceLabelStyles(): void {
|
||||||
for (const entry of this.indicators.values()) {
|
for (const entry of this.indicators.values()) {
|
||||||
this.applyIndicatorStyle(entry.config);
|
this.applyIndicatorStyle(entry.config);
|
||||||
}
|
}
|
||||||
}
|
this._applyAllSeriesPriceFormats();
|
||||||
|
|
||||||
getSeriesPriceLabelsEnabled(): boolean {
|
|
||||||
return this._seriesPriceLabelsEnabled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 차트 설정: 거래량 pane 표시 on/off */
|
/** 차트 설정: 거래량 pane 표시 on/off */
|
||||||
@@ -2308,8 +2349,12 @@ export class ChartManager {
|
|||||||
private shouldShowSeriesPriceLabel(
|
private shouldShowSeriesPriceLabel(
|
||||||
config: IndicatorConfig,
|
config: IndicatorConfig,
|
||||||
plotAllowsLastValue = true,
|
plotAllowsLastValue = true,
|
||||||
|
paneIndex = 0,
|
||||||
): boolean {
|
): boolean {
|
||||||
return this._seriesPriceLabelsEnabled
|
const areaEnabled = paneIndex < 2
|
||||||
|
? this._candleAreaPriceLabelsEnabled
|
||||||
|
: this._indicatorAreaPriceLabelsEnabled;
|
||||||
|
return areaEnabled
|
||||||
&& plotAllowsLastValue
|
&& plotAllowsLastValue
|
||||||
&& config.lastValueVisible !== false;
|
&& config.lastValueVisible !== false;
|
||||||
}
|
}
|
||||||
@@ -2318,8 +2363,9 @@ export class ChartManager {
|
|||||||
config: IndicatorConfig,
|
config: IndicatorConfig,
|
||||||
plot: PlotDef | undefined,
|
plot: PlotDef | undefined,
|
||||||
plotAllowsLastValue = true,
|
plotAllowsLastValue = true,
|
||||||
|
paneIndex = 0,
|
||||||
): string {
|
): string {
|
||||||
if (!this.shouldShowSeriesPriceLabel(config, plotAllowsLastValue)) return '';
|
if (!this.shouldShowSeriesPriceLabel(config, plotAllowsLastValue, paneIndex)) return '';
|
||||||
if (config.type === 'IchimokuCloud' && plot?.id) {
|
if (config.type === 'IchimokuCloud' && plot?.id) {
|
||||||
return getIchimokuPlotTitle(plot.id);
|
return getIchimokuPlotTitle(plot.id);
|
||||||
}
|
}
|
||||||
@@ -2362,10 +2408,10 @@ export class ChartManager {
|
|||||||
if (entry.type === 'IchimokuCloud') {
|
if (entry.type === 'IchimokuCloud') {
|
||||||
plotAllows = entry.seriesMeta[i]?.plotId !== 'plot2';
|
plotAllows = entry.seriesMeta[i]?.plotId !== 'plot2';
|
||||||
}
|
}
|
||||||
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, plotAllows);
|
const showPriceLabel = this.shouldShowSeriesPriceLabel(config, plotAllows, paneIdx);
|
||||||
opts['lastValueVisible'] = showPriceLabel;
|
opts['lastValueVisible'] = showPriceLabel;
|
||||||
opts['title'] = paneIdx < 2 && showPriceLabel
|
opts['title'] = paneIdx < 2 && showPriceLabel
|
||||||
? this.seriesTitleForPlot(config, plot, plotAllows)
|
? this.seriesTitleForPlot(config, plot, plotAllows, paneIdx)
|
||||||
: '';
|
: '';
|
||||||
} else {
|
} else {
|
||||||
opts['color'] = plot.color ?? '#aaa';
|
opts['color'] = plot.color ?? '#aaa';
|
||||||
|
|||||||
@@ -386,7 +386,9 @@ export interface AppSettingsDto {
|
|||||||
btAutoPopup?: boolean;
|
btAutoPopup?: boolean;
|
||||||
/** 백테스팅 매수/매도 마커에 금액 표시 여부 (기본 true) */
|
/** 백테스팅 매수/매도 마커에 금액 표시 여부 (기본 true) */
|
||||||
btShowPrice?: boolean;
|
btShowPrice?: boolean;
|
||||||
/** 보조지표 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
/** 캔들 영역 오버레이 지표 가격축 라벨·설명 (기본 true) */
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
|
/** 하단 보조지표 pane 가격축 라벨·설명 (기본 true) */
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
/** 차트 하단 거래량 바 표시 (기본 true) */
|
/** 차트 하단 거래량 바 표시 (기본 true) */
|
||||||
chartVolumeVisible?: boolean;
|
chartVolumeVisible?: boolean;
|
||||||
|
|||||||
@@ -471,6 +471,7 @@ export interface AppSettingsDto {
|
|||||||
/** 백테스팅 매수/매도 마커에 금액 표시 여부 (기본 true) */
|
/** 백테스팅 매수/매도 마커에 금액 표시 여부 (기본 true) */
|
||||||
btShowPrice?: boolean;
|
btShowPrice?: boolean;
|
||||||
/** 보조지표 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
/** 보조지표 우측 가격축 라벨·설명·금액 하이라이트 (기본 true) */
|
||||||
|
chartCandleAreaPriceLabels?: boolean;
|
||||||
chartSeriesPriceLabels?: boolean;
|
chartSeriesPriceLabels?: boolean;
|
||||||
/** 차트 하단 거래량 바 표시 (기본 true) */
|
/** 차트 하단 거래량 바 표시 (기본 true) */
|
||||||
chartVolumeVisible?: boolean;
|
chartVolumeVisible?: boolean;
|
||||||
|
|||||||
Reference in New Issue
Block a user