Skip to content

봉 번호 좌표계

같은 일봉(주말 휴장)을 두 좌표계로 — 위는 연속 시간축이라 주말이 공백으로 보이고, 아래는 봉 번호축(barIndexX)이라 봉이 빈틈없이 붙는다.

소스

apps/examples/src/cases/bar-index.ts — CI가 타입체크하는 실물이다.

ts
import { PlotBuilder, browserDeps } from "@finchart/dom";
import type { OHLC } from "@finchart/core";
import { barIndexX, candleSeries, priceFormat, timeTicks } from "@finchart/core";
import { fixtureCandles } from "./fixture";
import { chartHost } from "./stage";

export const title = "봉 번호 좌표계";
export const description =
  "같은 일봉(주말 휴장)을 두 좌표계로 — 위는 연속 시간축이라 주말이 공백으로 보이고, 아래는 봉 번호축(barIndexX)이라 봉이 빈틈없이 붙는다.";

const DAY = 86_400_000;
const MONDAY = Date.UTC(2026, 0, 5);

/** 거래일만 있는 일봉 — 다섯 봉마다 이틀(주말)이 빈다. */
function weekdayCandles(): OHLC[] {
  return fixtureCandles(90).map((candle, index) => {
    const week = Math.floor(index / 5);
    return { ...candle, x: MONDAY + (week * 7 + (index % 5)) * DAY };
  });
}

export function mount(container: HTMLElement): () => void {
  const hosts = [chartHost(container, 240), chartHost(container, 240)];
  hosts[0].style.marginBottom = "12px";

  const data = weekdayCandles();
  const axis = {
    x: { ticks: timeTicks({ timeZone: "UTC", locale: "ko" }) },
    y: {
      position: "right",
      format: priceFormat({ compact: true, locale: "ko" }),
    },
  } as const;

  const continuous = PlotBuilder.create<OHLC>(browserDeps({ autoSize: true }))
    .setSize(container.clientWidth || 900, 240)
    .setAxis(axis)
    .build(hosts[0]);
  continuous.mainPane.addSeries({ series: candleSeries(), data, name: "연속 시간축" });

  const indexed = PlotBuilder.create<OHLC>(
    browserDeps({ autoSize: true, createXMapping: barIndexX }),
  )
    .setSize(container.clientWidth || 900, 240)
    .setAxis(axis)
    .build(hosts[1]);
  indexed.mainPane.addSeries({ series: candleSeries(), data, name: "봉 번호축" });

  return Object.assign(
    () => {
      continuous.destroy();
      indexed.destroy();
      for (const host of hosts) host.remove();
    },
    {
      requestRender: () => {
        continuous.requestRender();
        indexed.requestRender();
      },
    },
  );
}