전략 시간봉 오류 수정
This commit is contained in:
@@ -147,11 +147,20 @@ function shouldShowBbBandFill(config: IndicatorConfig): boolean {
|
||||
}
|
||||
|
||||
function attachBbBandFill(entry: IndicatorEntry, config: IndicatorConfig): void {
|
||||
if (!shouldShowBbBandFill(config)) {
|
||||
detachBbBandFill(entry);
|
||||
return;
|
||||
}
|
||||
const basis = seriesByPlotId(entry, 'plot0');
|
||||
const upper = seriesByPlotId(entry, 'plot1');
|
||||
const lower = seriesByPlotId(entry, 'plot2');
|
||||
if (!basis || !upper || !lower || !shouldShowBbBandFill(config)) return;
|
||||
if (!basis || !upper || !lower) return;
|
||||
const bg = resolveBbBandBackground(config.bandBackground);
|
||||
if (entry.bbFillPrimitive) {
|
||||
entry.bbFillPrimitive.updateBackground(bg);
|
||||
entry.bbFillPrimitive.requestRefresh();
|
||||
return;
|
||||
}
|
||||
entry.bbFillPrimitive = new BollingerBandFillPrimitive(upper, lower, bg);
|
||||
basis.attachPrimitive(entry.bbFillPrimitive);
|
||||
}
|
||||
|
||||
@@ -329,10 +329,10 @@ export async function saveIndicatorSettings(
|
||||
* 앱 시작 시 호출 — 전역 시각 기본값을 DB 에서 가져온다.
|
||||
*/
|
||||
export async function loadIndicatorVisualSettings(): Promise<
|
||||
Record<string, { plots?: unknown[]; hlines?: unknown[] }>
|
||||
Record<string, { plots?: unknown[]; hlines?: unknown[]; cloudColors?: unknown; bandBackground?: unknown }>
|
||||
> {
|
||||
return (
|
||||
(await request<Record<string, { plots?: unknown[]; hlines?: unknown[] }>>(
|
||||
(await request<Record<string, { plots?: unknown[]; hlines?: unknown[]; cloudColors?: unknown; bandBackground?: unknown }>>(
|
||||
'/indicator-settings/visual'
|
||||
)) ?? {}
|
||||
);
|
||||
@@ -347,7 +347,7 @@ export async function loadIndicatorVisualSettings(): Promise<
|
||||
*/
|
||||
export async function saveIndicatorVisualSettings(
|
||||
indicatorType: string,
|
||||
visual: { plots?: unknown[]; hlines?: unknown[] }
|
||||
visual: { plots?: unknown[]; hlines?: unknown[]; cloudColors?: unknown; bandBackground?: unknown },
|
||||
): Promise<void> {
|
||||
await request(`/indicator-settings/${encodeURIComponent(indicatorType)}/visual`, {
|
||||
method: 'PATCH',
|
||||
|
||||
@@ -151,7 +151,7 @@ type GetVisual = (
|
||||
type: string,
|
||||
defaultPlots?: PlotDef[],
|
||||
defaultHlines?: HLineDef[],
|
||||
) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors };
|
||||
) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors; bandBackground?: import('../types').HlinesBackground };
|
||||
|
||||
/** 탭 전체 추가 — 기존 차트 지표를 제거하고 types 목록만 새로 구성 */
|
||||
export function replaceIndicatorConfigsFromTypes(
|
||||
@@ -181,7 +181,7 @@ export function buildIndicatorConfigsFromTypes(
|
||||
seen.add(type);
|
||||
|
||||
const params = getParams(type, def.defaultParams);
|
||||
const { plots, hlines, cloudColors } = getVisualConfig(type, def.plots, def.hlines);
|
||||
const { plots, hlines, cloudColors, bandBackground } = getVisualConfig(type, def.plots, def.hlines);
|
||||
let cfg: IndicatorConfig = {
|
||||
id: newId(),
|
||||
type: def.type,
|
||||
@@ -189,6 +189,7 @@ export function buildIndicatorConfigsFromTypes(
|
||||
plots,
|
||||
hlines,
|
||||
...(cloudColors ? { cloudColors } : {}),
|
||||
...(bandBackground ? { bandBackground } : {}),
|
||||
};
|
||||
if (type === 'SMA') {
|
||||
cfg = normalizeSmaConfig({
|
||||
|
||||
@@ -54,7 +54,7 @@ export function initializeIndicatorConfigForEditor(
|
||||
type: string,
|
||||
defaultPlots: PlotDef[],
|
||||
defaultHlines?: HLineDef[],
|
||||
) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors },
|
||||
) => { plots: PlotDef[]; hlines: HLineDef[]; cloudColors?: IchimokuCloudColors; bandBackground?: HlinesBackground },
|
||||
): IndicatorConfig {
|
||||
const def = getIndicatorDef(raw.type);
|
||||
if (!def) return enrichIndicatorConfig(raw);
|
||||
@@ -70,6 +70,7 @@ export function initializeIndicatorConfigForEditor(
|
||||
plots: raw.plots?.length ? raw.plots : visual?.plots,
|
||||
hlines: raw.hlines?.length ? raw.hlines : visual?.hlines,
|
||||
cloudColors: raw.cloudColors ?? visual?.cloudColors,
|
||||
bandBackground: raw.bandBackground ?? visual?.bandBackground,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -68,12 +68,27 @@ export function resolveHistogramDownColor(plot: PlotDef): string {
|
||||
return plot.histogramDownColor ?? DEFAULT_HIST_DOWN;
|
||||
}
|
||||
|
||||
/** MACD 등 histogram 막대 색 (상승·하락/음수 구분) */
|
||||
/** MACD 히스토그램 — histogramUp/DownColor 로 0선 위·아래 색 분리 */
|
||||
export function isMacdDualHistogramPlot(plot: PlotDef): boolean {
|
||||
return plot.type === 'histogram'
|
||||
&& plot.histogramUpColor != null
|
||||
&& plot.histogramDownColor != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* histogram 막대 색.
|
||||
* - MACD(상·하 색 지정): 0선 기준 — 양수=상승색, 음수=하락색 (전봴 대비 혼합 없음)
|
||||
* - 기타: 전봴 대비 방향 + 음수 영역 하락색
|
||||
*/
|
||||
export function histogramBarColor(
|
||||
value: number,
|
||||
prev: number | null | undefined,
|
||||
plot: PlotDef,
|
||||
): string {
|
||||
if (isMacdDualHistogramPlot(plot)) {
|
||||
const raw = value < 0 ? resolveHistogramDownColor(plot) : resolveHistogramUpColor(plot);
|
||||
return withHistogramAlpha(raw);
|
||||
}
|
||||
const isDown = prev != null && !isNaN(prev) && value < prev;
|
||||
const isNeg = value < 0;
|
||||
const raw = (isDown || isNeg) ? resolveHistogramDownColor(plot) : resolveHistogramUpColor(plot);
|
||||
|
||||
@@ -399,6 +399,31 @@ export function collectTimeframesFromEditorState(state: EditorConditionState): s
|
||||
return [...set];
|
||||
}
|
||||
|
||||
/** 매수·매도 START(기본) 평가 분봉을 동일하게 맞춤 — 한쪽만 3m·5m 체크 시 다른 쪽 1m 잔존 방지 */
|
||||
export function syncBuySellPrimaryStartCandleTypes(
|
||||
buy: EditorConditionState,
|
||||
sell: EditorConditionState,
|
||||
candleTypes: string[],
|
||||
): { buy: EditorConditionState; sell: EditorConditionState } {
|
||||
const types = normalizeCandleTypesList(candleTypes);
|
||||
return {
|
||||
buy: updateStartCandleTypes(buy, START_NODE_ID, types),
|
||||
sell: updateStartCandleTypes(sell, START_NODE_ID, types),
|
||||
};
|
||||
}
|
||||
|
||||
/** 저장 직전 — 양쪽 START 분봉 합집합을 각 탭에 반영 (매수만 설정한 경우 매도 DSL도 동기화) */
|
||||
export function alignBuySellStartCandleTypesForSave(
|
||||
buy: EditorConditionState,
|
||||
sell: EditorConditionState,
|
||||
): { buy: EditorConditionState; sell: EditorConditionState } {
|
||||
const merged = normalizeCandleTypesList([
|
||||
...getStartCandleTypes(buy.startMeta[START_NODE_ID]),
|
||||
...getStartCandleTypes(sell.startMeta[START_NODE_ID]),
|
||||
]);
|
||||
return syncBuySellPrimaryStartCandleTypes(buy, sell, merged);
|
||||
}
|
||||
|
||||
/** 저장된 DSL에서 Logic Expression용 분기 목록 */
|
||||
export function collectDslBranches(dsl: LogicNode | null): ConditionBranch[] {
|
||||
return collectEditorBranches(decodeConditionForEditor(dsl));
|
||||
|
||||
Reference in New Issue
Block a user