From 2af0a7d3c50ea885df12159171de4fe812212749 Mon Sep 17 00:00:00 2001 From: JIN Date: Wed, 6 Nov 2024 17:09:15 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat:=20=ED=95=9C=EA=B5=AD=ED=88=AC?= =?UTF-8?q?=EC=9E=90=20API=20=EC=9A=94=EC=B2=AD=20=EB=B0=8F=20=EA=B2=B0?= =?UTF-8?q?=EA=B3=BC=EA=B0=92=EC=9D=84=20=EB=B0=9B=EC=95=84=EC=98=A4?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84#12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 한국투자 Open API를 활용해 정보를 요청하고, 해당 정보를 모두 가져와 저장하는 로직 구현 --- BE/src/stocks/topfive/topfive.service.ts | 152 +++++++++++++++++++++++ 1 file changed, 152 insertions(+) diff --git a/BE/src/stocks/topfive/topfive.service.ts b/BE/src/stocks/topfive/topfive.service.ts index d801e213..51a563ef 100644 --- a/BE/src/stocks/topfive/topfive.service.ts +++ b/BE/src/stocks/topfive/topfive.service.ts @@ -1,6 +1,50 @@ import axios from 'axios'; import { Injectable } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; +import { StockRankigRequestDto } from './dto/stock-ranking-request.dto'; +import { StockRankingResponseDto } from './dto/stock-ranking-response.dto'; +import { StockRankingDataDto } from './dto/stock-ranking-data.dto'; + +export enum MarketType { + ALL = 'ALL', + KOSPI = 'KOSPI', + KOSDAQ = 'KOSDAQ', + KOSPI200 = 'KOSPI200', +} + +interface StockApiOutputData { + stck_shrn_iscd: string; + data_rank: string; + hts_kor_isnm: string; + stck_prpr: string; + prdy_vrss: string; + prdy_vrss_sign: string; + prdy_ctrt: string; + acml_vol: string; + stck_hgpr: string; + hgpr_hour: string; + acml_hgpr_data: string; + stck_lwpr: string; + lwpr_hour: string; + acml_lwpr_date: string; + lwpr_vrss_prpr_rate: string; + dsgt_date_clpr_vrss_prpr_rate: string; + cnnt_ascn_dynu: string; + hgpr_vrss_prpr_rate: string; + cnnt_down_dynu: string; + oprc_vrss_prpr_sign: string; + oprc_vrss_prpr: string; + oprc_vrss_prpr_rate: string; + prd_rsfl: string; + prd_rsfl_rate: string; +} + +interface StockApiResponse { + output: StockApiOutputData[]; + rt_cd: string; + msg_cd: string; + msg1: string; +} @Injectable() export class TopFiveService { @@ -40,4 +84,112 @@ export class TopFiveService { return this.accessToken; } + + private async requestApi(params: StockRankigRequestDto) { + try { + const token = await this.getAccessToken(); + + const response = await axios.get( + `${this.koreaInvestmentConfig.baseUrl}/uapi/domestic-stock/v1/ranking/fluctuation`, + { + headers: { + 'content-type': 'application/json; charset=utf-8', + authorization: `Bearer ${token}`, + appkey: this.koreaInvestmentConfig.appKey, + appsecret: this.koreaInvestmentConfig.appSecret, + tr_id: 'FHPST01700000', + custtype: 'P', + }, + params: { + fid_rsfl_rate2: '', + fid_cond_mrkt_div_code: params.fid_cond_mrkt_div_code, + fid_cond_scr_div_code: '20170', + fid_input_iscd: params.fid_input_iscd, + fid_rank_sort_cls_code: params.fid_rank_sort_cls_code, + fid_input_cnt_1: '0', + fid_prc_cls_code: '1', + fid_input_price_1: '', + fid_input_price_2: '', + fid_vol_cnt: '', + fid_trgt_cls_code: '0', + fid_trgt_exls_cls_code: '0', + fid_div_cls_code: '0', + fid_rsfl_rate1: '', + }, + }, + ); + return response.data; + } catch (error) { + console.error('API Error Details:', { + status: error.response?.status, + statusText: error.response?.statusText, + data: error.response?.data, + headers: error.response?.config?.headers, // 실제 요청 헤더 + message: error.message, + }); + throw error; + } + } + + async getMarketRanking(marketType: MarketType) { + try { + const params = new StockRankigRequestDto(); + params.fid_cond_mrkt_div_code = 'J'; + + switch (marketType) { + case MarketType.ALL: + params.fid_input_iscd = '0000'; + break; + case MarketType.KOSPI: + params.fid_input_iscd = '0001'; + break; + case MarketType.KOSDAQ: + params.fid_input_iscd = '1001'; + break; + case MarketType.KOSPI200: + params.fid_input_iscd = '2001'; + break; + default: + break; + } + + const highResponse = await this.requestApi({ + ...params, + fid_rank_sort_cls_code: '0', + }); + + const lowResponse = await this.requestApi({ + ...params, + fid_rank_sort_cls_code: '1', + }); + + const response = new StockRankingResponseDto(); + response.high = this.formatStockData(highResponse.output); + response.low = this.formatStockData(lowResponse.output); + + return response; + } catch (error) { + console.error('API Error Details:', { + status: error.response?.status, + statusText: error.response?.statusText, + data: error.response?.data, + headers: error.response?.config?.headers, // 실제 요청 헤더 + message: error.message, + }); + throw error; + } + } + + private formatStockData(stocks: StockApiOutputData[]) { + return stocks.map((stock) => { + const stockData = new StockRankingDataDto(); + stockData.hts_kor_isnm = stock.hts_kor_isnm; + stockData.stck_prpr = stock.stck_prpr; + stockData.prdy_vrss = stock.prdy_vrss; + stockData.prdy_vrss_sign = stock.prdy_vrss_sign; + stockData.prdy_ctrt = stock.prdy_ctrt; + + return stockData; + }); + } }