macd 추가수정
This commit is contained in:
@@ -43,7 +43,7 @@ import {
|
|||||||
} from './chartTimeFormat';
|
} from './chartTimeFormat';
|
||||||
import { DEFAULT_DISPLAY_TIMEZONE, getTimezoneOffsetSec } from './timezone';
|
import { DEFAULT_DISPLAY_TIMEZONE, getTimezoneOffsetSec } from './timezone';
|
||||||
import { getPaneHostId, sortIndicatorsForPaneLoad } from './indicatorPaneMerge';
|
import { getPaneHostId, sortIndicatorsForPaneLoad } from './indicatorPaneMerge';
|
||||||
import { calculateIndicator, enrichIndicatorConfig, getIndicatorDef, getHLineLabel, type PlotData, type MarkerData } from './indicatorRegistry';
|
import { calculateIndicator, enrichIndicatorConfig, getIndicatorDef, getHLineLabel, resolveHLineDrawPrice, type PlotData, type MarkerData } from './indicatorRegistry';
|
||||||
import { filterObvPlotDataForChart } from './customIndicators';
|
import { filterObvPlotDataForChart } from './customIndicators';
|
||||||
import { IchimokuCloudPlugin, type IchimokuCloudPoint } from './IchimokuCloudPlugin';
|
import { IchimokuCloudPlugin, type IchimokuCloudPoint } from './IchimokuCloudPlugin';
|
||||||
|
|
||||||
@@ -1249,7 +1249,7 @@ export class ChartManager {
|
|||||||
for (const hl of hlines) {
|
for (const hl of hlines) {
|
||||||
if (hl.visible === false) continue;
|
if (hl.visible === false) continue;
|
||||||
const pl = hlineHost.createPriceLine({
|
const pl = hlineHost.createPriceLine({
|
||||||
price: hl.price,
|
price: resolveHLineDrawPrice(config.type, hl, hlines),
|
||||||
color: hl.color,
|
color: hl.color,
|
||||||
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
||||||
lineStyle: toLineStyle(hl.lineStyle),
|
lineStyle: toLineStyle(hl.lineStyle),
|
||||||
@@ -3558,7 +3558,7 @@ export class ChartManager {
|
|||||||
for (const hl of hlines) {
|
for (const hl of hlines) {
|
||||||
if (hl.visible === false) continue;
|
if (hl.visible === false) continue;
|
||||||
const pl = hlineHost.createPriceLine({
|
const pl = hlineHost.createPriceLine({
|
||||||
price: hl.price,
|
price: resolveHLineDrawPrice(config.type, hl, hlines),
|
||||||
color: hl.color,
|
color: hl.color,
|
||||||
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
lineWidth: Math.min(4, hl.lineWidth ?? 1) as 1|2|3|4,
|
||||||
lineStyle: toLineStyle2(hl.lineStyle),
|
lineStyle: toLineStyle2(hl.lineStyle),
|
||||||
|
|||||||
@@ -157,6 +157,10 @@ export function mergeHlines(
|
|||||||
? savedList[0]
|
? savedList[0]
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
const defRoleLabels = new Set(
|
||||||
|
defs.map(d => d.label ?? getHLineLabel(d.price, defs.map(x => x.price))),
|
||||||
|
);
|
||||||
|
|
||||||
return defs
|
return defs
|
||||||
.map(def => {
|
.map(def => {
|
||||||
const wantLabel = def.label ?? getHLineLabel(def.price, defs.map(d => d.price));
|
const wantLabel = def.label ?? getHLineLabel(def.price, defs.map(d => d.price));
|
||||||
@@ -172,7 +176,9 @@ export function mergeHlines(
|
|||||||
.concat(
|
.concat(
|
||||||
savedList.filter(h => {
|
savedList.filter(h => {
|
||||||
const lbl = labelOf(h);
|
const lbl = labelOf(h);
|
||||||
return !defs.some(d => (d.label ?? getHLineLabel(d.price, defs.map(x => x.price))) === lbl);
|
if (defRoleLabels.has(lbl)) return false;
|
||||||
|
// registry에 없는 역할(잘못 분류된 과열/침체 orphan)은 제거 — 종가가 과열선으로 저장되는 MACD 버그 방지
|
||||||
|
return defRoleLabels.size > 1;
|
||||||
}).map(h => ({ ...h, label: labelOf(h) })),
|
}).map(h => ({ ...h, label: labelOf(h) })),
|
||||||
)
|
)
|
||||||
.sort((a, b) => b.price - a.price);
|
.sort((a, b) => b.price - a.price);
|
||||||
@@ -254,19 +260,64 @@ export function normalizeHLines(
|
|||||||
|
|
||||||
/** registry 기본 중앙선이 0인 지표에서 잘못 저장된 중앙선 가격을 0으로 고정 */
|
/** registry 기본 중앙선이 0인 지표에서 잘못 저장된 중앙선 가격을 0으로 고정 */
|
||||||
function clampZeroCenterHLines(hlines: HLineDef[], defaults?: HLineDef[]): HLineDef[] {
|
function clampZeroCenterHLines(hlines: HLineDef[], defaults?: HLineDef[]): HLineDef[] {
|
||||||
const defPrices = (defaults ?? []).map(d => d.price);
|
const defs = defaults ?? [];
|
||||||
const defCenter = (defaults ?? []).find(
|
const defPrices = defs.map(d => d.price);
|
||||||
|
const defCenter = defs.find(
|
||||||
d => (d.label ?? getHLineLabel(d.price, defPrices)) === '중앙선',
|
d => (d.label ?? getHLineLabel(d.price, defPrices)) === '중앙선',
|
||||||
);
|
);
|
||||||
if (defCenter?.price !== 0) return hlines;
|
if (defCenter?.price !== 0) return hlines;
|
||||||
|
|
||||||
const prices = hlines.map(h => h.price);
|
const defPriceSet = new Set(defPrices);
|
||||||
return hlines.map(h => {
|
let list = hlines;
|
||||||
|
// MACD·AO 등 중앙 0선 단일 def — registry에 없는 가격(종가 orphan) 제거
|
||||||
|
if (defs.length === 1 && defs[0].price === 0) {
|
||||||
|
const orphanWasVisible = hlines.some(h => {
|
||||||
|
const prices = hlines.map(x => x.price);
|
||||||
|
const lbl = h.label ?? getHLineLabel(h.price, prices);
|
||||||
|
return lbl !== '중앙선' && h.visible !== false && !defPriceSet.has(h.price);
|
||||||
|
});
|
||||||
|
list = hlines.filter(h => {
|
||||||
|
const prices = hlines.map(x => x.price);
|
||||||
|
const lbl = h.label ?? getHLineLabel(h.price, prices);
|
||||||
|
if (lbl === '중앙선') return true;
|
||||||
|
return defPriceSet.has(h.price);
|
||||||
|
});
|
||||||
|
if (orphanWasVisible) {
|
||||||
|
list = list.map(h => {
|
||||||
|
const prices = list.map(x => x.price);
|
||||||
|
const lbl = h.label ?? getHLineLabel(h.price, prices);
|
||||||
|
return lbl === '중앙선' ? { ...h, visible: true } : h;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prices = list.map(h => h.price);
|
||||||
|
return list.map(h => {
|
||||||
const lbl = h.label ?? getHLineLabel(h.price, prices);
|
const lbl = h.label ?? getHLineLabel(h.price, prices);
|
||||||
return lbl === '중앙선' ? { ...h, price: 0 } : h;
|
return lbl === '중앙선' ? { ...h, price: 0 } : h;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 차트 draw 시 hline 실제 가격 — 중앙 0선 지표는 항상 0 */
|
||||||
|
export function resolveHLineDrawPrice(
|
||||||
|
indicatorType: string,
|
||||||
|
hl: HLineDef,
|
||||||
|
allHlines: HLineDef[],
|
||||||
|
): number {
|
||||||
|
const def = getIndicatorDef(indicatorType);
|
||||||
|
const defaults = def?.hlines ?? [];
|
||||||
|
const defPrices = defaults.map(d => d.price);
|
||||||
|
const prices = allHlines.map(h => h.price);
|
||||||
|
const lbl = hl.label ?? getHLineLabel(hl.price, prices);
|
||||||
|
const defCenter = defaults.find(
|
||||||
|
d => (d.label ?? getHLineLabel(d.price, defPrices)) === '중앙선',
|
||||||
|
);
|
||||||
|
if (lbl === '중앙선' && defCenter?.price === 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return hl.price;
|
||||||
|
}
|
||||||
|
|
||||||
export interface IndicatorDef {
|
export interface IndicatorDef {
|
||||||
type: string;
|
type: string;
|
||||||
name: string;
|
name: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user