findStockPriceByStockAndDate()
메소드getStockPriceDTOByStockIdAndDate()
메소드StockPriceDTO
형식으로 반환 public ResponseEntity<ArrayList<StockPriceDTO>> stockPrice(@RequestBody GetStockPriceRequest request) throws JsonProcessingException {
... 생략
// 조회하려는 데이터 중에, DB에 없는 날짜가 하나라도 포함되어 있다면? -> Kis 서버에 새로 요첨
// 조회하려는 데이터가 모두 DB에 있다면? -> DB에서 가져와서 stockPriceDTOs에 넣어줌
boolean findFromDB = true;
for(LocalDate date : dates){
if(!stockPriceService.isStockPriceExistByStockIdAndDate(stockId, date)){
// DB에 존재하지 않는다면
findFromDB = false;
break;
}
}
if(findFromDB){
// 조회하려는 데이터가 모두 DB에 존재
for(LocalDate date : dates) {
StockPriceDTO stockPriceDtoDB = stockPriceService.getStockPriceDTOByStockIdAndDate(stockId, date);
log.info("stockId: {},Date: {} data already exists in DB. Got Data From DB", stockId, date);
stockPriceDTOs.add(stockPriceDtoDB);
}
} else {
// 조회하려는 데이터 중, DB에 존재하지 않는 날짜가 하나라도 포함되어 있다면
// startDate ~ endDate의 주식 정보 조회
String stockPriceResponse = kisService.getStockPriceByCodeAndDate(stockCode, request.getStartDate(), request.getEndDate()).block();
... 중략
}
}
return ResponseEntity.ok().body(stockPriceDTOs);
}
10일 이동평균선의 경우, 【 해당 날짜 ~ 해당 날짜 - 9 】 가격의 평균을 구해야 함.
위의 가격 정보들이 모두 DB에 존재하면
➜ 이동평균선을 계산할 필요 없이, 레코드를 가져오면 됨
위의 가격 정보들 중, 하나라도 DB에 존재하지 않는 경우
➜ KIS 서버에서 100일전까지의 가격 정보를 모두 땡겨옴
땡겨온 가격 정보 + 가지고 있는 가격 정보로 이동평균선 계산
@Scheduled
어노테이션 사용@EnableScheduling
어노테이션을 추가해야 한다.@Component
@Slf4j
@Getter
public class KisAccessToken {
private String accessToken;
private final WebClient webClient;
private final String baseUrl;
private final String appKey;
private final String appSecretKey;
/**
* 한국 투자 증권 API에 접근하기 위한 Access Token를 받아와서 빈 내부에 저장
*/
public KisAccessToken(WebClient webClient,
@Value("${spring.kis-api.endpoint-url}") String baseUrl,
@Value("${spring.kis-api.app-key}")String appKey,
@Value("${spring.kis-api.app-secret-key}") String appSecretKey) throws JsonProcessingException {
this.webClient = webClient;
this.baseUrl = baseUrl;
this.appKey = appKey;
this.appSecretKey = appSecretKey;
refreshAccessToken(); // 초기 토큰 로드
}
// 23시간마다 자동 갱신
@Scheduled(fixedRate = 82800000, initialDelay = 82800000)
public void refreshAccessToken() throws JsonProcessingException {
Map<String, String> bodyMap = new HashMap<>();
bodyMap.put("grant_type", "client_credentials");
bodyMap.put("appkey", appKey);
bodyMap.put("appsecret", appSecretKey);
String fullUrl = baseUrl + "/oauth2/tokenP"; // 호스트와 경로를 조합
Mono<String> monoAccess = webClient.post()
.uri(fullUrl) // 전체 URL을 명시적으로 지정
.contentType(MediaType.APPLICATION_JSON)
.body(BodyInserters.fromValue(bodyMap))
.retrieve()
.bodyToMono(String.class);
String accessTokenJson = monoAccess.block();
ObjectMapper objectMapper = new ObjectMapper();
Map<String, String> AccessTokenMap = objectMapper.readValue(accessTokenJson, Map.class);
accessToken = AccessTokenMap.get("access_token");
log.info(accessToken);
}
}
@Scheduled
어노테이션@Scheduled
어노테이션을 사용하면, 특정 시간마다 동작하는 스케줄러를 구현할 수 있다.