import z from "zod";
import { krxRequest } from "../utils/request.js";
import { buildUrl } from "../utils/url.js";
import { koreaMarket } from "../utils/const.js";
const krxBaseInfoUrl: Record<(typeof koreaMarket)[number], string> = {
KOSPI: "http://data-dbg.krx.co.kr/svc/apis/sto/stk_isu_base_info",
KOSDAQ: "http://data-dbg.krx.co.kr/svc/apis/sto/ksq_isu_base_info",
KONEX: "http://data-dbg.krx.co.kr/svc/apis/sto/knx_isu_base_info",
};
export const getBaseInfoSchema = z.object({
basDdList: z
.array(z.string().length(8))
.nonempty()
.describe("기준일자(YYYYMMDD) 배열"),
market: z.enum(koreaMarket).describe("상장된 주식시장 종류"),
codeList: z
.array(z.string())
.nonempty()
.describe("데이터를 가져올 종목들의 종목코드의 배열"),
});
export type GetBaseInfoParams = z.infer<typeof getBaseInfoSchema>;
export interface BaseInfo {
OutBlock_1: {
/** 표준코드 (ISU_CD) */
ISU_CD: string;
/** 단축코드 (ISU_SRT_CD) */
ISU_SRT_CD: string;
/** 한글 종목명 (ISU_NM) */
ISU_NM: string;
/** 한글 종목약명 (ISU_ABBRV) */
ISU_ABBRV: string;
/** 영문 종목명 (ISU_ENG_NM) */
ISU_ENG_NM: string;
/** 상장일 (LIST_DD) - YYYYMMDD 형식 */
LIST_DD: string;
/** 시장구분 (MKT_TP_NM) */
MKT_TP_NM: string;
/** 증권구분 (SECUGRP_NM) */
SECUGRP_NM: string;
/** 소속부 (SECT_TP_NM) */
SECT_TP_NM: string;
/** 주식종류 (KIND_STKCERT_TP_NM) */
KIND_STKCERT_TP_NM: string;
/** 액면가 (PARVAL) */
PARVAL: string;
/** 상장주식수 (LIST_SHRS) */
LIST_SHRS: string;
}[];
}
async function getSingleBaseInfo(
url: string,
basDd: string,
codeList: string[]
) {
const response = await krxRequest(buildUrl(url, { basDd }));
const data = (await response.json()) as BaseInfo;
const filtered = data.OutBlock_1.filter((stock) =>
codeList.includes(stock.ISU_SRT_CD)
);
return { basDd, filtered };
}
export async function getBaseInfo(params: GetBaseInfoParams) {
const { basDdList, market, codeList } = params;
const url = krxBaseInfoUrl[market];
const response: Record<string, BaseInfo["OutBlock_1"]> = {};
const resultPromises = basDdList.map((basDd) =>
getSingleBaseInfo(url, basDd, codeList)
);
const results = await Promise.all(resultPromises);
results.forEach(({ basDd, filtered }) => {
response[basDd] = filtered;
});
return response;
}