Files
auto-trade/features/trade/apis/kis-stock.api.ts

204 lines
5.5 KiB
TypeScript
Raw Normal View History

2026-02-11 16:31:28 +09:00
import type { KisRuntimeCredentials } from "@/features/settings/store/use-kis-runtime-store";
2026-02-26 09:05:17 +09:00
import {
buildKisRequestHeaders,
resolveKisApiErrorMessage,
type KisApiErrorPayload,
} from "@/features/settings/apis/kis-api-utils";
2026-02-10 11:16:39 +09:00
import type {
DashboardChartTimeframe,
DashboardStockCashOrderRequest,
DashboardStockCashOrderResponse,
2026-03-12 09:26:27 +09:00
DashboardStockOrderableCashRequest,
DashboardStockOrderableCashResponse,
2026-02-10 11:16:39 +09:00
DashboardStockChartResponse,
DashboardStockOrderBookResponse,
DashboardStockOverviewResponse,
DashboardStockSearchResponse,
2026-02-11 16:31:28 +09:00
} from "@/features/trade/types/trade.types";
2026-02-10 11:16:39 +09:00
/**
* API
* @param keyword
*/
export async function fetchStockSearch(
keyword: string,
signal?: AbortSignal,
): Promise<DashboardStockSearchResponse> {
const response = await fetch(
`/api/kis/domestic/search?q=${encodeURIComponent(keyword)}`,
{
cache: "no-store",
signal,
},
);
const payload = (await response.json()) as
| DashboardStockSearchResponse
2026-02-26 09:05:17 +09:00
| KisApiErrorPayload;
2026-02-10 11:16:39 +09:00
if (!response.ok) {
2026-02-26 09:05:17 +09:00
throw new Error(resolveKisApiErrorMessage(payload, "종목 검색 중 오류가 발생했습니다."));
2026-02-10 11:16:39 +09:00
}
return payload as DashboardStockSearchResponse;
}
/**
* API
* @param symbol
* @param credentials KIS
*/
export async function fetchStockOverview(
symbol: string,
credentials: KisRuntimeCredentials,
): Promise<DashboardStockOverviewResponse> {
const response = await fetch(
`/api/kis/domestic/overview?symbol=${encodeURIComponent(symbol)}`,
{
method: "GET",
2026-02-26 09:05:17 +09:00
headers: buildKisRequestHeaders(credentials, {
includeSessionOverride: true,
}),
2026-02-10 11:16:39 +09:00
cache: "no-store",
},
);
const payload = (await response.json()) as
| DashboardStockOverviewResponse
2026-02-26 09:05:17 +09:00
| KisApiErrorPayload;
2026-02-10 11:16:39 +09:00
if (!response.ok) {
2026-02-26 09:05:17 +09:00
throw new Error(resolveKisApiErrorMessage(payload, "종목 조회 중 오류가 발생했습니다."));
2026-02-10 11:16:39 +09:00
}
return payload as DashboardStockOverviewResponse;
}
/**
* API
* @param symbol
* @param credentials KIS
*/
export async function fetchStockOrderBook(
symbol: string,
credentials: KisRuntimeCredentials,
signal?: AbortSignal,
): Promise<DashboardStockOrderBookResponse> {
const response = await fetch(
`/api/kis/domestic/orderbook?symbol=${encodeURIComponent(symbol)}`,
{
method: "GET",
2026-02-26 09:05:17 +09:00
headers: buildKisRequestHeaders(credentials, {
includeSessionOverride: true,
}),
2026-02-11 11:18:15 +09:00
cache: "no-store",
2026-02-10 11:16:39 +09:00
signal,
},
);
const payload = (await response.json()) as
| DashboardStockOrderBookResponse
2026-02-26 09:05:17 +09:00
| KisApiErrorPayload;
2026-02-10 11:16:39 +09:00
if (!response.ok) {
2026-02-26 09:05:17 +09:00
throw new Error(resolveKisApiErrorMessage(payload, "호가 조회 중 오류가 발생했습니다."));
2026-02-10 11:16:39 +09:00
}
return payload as DashboardStockOrderBookResponse;
}
/**
* (//) API
*/
export async function fetchStockChart(
symbol: string,
timeframe: DashboardChartTimeframe,
credentials: KisRuntimeCredentials,
cursor?: string,
): Promise<DashboardStockChartResponse> {
const query = new URLSearchParams({
symbol,
timeframe,
});
if (cursor) query.set("cursor", cursor);
const response = await fetch(`/api/kis/domestic/chart?${query.toString()}`, {
method: "GET",
2026-02-26 09:05:17 +09:00
headers: buildKisRequestHeaders(credentials, {
includeSessionOverride: true,
}),
2026-02-10 11:16:39 +09:00
cache: "no-store",
});
const payload = (await response.json()) as
| DashboardStockChartResponse
2026-02-26 09:05:17 +09:00
| KisApiErrorPayload;
2026-02-10 11:16:39 +09:00
if (!response.ok) {
2026-02-26 09:05:17 +09:00
throw new Error(resolveKisApiErrorMessage(payload, "차트 조회 중 오류가 발생했습니다."));
2026-02-10 11:16:39 +09:00
}
return payload as DashboardStockChartResponse;
}
/**
* API
* @param request
* @param credentials KIS
*/
export async function fetchOrderCash(
request: DashboardStockCashOrderRequest,
credentials: KisRuntimeCredentials,
): Promise<DashboardStockCashOrderResponse> {
const response = await fetch("/api/kis/domestic/order-cash", {
method: "POST",
2026-02-26 09:05:17 +09:00
headers: buildKisRequestHeaders(credentials, {
jsonContentType: true,
includeSessionOverride: true,
}),
2026-02-10 11:16:39 +09:00
body: JSON.stringify(request),
cache: "no-store",
});
2026-02-26 09:05:17 +09:00
const payload = (await response.json()) as
| DashboardStockCashOrderResponse
| KisApiErrorPayload;
2026-02-10 11:16:39 +09:00
if (!response.ok) {
2026-02-26 09:05:17 +09:00
throw new Error(resolveKisApiErrorMessage(payload, "주문 전송 중 오류가 발생했습니다."));
2026-02-10 11:16:39 +09:00
}
2026-02-26 09:05:17 +09:00
return payload as DashboardStockCashOrderResponse;
2026-02-10 11:16:39 +09:00
}
2026-03-12 09:26:27 +09:00
/**
* () API
* @param request /
* @param credentials KIS
*/
export async function fetchOrderableCashEstimate(
request: DashboardStockOrderableCashRequest,
credentials: KisRuntimeCredentials,
): Promise<DashboardStockOrderableCashResponse> {
const response = await fetch("/api/kis/domestic/orderable-cash", {
method: "POST",
headers: buildKisRequestHeaders(credentials, {
jsonContentType: true,
includeAccountNo: true,
includeSessionOverride: true,
}),
body: JSON.stringify(request),
cache: "no-store",
});
const payload = (await response.json()) as
| DashboardStockOrderableCashResponse
| KisApiErrorPayload;
if (!response.ok) {
throw new Error(resolveKisApiErrorMessage(payload, "매수가능금액 조회 중 오류가 발생했습니다."));
}
return payload as DashboardStockOrderableCashResponse;
}