npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

krx-js-client

v1.0.1

Published

KRX Javascript Client and Trigger Batch

Readme

krx-js-client

krx-js-client는 Node.js용 KRX(한국거래소) 데이터 클라이언트와 오전 조건 스캔 배치 도구를 함께 제공하는 ESM 패키지입니다.

이 패키지로 할 수 있는 일:

  • 종목별 OHLCV, 시가총액, 기본적 지표 조회
  • 날짜 기준 전 종목 스냅샷 조회
  • 종목코드 ↔ 종목명 매핑 조회
  • 오전 배치 트리거 실행 및 JSON 결과 저장
  • KRX 직접 로그인 또는 Kakao 로그인 기반 세션 자동 관리

주의할 점:

  • 패키지 루트(krx-js-client)는 데이터 클라이언트 관련 export만 다시 내보냅니다.
  • 배치 API(runBatch, triggerMorning...)는 krx-js-client/trigger_batch.js로 직접 import해야 합니다.
  • 현재 CLI 모드는 morning만 구현되어 있습니다. afternoon은 구현되어 있지 않습니다.
  • 패키지에 playwright 의존성은 포함되어 있지만, Chromium 브라우저 바이너리는 별도 설치가 필요할 수 있습니다.

1. 설치

이 패키지는 ESM("type": "module") 기준입니다.

프로젝트 로컬 설치

npm install krx-js-client

처음 로그인/인증을 실행하는 환경이라면 Chromium 설치도 확인하세요.

npx playwright install chromium

다음 상황에서는 위 명령이 특히 필요합니다.

  • browserType.launch: Executable doesn't exist 같은 오류가 날 때
  • CI / 서버 / 새 개발 머신에서 처음 실행할 때
  • playwright 패키지는 설치되어 있는데 실제 브라우저가 없는 경우

CLI를 전역으로 설치하고 싶다면

npm install -g krx-js-client
npx playwright install chromium

전역 설치 후에는 krx-trigger 명령을 바로 사용할 수 있습니다.

2. 환경 변수와 인증 방식

기본 로그인 방식은 KRX 직접 로그인입니다.

  • KRX_LOGIN_METHOD 기본값: krx
  • KRX_LOGIN_METHOD=krx이면 KRX_ID, KRX_PW 필요
  • 그 외 값이면 Kakao 로그인으로 간주되며 KAKAO_ID, KAKAO_PW 필요

환경 변수 목록

| 변수 | 기본값 | 용도 | | --- | --- | --- | | KRX_LOGIN_METHOD | krx | 로그인 방식 선택. krx면 KRX 직접 로그인, 그 외는 Kakao 로그인 | | KRX_ID | 없음 | KRX 직접 로그인 ID | | KRX_PW | 없음 | KRX 직접 로그인 비밀번호 | | KAKAO_ID | 없음 | Kakao 로그인 ID | | KAKAO_PW | 없음 | Kakao 로그인 비밀번호 |

.env 예시: KRX 직접 로그인

KRX_LOGIN_METHOD=krx
KRX_ID=your_krx_id
KRX_PW=your_krx_password

.env 예시: Kakao 로그인

KRX_LOGIN_METHOD=kakao
KAKAO_ID=your_kakao_id
KAKAO_PW=your_kakao_password

중요한 차이: 라이브러리 vs CLI

  • CLI(krx-trigger)는 dotenv/config를 자동 로드합니다.
  • 라이브러리 사용 시에는 .env를 자동 로드하지 않습니다.

즉, 라이브러리에서 환경 변수를 쓰려면 직접 로드해야 합니다.

import 'dotenv/config';
import { get_market_ohlcv_by_ticker } from 'krx-js-client';

const rows = await get_market_ohlcv_by_ticker('20240102');
console.log(rows.slice(0, 3));

3. 인증 관리자와 세션/캐시 파일

내장 인증은 KRXAuthManager가 담당합니다.

기본 파일 경로:

  • 세션 파일: ~/.krx_session.json
  • 로그인 락 파일: ~/.krx_session.lock
  • ISIN 캐시 파일: ~/.krx_isin_cache.json

세션 파일(~/.krx_session.json)

로그인 성공 후 대략 아래와 같은 구조로 저장됩니다.

{
  "cookies": {
    "JSESSIONID": "...",
    "mdc.client_session": "..."
  },
  "krx_cookies": [
    {
      "name": "mdc.client_session",
      "value": "...",
      "domain": "data.krx.co.kr",
      "path": "/"
    }
  ],
  "last_login": "2026-04-09T07:00:00.000Z",
  "last_validated": "2026-04-09T07:00:00.000Z"
}

동작 특성:

  • 세션 만료 기준: 4시간
  • 최근 검증 freshness: 5분 이내면 재검증을 건너뜀
  • 세션이 만료되면 요청 시 자동 재로그인을 최대 3회까지 시도

락 파일(~/.krx_session.lock)

동시에 여러 프로세스가 로그인할 때 충돌을 줄이기 위한 파일입니다.

  • 락 획득 대기 타임아웃: 120초
  • 오래된 락 파일은 자동 정리 시도
  • 권한 문제나 비정상 종료가 있으면 수동 삭제가 필요할 수 있음

ISIN 캐시 파일(~/.krx_isin_cache.json)

종목코드 → ISIN 매핑을 캐시합니다.

{
  "date": "20240102",
  "cached_at": "2026-04-09T07:00:00.000Z",
  "cache": {
    "005930": "KR7005930003"
  }
}

동작 특성:

  • 개별 종목 조회 시 내부적으로 ISIN 조회에 사용됩니다.
  • 거래일 기준 캐시를 새로 구성합니다.
  • 현재 공개 API에서 ISIN 캐시 경로를 바꾸는 옵션은 없습니다.

4. 빠른 시작

가장 간단한 라이브러리 사용

import 'dotenv/config';
import {
  get_market_ohlcv_by_date,
  get_market_ticker_name,
  get_market_ticker_name_map,
} from 'krx-js-client';

const samsung = await get_market_ticker_name('005930');
console.log(samsung); // 삼성전자 같은 단일 문자열

const map = await get_market_ticker_name_map(null, 'KOSPI');
console.log(map['005930']);

const ohlcv = await get_market_ohlcv_by_date('20240102', '20240112', '005930');
console.log(ohlcv[0]);

권장 방식: KRXAuthManager를 명시적으로 주입

주의: KRXDataClient 생성자 자체는 krxId, krxPw 같은 값을 직접 받지 않습니다. 환경 변수 또는 authManager를 사용해야 합니다.

import 'dotenv/config';
import { KRXAuthManager, KRXDataClient } from 'krx-js-client';

const authManager = new KRXAuthManager({
  loginMethod: 'krx',
  krxId: process.env.KRX_ID,
  krxPw: process.env.KRX_PW,
  headless: true,
});

const client = new KRXDataClient({ authManager });
const rows = await client.get_market_ohlcv_by_ticker('20240102', 'KOSPI');
console.log(rows.slice(0, 5));

Kakao 로그인 예시

import 'dotenv/config';
import { KRXAuthManager, KRXDataClient } from 'krx-js-client';

const authManager = new KRXAuthManager({
  loginMethod: 'kakao',
  kakaoId: process.env.KAKAO_ID,
  kakaoPw: process.env.KAKAO_PW,
  headless: true,
});

const client = new KRXDataClient({ authManager });
const rows = await client.get_market_cap_by_ticker('20240102');
console.log(rows.slice(0, 3));

테스트/모킹용 requestImpl 사용

requestImpl을 주면 내장 HTTP 요청과 자동 로그인 흐름을 우회합니다.

import { KRXDataClient } from 'krx-js-client';

const client = new KRXDataClient({
  requestImpl: async (bld, params) => {
    console.log('mock request', bld, params);
    return [];
  },
});

const rows = await client.get_market_ohlcv_by_ticker('20240102');
console.log(rows); // []

5. 패키지 루트 export (import ... from 'krx-js-client')

패키지 루트는 index.js를 통해 krx_data_client.js의 export를 다시 내보냅니다.

5.1 오류 클래스

| export | 설명 | | --- | --- | | KRXAuthError | 인증/로그인 관련 기본 오류 | | KRX2FARequiredError | 2차 인증이 필요한 상황을 표현하는 오류 클래스 | | KRXSessionExpiredError | 세션 만료, 로그인 페이지 HTML 응답, 빈 응답 등 세션 유효성 문제 | | KRXDataError | 데이터 조회/입력값 문제. 예: 종목을 찾을 수 없음, fetch 미설정 |

예시:

import 'dotenv/config';
import {
  get_market_ohlcv_by_date,
  KRXAuthError,
  KRXSessionExpiredError,
  KRXDataError,
} from 'krx-js-client';

try {
  const rows = await get_market_ohlcv_by_date('20240102', '20240105', '005930');
  console.log(rows);
} catch (error) {
  if (error instanceof KRXSessionExpiredError) {
    console.error('세션이 만료되어 재로그인이 필요합니다.');
  } else if (error instanceof KRXAuthError) {
    console.error('로그인 실패:', error.message);
  } else if (error instanceof KRXDataError) {
    console.error('데이터 오류:', error.message);
  } else {
    console.error(error);
  }
}

5.2 클래스

KRXAuthManager

생성자 옵션:

new KRXAuthManager({
  kakaoId,
  kakaoPw,
  krxId,
  krxPw,
  loginMethod,
  headless = true,
  cookiePath,
  lockPath,
  loginProvider,
  fetchImpl,
})

주요 포인트:

  • 기본 로그인 방식은 process.env.KRX_LOGIN_METHOD || 'krx'
  • cookiePath 기본값: ~/.krx_session.json
  • lockPath 기본값: ~/.krx_session.lock
  • loginProvider를 주면 내장 Playwright 로그인 대신 사용자 정의 로그인 함수를 사용
  • fetchImpl은 로그인 후 세션 검증용 API probe에 사용
  • login({ force }) 메서드로 세션 로드/저장/재로그인 처리

loginProvidercookies 배열을 돌려주는 형태를 기대합니다.

import { KRXAuthManager } from 'krx-js-client';

const authManager = new KRXAuthManager({
  loginMethod: 'krx',
  krxId: 'id',
  krxPw: 'pw',
  loginProvider: async () => ({
    cookies: [
      { name: 'mdc.client_session', value: 'dummy', domain: 'data.krx.co.kr', path: '/' },
    ],
  }),
});

await authManager.login({ force: true });

KRXDataClient

생성자 옵션:

new KRXDataClient({
  autoLogin = true,
  requestImpl = null,
  fetchImpl = null,
  authManager = null,
})

주의할 점:

  • authManager를 주지 않고 requestImpl도 없으면 내부에서 new KRXAuthManager()를 생성합니다.
  • 이 경우 인스턴스 생성 시점에 환경 변수가 이미 준비되어 있어야 합니다.
  • autoLogin 인자는 현재 구현에서 저장만 되고 실제 동작에는 사용되지 않습니다.
  • fetchImpl을 주지 않으면 globalThis.fetch를 사용합니다.
  • 런타임에 fetch가 없고 fetchImpl도 주지 않으면 KRXDataError('fetchImpl not configured')가 발생합니다.

5.3 함수 export

아래 함수들은 모두 패키지 루트에서 바로 import할 수 있습니다.

ensure_session_valid(): Promise<boolean>

기본 클라이언트의 세션이 유효한지 확인합니다.

  • 최근 5분 이내에 확인했다면 네트워크 없이 true
  • 로그인 실패 시 예외를 던지지 않고 false
import 'dotenv/config';
import { ensure_session_valid } from 'krx-js-client';

const ok = await ensure_session_valid();
console.log('session ok?', ok);

reset_session_freshness(): void

ensure_session_valid()의 freshness 캐시를 초기화합니다.

import { reset_session_freshness } from 'krx-js-client';

reset_session_freshness();

get_market_ohlcv_by_date(fromdate, todate, ticker, adjusted = true)

개별 종목의 기간별 OHLCV를 반환합니다.

반환 shape:

[
  {
    date: Date,
    Open: number | null,
    High: number | null,
    Low: number | null,
    Close: number | null,
    Volume: number | null,
    Amount: number | null,
    MarketCap: number | null,
  },
]

예시:

import 'dotenv/config';
import { get_market_ohlcv_by_date } from 'krx-js-client';

const rows = await get_market_ohlcv_by_date('20240102', '20240110', '005930');
console.log(rows[0]);

get_market_ohlcv_by_ticker(date, market = 'ALL')

특정 거래일의 전 종목 OHLCV 스냅샷을 반환합니다.

내부적으로 지정 날짜가 휴장일이면 최근 거래일로 보정해서 조회합니다.

지원 시장 코드:

  • KOSPI
  • KOSDAQ
  • KONEX
  • ALL

반환 shape:

[
  {
    ticker: string,
    Open: number | null,
    High: number | null,
    Low: number | null,
    Close: number | null,
    Volume: number | null,
    Amount: number | null,
  },
]

get_market_cap_by_ticker(date, market = 'ALL')

특정 거래일의 전 종목 시가총액 스냅샷을 반환합니다.

이 메서드도 내부적으로 최근 거래일 보정을 사용합니다.

반환 shape:

[
  {
    ticker: string,
    MarketCap: number | null,
    Volume: number | null,
    Amount: number | null,
    ListedShares: number | null,
  },
]

get_market_cap_by_date(fromdate, todate, ticker)

개별 종목의 기간별 시가총액/거래량/거래대금을 반환합니다.

[
  {
    date: Date,
    MarketCap: number | null,
    Volume: number | null,
    Amount: number | null,
  },
]

get_market_fundamental_by_date(fromdate, todate, ticker)

개별 종목의 기본적 지표를 반환합니다.

[
  {
    date: Date,
    BPS: number | null,
    PER: number | null,
    PBR: number | null,
    EPS: number | null,
    DIV: number | null,
    DPS: number | null,
  },
]

get_market_trading_volume_by_date(fromdate, todate, ticker, detail = false)

투자자별 거래량을 반환합니다.

detail = false일 때:

[
  {
    date: Date,
    기관합계: number | null,
    기타법인: number | null,
    개인: number | null,
    외국인합계: number | null,
    전체: number | null,
  },
]

detail = true일 때:

[
  {
    date: Date,
    금융투자: number | null,
    보험: number | null,
    투신: number | null,
    사모: number | null,
    은행: number | null,
    기타금융: number | null,
    연기금: number | null,
    기타법인: number | null,
    개인: number | null,
    외국인: number | null,
    기타외국인: number | null,
    전체: number | null,
  },
]

get_market_trading_value_by_date(fromdate, todate, ticker, on = '순매수')

투자자별 거래대금 계열 데이터를 반환합니다.

현재 구현 주의:

  • on 인자는 실제로 사용되지 않습니다.
  • 내부적으로 get_market_trading_value_by_investor(fromdate, todate, ticker)를 그대로 호출합니다.
  • 즉, 현재 JS 구현에서는 on='순매수', on='매수', on='매도' 같은 의미 구분이 없습니다.

반환 shape은 get_market_trading_value_by_investor(..., false)와 동일합니다.

get_market_trading_value_by_investor(fromdate, todate, ticker, detail = false)

투자자별 순매수 성격의 거래대금 데이터를 반환합니다. 구현상 buy - sell 계산으로 만들어집니다.

detail = false일 때:

[
  {
    date: Date,
    기관합계: number,
    기타법인: number,
    개인: number,
    외국인합계: number,
    전체: number,
  },
]

detail = true일 때:

[
  {
    date: Date,
    금융투자: number,
    보험: number,
    투신: number,
    사모: number,
    은행: number,
    기타금융: number,
    연기금: number,
    기관합계: number,
    기타법인: number,
    개인: number,
    외국인: number,
    기타외국인: number,
  },
]

예시:

import 'dotenv/config';
import { get_market_trading_value_by_investor } from 'krx-js-client';

const rows = await get_market_trading_value_by_investor('20240102', '20240105', '005930', true);
console.log(rows[0]);

get_market_ticker_list(date = null, market = 'KOSPI')

시장별 종목코드 배열을 반환합니다.

import 'dotenv/config';
import { get_market_ticker_list } from 'krx-js-client';

const kospiTickers = await get_market_ticker_list(null, 'KOSPI');
console.log(kospiTickers.slice(0, 10));

get_market_ticker_name(ticker)

패키지 루트의 이 함수는 단일 종목코드에 대한 종목명 문자열을 반환합니다.

import 'dotenv/config';
import { get_market_ticker_name } from 'krx-js-client';

const name = await get_market_ticker_name('005930');
console.log(name); // 문자열

get_market_ticker_name_map(date = null, market = 'ALL')

시장별 ticker -> name 맵 객체를 반환합니다.

import 'dotenv/config';
import { get_market_ticker_name_map } from 'krx-js-client';

const map = await get_market_ticker_name_map(null, 'ALL');
console.log(map['005930']);

get_index_ohlcv_by_date(fromdate, todate, ticker, freq = 'd')

지수 OHLCV를 반환합니다.

[
  {
    date: Date,
    Open: number | null,
    High: number | null,
    Low: number | null,
    Close: number | null,
    Volume: number | null,
    Amount: number | null,
  },
]

주의:

  • 구현상 ticker 문자열의 첫 글자와 나머지를 분리해 API 파라미터로 사용합니다.
  • freq 인자는 현재 구현에서 실제로 사용되지 않습니다.

get_nearest_business_day_in_a_week(targetDate = null, prev = true)

가까운 거래일 문자열(YYYYMMDD)을 반환합니다.

주의:

  • 현재 JS 구현에서는 사실상 "가장 가까운 최근 거래일" 헬퍼로 동작합니다.
  • prev 인자는 의미 있게 사용되지 않습니다.
import { get_nearest_business_day_in_a_week } from 'krx-js-client';

const d = await get_nearest_business_day_in_a_week('20240106', true);
console.log(d); // 예: 20240105

5.4 추가 export: __test

소스에는 __test export도 존재합니다.

포함 항목:

  • parseNumber
  • parseDate
  • CookieJar
  • extractOutput
  • getNearestBusinessDay
  • FileLock
  • ensureClientSessionCookie
  • readSessionFile
  • writeSessionFile
  • createTempSessionFile

테스트/내부 검증 성격으로 보이므로 애플리케이션 코드에서의 직접 의존은 권장하지 않습니다.

6. KRXDataClient 공개 메서드 정리

KRXDataClient는 아래 공개 메서드를 제공합니다.

| 메서드 | 설명 | | --- | --- | | get_market_ohlcv(fromdate, todate, ticker, adjusted = true) | 개별 종목 OHLCV | | get_market_fundamental(fromdate, todate, ticker) | 개별 종목 기본적 지표 | | get_market_trading_volume_by_date(fromdate, todate, ticker, detail = false) | 투자자별 거래량 | | get_index_ohlcv(fromdate, todate, ticker, freq = 'd') | 지수 OHLCV | | get_market_ohlcv_by_ticker(date, market = 'ALL') | 날짜 기준 전 종목 OHLCV | | get_market_cap_by_ticker(date, market = 'ALL') | 날짜 기준 전 종목 시총 | | get_market_ticker_name(date = null, market = 'ALL') | ticker -> name 맵 반환 | | get_market_ticker_list(date = null, market = 'KOSPI') | 종목코드 배열 반환 | | get_market_cap(fromdate, todate, ticker) | 개별 종목 시총 | | get_nearest_business_day(targetDate = null) | 가장 가까운 최근 거래일 반환 | | get_nearest_business_day_in_a_week(targetDate = null, prev = true) | 현재 구현상 위 메서드와 동일 | | is_market_day(targetDate = null) | 거래일 여부 boolean | | get_market_ohlcv_by_date(fromdate, todate, ticker, adjusted = true) | get_market_ohlcv 별칭 | | get_market_cap_by_date(fromdate, todate, ticker) | get_market_cap 별칭 | | get_market_fundamental_by_date(fromdate, todate, ticker) | get_market_fundamental 별칭 | | get_index_ohlcv_by_date(fromdate, todate, ticker, freq = 'd') | get_index_ohlcv 별칭 | | get_market_trading_value_by_date(fromdate, todate, ticker, on = '순매수') | 현재 구현상 investor 버전 위임 | | get_market_trading_value_by_investor(fromdate, todate, ticker, detail = false) | 투자자별 거래대금 순값 |

로그인 관련 공개 메서드는 KRXDataClient가 아니라 KRXAuthManager.login({ force })에 있습니다.

중요 차이:

  • 클래스 메서드 client.get_market_ticker_name(date, market)은 이름과 달리 종목명 문자열이 아니라 맵 객체를 반환합니다.
  • 패키지 루트 함수 get_market_ticker_name(ticker)만 단일 문자열을 반환합니다.
import 'dotenv/config';
import { KRXDataClient } from 'krx-js-client';

const client = new KRXDataClient();

const map = await client.get_market_ticker_name(null, 'ALL');
console.log(typeof map, map['005930']);

7. 배치 API (import ... from 'krx-js-client/trigger_batch.js')

패키지 루트에서 재-export되지 않으므로 서브패스로 import하세요.

import { runBatch } from 'krx-js-client/trigger_batch.js';

export 목록

| export | 설명 | | --- | --- | | runBatch(mode, logLevel = 'INFO', outputPath = null, injectedFunctions = {}) | 전체 배치 실행 | | triggerMorningVolumeSurge(...) | 거래량 급증 상위주 계산 | | triggerMorningGapUpMomentum(...) | 갭 상승 모멘텀 상위주 계산 | | triggerMorningValueToCapRatio(...) | 시총 대비 집중 자금 유입 상위주 계산 | | applyAbsoluteFilters(rows, minValue) | 배치 내부 절대 필터 유틸 | | normalizeAndScore(...) | 정규화 + 점수화 유틸 | | enhanceRows(rows, tickerMap) | 종목명 결합 유틸 | | getSnapshot(tradeDate) | 일자 스냅샷 조회 | | getPreviousSnapshot(tradeDate) | 직전 거래일 스냅샷 조회 | | getMarketCapRows(tradeDate, market) | 시총 스냅샷 조회 |

runBatch 예시

import 'dotenv/config';
import { runBatch } from 'krx-js-client/trigger_batch.js';

const result = await runBatch('morning', 'INFO', './trigger-output.json');
console.log(result.metadata);

outputPath를 생략하면 파일 저장 없이 결과 객체만 반환합니다.

morning 모드에서 생성되는 트리거 키

  • 거래량 급증 상위주
  • 갭 상승 모멘텀 상위주
  • 시총 대비 집중 자금 유입 상위주

배치 결과 JSON shape

{
  "거래량 급증 상위주": [
    {
      "code": "005930",
      "name": "삼성전자",
      "current_price": 70000,
      "change_rate": 1.23,
      "volume": 12345678,
      "trade_value": 876543210000,
      "volume_increase": 55.4
    }
  ],
  "갭 상승 모멘텀 상위주": [
    {
      "code": "035420",
      "name": "NAVER",
      "current_price": 200000,
      "change_rate": 2.1,
      "volume": 1000000,
      "trade_value": 200000000000,
      "gap_rate": 1.8
    }
  ],
  "시총 대비 집중 자금 유입 상위주": [
    {
      "code": "000660",
      "name": "SK하이닉스",
      "current_price": 180000,
      "change_rate": 3.2,
      "volume": 5000000,
      "trade_value": 900000000000,
      "trade_value_ratio": 0.45,
      "market_cap": 130000000000000
    }
  ],
  "metadata": {
    "run_time": "2026-04-09T08:00:00.000Z",
    "trigger_mode": "morning",
    "trade_date": "20260409",
    "selection_mode": "direct",
    "lookback_days": 10
  }
}

조건부 필드:

  • volume_increase: 거래량 급증 트리거일 때만 포함
  • gap_rate: 갭 상승 모멘텀 트리거일 때만 포함
  • trade_value_ratio, market_cap: 시총 대비 자금 유입 트리거일 때만 포함
  • 후보가 없으면 각 트리거 값은 빈 배열이 될 수 있음

8. CLI 사용법

실행 명령:

krx-trigger <mode> [LOG_LEVEL] [--output <path>]

현재 허용값:

  • mode: morning만 가능
  • LOG_LEVEL: DEBUG, INFO, WARNING

주의:

  • 내부 runBatch()ERROR 레벨 숫자도 가지고 있지만, 실제 CLI 인자 파서는 DEBUG, INFO, WARNING만 허용합니다.
  • .env는 CLI가 자동 로드합니다.

예시

# 패키지를 로컬 설치한 프로젝트에서
npx krx-trigger morning INFO --output ./trigger-output.json
# 로그를 더 자세히 보고 싶을 때
npx krx-trigger morning DEBUG
# 전역 설치 후
krx-trigger morning WARNING --output /tmp/krx-morning.json

도움말

krx-trigger --help

9. 현재 구현 기준 제한사항 / 주의사항

이 항목들은 소스 기준 실제 구현 상태입니다.

  1. afternoon 모드는 구현되어 있지 않습니다.

    • runBatch('afternoon', ...)와 CLI krx-trigger afternoon은 실패합니다.
  2. 패키지 루트 함수 get_market_ticker_name(ticker)와 클래스 메서드 client.get_market_ticker_name(date, market)의 의미가 다릅니다.

    • 루트 함수: 단일 종목명 문자열
    • 클래스 메서드: ticker -> name 맵 객체
  3. get_market_trading_value_by_date(..., on)on 파라미터는 현재 무시됩니다.

    • 내부적으로 get_market_trading_value_by_investor()에 그대로 위임됩니다.
  4. get_nearest_business_day_in_a_week(targetDate, prev)prev는 현재 구현에서 의미 있게 쓰이지 않습니다.

    • 사실상 get_nearest_business_day()와 동일하게 동작합니다.
  5. 거래일 계산 로직은 단순화되어 있습니다.

    • 주말 제외
    • 5월 1일, 12월 31일 제외
    • 2025년 일부 휴장일만 하드코딩되어 있음
    • 완전한 KRX 공식 휴장일 캘린더는 아닙니다.
  6. get_index_ohlcv_by_date(..., freq) / get_index_ohlcv(..., freq)freq 인자는 현재 구현에서 사용되지 않습니다.

  7. get_market_ticker_name_map(date, market) / 클래스의 get_market_ticker_name(date, market)에서 date 인자는 현재 구현상 사용되지 않습니다.

  8. autoLogin 생성자 옵션은 현재 구현에서 의미 있는 차이를 만들지 않습니다.

  9. requestImpl을 주면 내장 인증/세션 처리 흐름이 사실상 비활성화됩니다.

    • 테스트/모킹에는 좋지만 실제 KRX 통신에는 직접 책임져야 합니다.
  10. Playwright 패키지는 의존성에 포함되어 있어도 브라우저 설치는 별도로 필요할 수 있습니다.

  11. KRX 웹 페이지 구조나 로그인 셀렉터가 바뀌면 인증 흐름이 깨질 수 있습니다.

10. 문제 해결

10.1 KRX direct login requires KRX_ID and KRX_PW.

원인:

  • 기본 로그인 방식이 krx인데 계정 정보가 없음

해결:

export KRX_LOGIN_METHOD=krx
export KRX_ID=your_id
export KRX_PW=your_password

또는 .env를 설정하고, 라이브러리라면 import 'dotenv/config'를 직접 호출하세요.

10.2 Kakao login requires KAKAO_ID and KAKAO_PW.

원인:

  • KRX_LOGIN_METHODkrx가 아닌 값인데 Kakao 계정 환경 변수가 없음

해결:

export KRX_LOGIN_METHOD=kakao
export KAKAO_ID=your_id
export KAKAO_PW=your_password

10.3 playwright가 설치되지 않았습니다... 또는 Chromium 실행 파일 오류

원인:

  • Playwright 패키지 또는 브라우저 바이너리가 준비되지 않음

해결:

npm install krx-js-client
npx playwright install chromium

10.4 HTML response - session expired, Empty response - session expired, JSON parse failed - session expired

원인:

  • 로그인 세션이 만료됨
  • KRX가 JSON 대신 로그인 페이지/오류 페이지를 반환함

해결:

  1. 한 번 더 재시도
  2. 세션 파일 삭제 후 재로그인
  3. 브라우저 설치 상태 확인
rm -f ~/.krx_session.json ~/.krx_session.lock

10.5 mdc.client_session 쿠키가 없습니다.

원인:

  • 로그인은 진행됐지만 KRX 데이터 세션 쿠키 확보에 실패

해결:

  • npx playwright install chromium 재실행
  • KRX 로그인 페이지 동작 변화 여부 확인
  • headless 환경 문제라면 headless: false로 직접 점검
import 'dotenv/config';
import { KRXAuthManager } from 'krx-js-client';

const auth = new KRXAuthManager({
  loginMethod: 'krx',
  krxId: process.env.KRX_ID,
  krxPw: process.env.KRX_PW,
  headless: false,
});

await auth.login({ force: true });

10.6 로그인 락 획득 타임아웃

원인:

  • 다른 프로세스가 로그인 중이거나 stale lock이 남아 있음

해결:

rm -f ~/.krx_session.lock

여러 프로세스가 동시에 뜨는 배치 환경이라면 시작 시점을 분산하세요.

10.7 종목을 찾을 수 없습니다: ...

원인:

  • 잘못된 종목코드
  • 비정상 캐시
  • 거래일/티커 조합 문제

해결:

rm -f ~/.krx_isin_cache.json

그 후 다시 조회하세요.

10.8 fetchImpl not configured

원인:

  • 런타임에 globalThis.fetch가 없고 fetchImpl도 주입하지 않음

해결:

import fetch from 'node-fetch';
import { KRXDataClient } from 'krx-js-client';

const client = new KRXDataClient({ fetchImpl: fetch });

또는 fetch가 있는 Node 런타임을 사용하세요.

10.9 Invalid mode: afternoon 또는 CLI에서 morning 외 모드 실패

원인:

  • 현재 구현은 morning 전용

해결:

  • CLI와 runBatch() 모두 morning만 사용하세요.

10.10 배치 결과가 빈 배열만 나온다

가능한 원인:

  • 해당 거래일에 조건을 만족하는 종목이 없음
  • 데이터 조회는 성공했지만 필터(거래대금/시총/상승 여부)에 모두 걸러짐

해결:

  • DEBUG 로그로 실행
  • 출력 파일을 저장해서 메타데이터와 거래일 확인
npx krx-trigger morning DEBUG --output ./trigger-output.json

10.11 CommonJS에서 require()가 바로 안 된다

원인:

  • 패키지가 ESM("type": "module")임

해결:

  • import 사용
  • 또는 동적 import 사용
const { get_market_ticker_name } = await import('krx-js-client');
console.log(await get_market_ticker_name('005930'));

11. 참고 예제 모음

날짜 기준 전 종목 스냅샷 + 종목명 합치기

import 'dotenv/config';
import {
  get_market_ohlcv_by_ticker,
  get_market_ticker_name_map,
} from 'krx-js-client';

const tradeDate = '20240102';
const [rows, nameMap] = await Promise.all([
  get_market_ohlcv_by_ticker(tradeDate, 'KOSPI'),
  get_market_ticker_name_map(null, 'KOSPI'),
]);

const enriched = rows.slice(0, 10).map((row) => ({
  ...row,
  name: nameMap[row.ticker] || '',
}));

console.log(enriched);

세션을 미리 확인한 뒤 조회

import 'dotenv/config';
import {
  ensure_session_valid,
  get_market_cap_by_ticker,
  reset_session_freshness,
} from 'krx-js-client';

const ok = await ensure_session_valid();
if (!ok) {
  throw new Error('세션 준비 실패');
}

const rows = await get_market_cap_by_ticker('20240102');
console.log(rows.slice(0, 3));

reset_session_freshness();

프로그램에서 배치 실행

import 'dotenv/config';
import { runBatch } from 'krx-js-client/trigger_batch.js';

const output = await runBatch('morning', 'INFO');
console.log(Object.keys(output));
console.log(output.metadata);

12. 라이선스

LICENSE 파일을 참고하세요.