stochastic slow 중앙선 안나오는 문제 수정

This commit is contained in:
Macbook
2026-05-24 22:24:18 +09:00
parent 3c66c562d8
commit ca249ad318
5 changed files with 55 additions and 13 deletions
+4 -2
View File
@@ -22,7 +22,7 @@
*/
import { useEffect, useRef, useCallback } from 'react';
import { getIndicatorDef, mergePlotDefs, PlotDef, HLineDef } from '../utils/indicatorRegistry';
import { getIndicatorDef, mergePlotDefs, normalizeHLines, PlotDef, HLineDef } from '../utils/indicatorRegistry';
import { createDefaultSmaParams, createDefaultSmaPlots, normalizeSmaConfig } from '../utils/smaConfig';
import { normalizeIchimokuConfig, mergeIchimokuPlots } from '../utils/ichimokuConfig';
import {
@@ -170,7 +170,9 @@ export function useIndicatorSettings(sessionKey = 0) {
const def = getIndicatorDef(type);
const registryPlots = defaultPlots ?? def?.plots ?? [];
let plots = mergePlotDefs(saved?.plots as PlotDef[] | undefined, registryPlots);
const hlines = (saved?.hlines as HLineDef[] | undefined) ?? defaultHlines ?? def?.hlines ?? [];
const registryHlines = defaultHlines ?? def?.hlines ?? [];
const rawHlines = (saved?.hlines as HLineDef[] | undefined) ?? registryHlines;
const hlines = normalizeHLines(rawHlines, type, registryHlines);
if (type === 'SMA') {
plots = normalizeSmaConfig({
+1 -1
View File
@@ -27,7 +27,7 @@ export const MAIN_INDICATOR_TYPES: readonly string[] = [
/** Main 탭 전용 표시 라벨 (업비트 주요 지표 명칭) */
export const MAIN_INDICATOR_LABELS: Record<string, { ko: string; en: string }> = {
RSI: { ko: 'RSI (상대강도지수)', en: 'Relative Strength Index' },
Stochastic: { ko: 'Stochastic Oscillator', en: 'Stochastic Oscillator' },
Stochastic: { ko: 'Stochastic Slow', en: 'Stochastic Slow' },
BollingerBands: { ko: '볼린저밴드', en: 'Bollinger Bands' },
IchimokuCloud: { ko: '일목균형표', en: 'Ichimoku Cloud' },
ADX: { ko: 'ADX (평균방향성지수)', en: 'Average Directional Index' },
+33 -5
View File
@@ -73,12 +73,33 @@ function migrateHLineLabel(label: string | undefined): string | undefined {
return label;
}
/** normalizeHLines 합성 중앙선(0) 등 레거시 저장값을 registry 기본 가격으로 교정 */
function resolveMergedHLinePrice(
roleLabel: string,
savedPrice: number,
defPrice: number,
): number {
if (roleLabel === '중앙선' && savedPrice === 0 && defPrice !== 0) {
return defPrice;
}
return savedPrice;
}
/** 지표별 누락 수평선 합성 기본값 */
const HL_SYNTH_DEFAULTS: Record<string, { over: number; mid: number; under: number }> = {
ADX: { over: 40, mid: 25, under: 20 },
DMI: { over: 30, mid: 20, under: 10 },
ADX: { over: 40, mid: 25, under: 20 },
DMI: { over: 30, mid: 20, under: 10 },
Stochastic: { over: 80, mid: 50, under: 20 },
StochRSI: { over: 80, mid: 50, under: 20 },
};
/** Stochastic Slow 기본 수평선 — 과열 80 / 중앙 50(기본 off) / 침체 20 */
export const STOCHASTIC_DEFAULT_HLINES: HLineDef[] = [
{ price: 80, color: '#EF5350', label: '과열선', lineStyle: 'dashed', lineWidth: 1 },
{ price: 50, color: '#607D8B', label: '중앙선', lineStyle: 'dashed', lineWidth: 1, visible: false },
{ price: 20, color: '#4CAF50', label: '침체선', lineStyle: 'dashed', lineWidth: 1 },
];
/** ADX 기본 수평선 — 강한 추세(과열) / 기준(중앙) / 약한 추세(침체) */
export const ADX_DEFAULT_HLINES: HLineDef[] = [
{ price: 40, color: '#EF5350', label: '과열선', lineStyle: 'dashed', lineWidth: 1 },
@@ -130,10 +151,17 @@ export function mergeHlines(
savedList.find(h => labelOf(h) === wantLabel)
?? (legacyMid && wantLabel === '중앙선' ? legacyMid : undefined);
if (match) {
return { ...def, ...match, label: wantLabel, price: match.price };
const price = resolveMergedHLinePrice(wantLabel, match.price, def.price);
return { ...def, ...match, label: wantLabel, price };
}
return { ...def, label: wantLabel };
})
.concat(
savedList.filter(h => {
const lbl = labelOf(h);
return !defs.some(d => (d.label ?? getHLineLabel(d.price, defs.map(x => x.price))) === lbl);
}).map(h => ({ ...h, label: labelOf(h) })),
)
.sort((a, b) => b.price - a.price);
}
@@ -257,8 +285,8 @@ export const INDICATOR_REGISTRY: IndicatorDef[] = [
// ── Oscillators ───────────────────────────────────────────────────────────
{ type:'RSI', name:'Relative Strength Index', koreanName:'상대강도지수', shortName:'RSI', category:'Oscillators', overlay:false, defaultParams:{length:14, src:'close', maType:'SMA', maLength:14}, plots:[{id:'plot0',title:'RSI',color:'#7E57C2',type:'line',lineWidth:2},{id:'plot1',title:'Signal',color:'#F23645',type:'line',lineWidth:1}], hlines:[{price:70,color:'#EF5350'},{price:50,color:'#607D8B'},{price:30,color:'#4CAF50'}], description:'상대 강도 지수 (0~100)' },
{ type:'Stochastic', name:'Stochastic', koreanName:'스토스틱', shortName:'Stoch', category:'Oscillators', overlay:false, defaultParams:{kLength:14, dSmoothing:3, smooth:3}, plots:[{id:'plot0',title:'%K',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'%D',color:'#FF6D00',type:'line',lineWidth:1}], hlines:[{price:80,color:'#EF5350'},{price:20,color:'#4CAF50'}], description:'스토캐스틱 %K/%D' },
{ type:'StochRSI', name:'Stochastic RSI', koreanName:'스토캐스틱RSI', shortName:'StochRSI',category:'Oscillators',overlay:false, defaultParams:{lengthRSI:14, lengthStoch:14, smoothK:3, smoothD:3, src:'close'}, plots:[{id:'plot0',title:'%K',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'%D',color:'#FF6D00',type:'line',lineWidth:1}], hlines:[{price:80,color:'#EF5350'},{price:20,color:'#4CAF50'}], description:'스토캐스틱 RSI' },
{ type:'Stochastic', name:'Stochastic Slow', koreanName:'스토스틱 슬로우', shortName:'Stoch', category:'Oscillators', overlay:false, defaultParams:{kLength:14, dSmoothing:3, smooth:3}, plots:[{id:'plot0',title:'%K',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'%D',color:'#FF6D00',type:'line',lineWidth:1}], hlines:STOCHASTIC_DEFAULT_HLINES, description:'Stochastic Slow %K/%D (Slowing 적용)' },
{ type:'StochRSI', name:'Stochastic RSI', koreanName:'스토캐스틱RSI', shortName:'StochRSI',category:'Oscillators',overlay:false, defaultParams:{lengthRSI:14, lengthStoch:14, smoothK:3, smoothD:3, src:'close'}, plots:[{id:'plot0',title:'%K',color:'#2196F3',type:'line',lineWidth:1},{id:'plot1',title:'%D',color:'#FF6D00',type:'line',lineWidth:1}], hlines:STOCHASTIC_DEFAULT_HLINES, description:'스토캐스틱 RSI' },
{ type:'CCI', name:'Commodity Channel Index', koreanName:'상품채널지수', shortName:'CCI', category:'Oscillators', overlay:false, defaultParams:{length:13, src:'hlc3', maType:'SMA', maLength:20}, plots:[{id:'plot0',title:'CCI',color:'#2962FF',type:'line',lineWidth:2},{id:'plot1',title:'Signal',color:'#F23645',type:'line',lineWidth:1}], hlines:[{price:100,color:'#EF5350'},{price:0,color:'#607D8B'},{price:-100,color:'#4CAF50'}], description:'상품 채널 지수' },
{ type:'WilliamsPercentRange',name:'Williams %R', koreanName:'윌리엄스 %R', shortName:'W%R', category:'Oscillators', overlay:false, defaultParams:{length:14, src:'close'}, plots:[{id:'plot0',title:'%R', color:'#9C27B0',type:'line',lineWidth:2}], hlines:[{price:-20,color:'#EF5350'},{price:-50,color:'#607D8B'},{price:-80,color:'#4CAF50'}], description:'윌리엄스 %R 오실레이터' },
{ type:'AwesomeOscillator', name:'Awesome Oscillator', koreanName:'어썸오실레이터', shortName:'AO', category:'Oscillators', overlay:false, defaultParams:{}, plots:[{id:'plot0',title:'AO',color:'#26A69A',type:'histogram'}], hlines:[{price:0,color:'#607D8B'}], description:'AO 오실레이터' },