-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[BE] 6.04 매수/매도 요청 현황 API 구현 #92
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
|
||
export class StockTradeHistoryDataDto { | ||
@ApiProperty({ description: '주식 체결 시간' }) | ||
stck_cntg_hour: string; | ||
|
||
@ApiProperty({ description: '주식 현재가' }) | ||
stck_prpr: string; | ||
|
||
@ApiProperty({ description: '전일 대비 부호' }) | ||
prdy_vrss_sign: string; | ||
|
||
@ApiProperty({ description: '체결 거래량' }) | ||
cntg_vol: string; | ||
|
||
@ApiProperty({ description: '전일 대비율' }) | ||
prdy_ctrt: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
|
||
export class StockTradeHistoryOutputDto { | ||
@ApiProperty({ description: '주식 체결 시간' }) | ||
stck_cntg_hour: string; | ||
|
||
@ApiProperty({ description: '주식 현재가' }) | ||
stck_prpr: string; | ||
|
||
@ApiProperty({ description: '전일 대비' }) | ||
prdy_vrss: string; | ||
|
||
@ApiProperty({ description: '전일 대비 부호' }) | ||
prdy_vrss_sign: string; | ||
|
||
@ApiProperty({ description: '체결 거래량' }) | ||
cntg_vol: string; | ||
|
||
@ApiProperty({ description: '당일 체결강도' }) | ||
tday_rltv: string; | ||
|
||
@ApiProperty({ description: '전일 대비율' }) | ||
prdy_ctrt: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/** | ||
* 주식현재가 체결 API를 사용할 때 쿼리 파라미터로 사용할 요청값 DTO | ||
*/ | ||
export class StockTradeHistoryQueryParameterDto { | ||
/** | ||
* 조건 시장 분류 코드 | ||
* 'J' 주식 | ||
*/ | ||
fid_cond_mrkt_div_code: string; | ||
|
||
/** | ||
* 주식 종목 코드 | ||
* (ex) 005930 | ||
*/ | ||
fid_input_iscd: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { ApiProperty } from '@nestjs/swagger'; | ||
import { StockTradeHistoryOutputDto } from './stock-trade-history-output.dto'; | ||
|
||
/** | ||
* 주식현재가 체결 API 응답값 정제 후 FE에 보낼 DTO | ||
*/ | ||
export class StockTradeHistoryResponseDto { | ||
@ApiProperty({ type: StockTradeHistoryOutputDto, description: '상승률 순위' }) | ||
output: StockTradeHistoryOutputDto[]; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
export interface InquireCCNLOutputData { | ||
stck_cntg_hour: string; | ||
stck_prpr: string; | ||
prdy_vrss: string; | ||
prdy_vrss_sign: string; | ||
cntg_vol: string; | ||
tday_rltv: string; | ||
prdy_ctrt: string; | ||
} | ||
|
||
export interface InquireCCNLApiResponse { | ||
output: InquireCCNLOutputData[]; | ||
rt_cd: string; | ||
msg_cd: string; | ||
msg1: string; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { Controller, Get, Param } from '@nestjs/common'; | ||
import { ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger'; | ||
import { StockTradeHistoryService } from './stock-trade-history.service'; | ||
import { StockTradeHistoryResponseDto } from './dto/stock-trade-history-response.dto'; | ||
|
||
@Controller('/api/stocks') | ||
export class StockTradeHistoryController { | ||
constructor( | ||
private readonly stockTradeHistoryService: StockTradeHistoryService, | ||
) {} | ||
|
||
@Get(':stockCode/trade-history') | ||
@ApiOperation({ summary: '단일 주식 종목에 대한 주식현재가 체결 API' }) | ||
@ApiParam({ | ||
name: 'stockCode', | ||
required: true, | ||
description: | ||
'종목 코드\n\n' + | ||
'(ex) 005930 삼성전자 / 005380 현대차 / 001500 현대차증권', | ||
}) | ||
@ApiResponse({ | ||
status: 200, | ||
description: '단일 주식 종목에 대한 주식현재가 체결값 조회 성공', | ||
type: StockTradeHistoryResponseDto, | ||
}) | ||
getStockDetail(@Param('stockCode') stockCode: string) { | ||
return this.stockTradeHistoryService.getStockTradeHistory(stockCode); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { Module } from '@nestjs/common'; | ||
import { KoreaInvestmentModule } from '../../../koreaInvestment/korea-investment.module'; | ||
import { StockTradeHistoryController } from './stock-trade-history.controller'; | ||
import { StockTradeHistoryService } from './stock-trade-history.service'; | ||
|
||
@Module({ | ||
imports: [KoreaInvestmentModule], | ||
controllers: [StockTradeHistoryController], | ||
providers: [StockTradeHistoryService], | ||
}) | ||
export class StockTradeHistoryModule {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import axios from 'axios'; | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { KoreaInvestmentService } from '../../../koreaInvestment/korea-investment.service'; | ||
import { getHeader } from '../../../util/get-header'; | ||
import { getFullURL } from '../../../util/get-full-URL'; | ||
import { StockTradeHistoryQueryParameterDto } from './dto/stock-trade-history-query-parameter.dto'; | ||
import { InquireCCNLApiResponse } from './interface/Inquire-ccnl.interface'; | ||
import { StockTradeHistoryOutputDto } from './dto/stock-trade-history-output.dto'; | ||
import { StockTradeHistoryDataDto } from './dto/stock-trade-history-data.dto'; | ||
|
||
@Injectable() | ||
export class StockTradeHistoryService { | ||
private readonly logger = new Logger(); | ||
|
||
constructor(private readonly koreaInvetmentService: KoreaInvestmentService) {} | ||
|
||
/** | ||
* 특정 주식의 현재가 체결 데이터를 반환하는 함수 | ||
* @param {string} stockCode - 종목코드 | ||
* @returns - 특정 주식의 현재가 체결 데이터 객체 반환 | ||
* | ||
* @author uuuo3o | ||
*/ | ||
async getStockTradeHistory(stockCode: string) { | ||
try { | ||
const queryParams = new StockTradeHistoryQueryParameterDto(); | ||
queryParams.fid_cond_mrkt_div_code = 'J'; | ||
queryParams.fid_input_iscd = stockCode; | ||
|
||
const response = await this.requestApi(queryParams); | ||
|
||
return this.formatTradeHistoryData(response.output); | ||
} catch (error) { | ||
this.logger.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 한국투자 Open API - [국내주식] 기본시세 - 주식현재가 체결 호출 함수 | ||
* @param {StockTradeHistoryQueryParameterDto} queryParams - API 요청 시 필요한 쿼리 파라미터 DTO | ||
* @returns - 주식현재가 체결 데이터 | ||
* | ||
* @author uuuo3o | ||
*/ | ||
private async requestApi(queryParams: StockTradeHistoryQueryParameterDto) { | ||
try { | ||
const accessToken = await this.koreaInvetmentService.getAccessToken(); | ||
const headers = getHeader(accessToken, 'FHKST01010300'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟢 이 requestAPI 함수 몇번 본거 같은데 Util 같은 곳에 KoreaInvestRequestAPI 이런 식으로 메소드 분리해서 사용하는 것도 좋을것 같습니다! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 진짜 좋은 거 같아요! |
||
const url = getFullURL('/uapi/domestic-stock/v1/quotations/inquire-ccnl'); | ||
const params = this.getTradeHistoryParams(queryParams); | ||
|
||
const response = await axios.get<InquireCCNLApiResponse>(url, { | ||
headers, | ||
params, | ||
}); | ||
|
||
return response.data; | ||
} catch (error) { | ||
this.logger.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 API에서 받은 주식현재가 체결 데이터를 필요한 정보로 정제하는 함수 | ||
* @param {StockTradeHistoryOutputDto} infos - API 응답에서 받은 원시 데이터 | ||
* @returns - 필요한 정보만 추출한 데이터 배열 | ||
* | ||
* @author uuuo3o | ||
*/ | ||
private formatTradeHistoryData(infos: StockTradeHistoryOutputDto[]) { | ||
return infos.map((info) => { | ||
const infoData = new StockTradeHistoryDataDto(); | ||
infoData.stck_cntg_hour = info.stck_cntg_hour; | ||
infoData.stck_prpr = info.stck_prpr; | ||
infoData.prdy_vrss_sign = info.prdy_vrss_sign; | ||
infoData.cntg_vol = info.cntg_vol; | ||
infoData.prdy_ctrt = info.prdy_ctrt; | ||
|
||
return infoData; | ||
}); | ||
} | ||
|
||
/** | ||
* @private 주식현재가 체결 요청을 위한 쿼리 파라미터 객체 생성 함수 | ||
* @param {StockTradeHistoryQueryParameterDto} params - API 요청에 필요한 쿼리 파라미터 DTO | ||
* @returns - API 요청에 필요한 쿼리 파라미터 객체 | ||
* | ||
* @author uuuo3o | ||
*/ | ||
private getTradeHistoryParams(params: StockTradeHistoryQueryParameterDto) { | ||
return { | ||
fid_cond_mrkt_div_code: params.fid_cond_mrkt_div_code, | ||
fid_input_iscd: params.fid_input_iscd, | ||
}; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🟢 고생하셨습니당! 사소한 거지만 여기 ApiTags 빠진 것 같네용