Skip to content
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

[feat] : 비트코인 1분봉 차트 조회 API 구현 (GET) #75

Merged
merged 4 commits into from
Jun 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public enum SuccessStatus implements BaseCode {
SUCCESS_GET_USER_COINS(HttpStatus.OK, "200", "유저 보유 코인 조회에 성공했습니다"),
SUCCESS_GET_REPRESENTATIVE_COINS(HttpStatus.OK, "200", "대표 코인 조회에 성공했습니다"),
SUCCESS_GET_BITCOIN_DAY_CHARTS(HttpStatus.OK, "200", "비트코인 일봉 차트 조회에 성공했습니다"),
SUCCESS_GET_BITCOIN_ONE_MINUTE_CHARTS(HttpStatus.OK, "200", "비트코인 1분봉 차트 조회에 성공했습니다"),
// Upbit-Key
SUCCESS_ADD_UPBIT_KEYS(HttpStatus.CREATED, "201", "업비트 키 등록에 성공했습니다"),
// Chart
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public ResponseEntity<ApiResponse<List<ChartDto.OHLCVResponse>>> getOHLCVCharts(
@RequestParam("coin_name") String koreanName,
@RequestParam("candle_name") String candleName) {

List<ChartDto.OHLCVResponse> ohlcvResponses = chartService.getOHLCVCharts(koreanName, candleName);
List<ChartDto.OHLCVResponse> ohlcvResponses = chartService.getOHLCVCharts(koreanName, candleName, null);
return ApiResponse.onSuccess(SuccessStatus.SUCCESS_GET_OHLCV_CHART, ohlcvResponses);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import org.dgu.backend.dto.DashBoardDto;
import org.dgu.backend.service.ChartService;
import org.dgu.backend.service.DashBoardService;
import org.dgu.backend.util.DateUtil;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.List;

@RestController
Expand All @@ -18,6 +20,7 @@
public class DashBoardController {
private final DashBoardService dashBoardService;
private final ChartService chartService;
private final DateUtil dateUtil;

// 유저 업비트 잔고 조회 API
@GetMapping("/accounts")
Expand Down Expand Up @@ -46,10 +49,19 @@ public ResponseEntity<ApiResponse<List<DashBoardDto.RepresentativeCoinResponse>>
}

// 비트코인 차트 (일봉) 조회 API
@GetMapping("/bit-charts")
@GetMapping("/bit-charts/days")
public ResponseEntity<ApiResponse<List<ChartDto.OHLCVResponse>>> getBitcoinDayCharts() {

List<ChartDto.OHLCVResponse> ohlcvResponses = chartService.getOHLCVCharts("비트코인", "days");
List<ChartDto.OHLCVResponse> ohlcvResponses = chartService.getOHLCVCharts("비트코인", "days", null);
return ApiResponse.onSuccess(SuccessStatus.SUCCESS_GET_BITCOIN_DAY_CHARTS, ohlcvResponses);
}

// 비트코인 차트 (1분봉) 조회 API
@GetMapping("/bit-charts/minutes1")
public ResponseEntity<ApiResponse<List<ChartDto.OHLCVResponse>>> getBitcoinOneMinuteCharts() {

LocalDateTime startDate = dateUtil.calculateDailyStartDate();
List<ChartDto.OHLCVResponse> ohlcvResponses = chartService.getOHLCVCharts("비트코인", "minutes1", startDate);
return ApiResponse.onSuccess(SuccessStatus.SUCCESS_GET_BITCOIN_ONE_MINUTE_CHARTS, ohlcvResponses);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,15 @@ public class BackTestingServiceImpl implements BackTestingService {
// 백테스팅 결과를 생성하는 메서드
@Override
public BackTestingDto.BackTestingResponse createBackTestingResult(String authorizationHeader, BackTestingDto.StepInfo stepInfo) {
updateCandleInfo("비트코인", stepInfo.getCandleName());
updateCandleInfo("비트코인", stepInfo.getCandleName(), null);

return fetchBackTestingResult(authorizationHeader, stepInfo);
}

// 캔들 정보 최신화 메서드
@Transactional
protected void updateCandleInfo(String koreanName, String candleName) {
candleInfoUpdater.ensureCandleInfoUpToDate(koreanName, candleName);
protected void updateCandleInfo(String koreanName, String candleName, LocalDateTime startDate) {
candleInfoUpdater.ensureCandleInfoUpToDate(koreanName, candleName, startDate);
}

// 최신화된 캔들 정보를 사용해 백테스팅 결과를 생성하는 메서드
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public class CandleInfoUpdater {
private final DateUtil dateUtil;

// 현재 시각을 기준으로 캔들 정보를 최신화하는 메서드
public void ensureCandleInfoUpToDate(String koreanName, String candleName) {
public void ensureCandleInfoUpToDate(String koreanName, String candleName, LocalDateTime startDate) {
Market market = marketRepository.findByKoreanName(koreanName);
if (Objects.isNull(market)) {
throw new MarketException(MarketErrorResult.NOT_FOUND_MARKET);
Expand All @@ -40,16 +40,17 @@ public void ensureCandleInfoUpToDate(String koreanName, String candleName) {
throw new CandleException(CandleErrorResult.NOT_FOUND_CANDLE);
}

// 가장 최근 캔들 차트
CandleInfo latestCandleInfo = candleInfoRepository.findTopByMarketAndCandleOrderByTimestampDesc(market, candle);
int candleInterval = candleUtil.calculateCandleInterval(candleName);
LocalDateTime startDate;
if (Objects.isNull(latestCandleInfo)) {
startDate = dateUtil.convertToLocalDateTime("2018-01-01T00:00:00");
} else {
startDate = latestCandleInfo.getDateTime();
if (startDate.plusMinutes(candleInterval).isAfter(LocalDateTime.now())) {
return;
if (Objects.isNull(startDate)) {
// 가장 최근 캔들 차트
CandleInfo latestCandleInfo = candleInfoRepository.findTopByMarketAndCandleOrderByTimestampDesc(market, candle);
int candleInterval = candleUtil.calculateCandleInterval(candleName);
if (Objects.isNull(latestCandleInfo)) {
startDate = dateUtil.convertToLocalDateTime("2018-01-01T00:00:00");
} else {
startDate = latestCandleInfo.getDateTime();
if (startDate.plusMinutes(candleInterval).isAfter(LocalDateTime.now())) {
return;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

import org.dgu.backend.dto.ChartDto;

import java.time.LocalDateTime;
import java.util.List;

public interface ChartService {
List<ChartDto.OHLCVResponse> getOHLCVCharts(String koreanName, String candleType);
List<ChartDto.OHLCVResponse> getOHLCVCharts(String koreanName, String candleType, LocalDateTime startDate);
List<ChartDto.ChartOptionResponse> getAllChartOptions();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ public class ChartServiceImpl implements ChartService {

// OHLCV 차트를 반환하는 메서드
@Override
public List<ChartDto.OHLCVResponse> getOHLCVCharts(String koreanName, String candleName) {
updateCandleInfo(koreanName, candleName);
public List<ChartDto.OHLCVResponse> getOHLCVCharts(String koreanName, String candleName, LocalDateTime startDate) {
updateCandleInfo(koreanName, candleName, startDate);

return fetchUpdatedCandleInfo(koreanName, candleName);
return fetchUpdatedCandleInfo(koreanName, candleName, startDate);
}

// 차트 선택 지표 목록을 반환하는 메서드
Expand All @@ -55,13 +55,13 @@ public List<ChartDto.ChartOptionResponse> getAllChartOptions() {

// 캔들 정보 최신화 메서드
@Transactional
protected void updateCandleInfo(String koreanName, String candleName) {
candleInfoUpdater.ensureCandleInfoUpToDate(koreanName, candleName);
protected void updateCandleInfo(String koreanName, String candleName, LocalDateTime startDate) {
candleInfoUpdater.ensureCandleInfoUpToDate(koreanName, candleName, startDate);
}

// 최신화된 캔들 정보를 반환하는 메서드
@Transactional
protected List<ChartDto.OHLCVResponse> fetchUpdatedCandleInfo(String koreanName, String candleName) {
protected List<ChartDto.OHLCVResponse> fetchUpdatedCandleInfo(String koreanName, String candleName, LocalDateTime startDate) {
Market market = marketRepository.findByKoreanName(koreanName);
if (Objects.isNull(market)) {
throw new MarketException(MarketErrorResult.NOT_FOUND_MARKET);
Expand All @@ -70,7 +70,9 @@ protected List<ChartDto.OHLCVResponse> fetchUpdatedCandleInfo(String koreanName,
if (Objects.isNull(candle)) {
throw new CandleException(CandleErrorResult.NOT_FOUND_CANDLE);
}
LocalDateTime startDate = candleUtil.getStartDateByCandleName(candleName);
if (Objects.isNull(startDate)) {
startDate = candleUtil.getStartDateByCandleName(candleName);
}

List<CandleInfo> candleInfos = candleInfoRepository.findByMarketAndCandleAndDateTimeAfter(market, candle, startDate);
if (candleInfos.isEmpty()) {
Expand Down
15 changes: 15 additions & 0 deletions backend/src/main/java/org/dgu/backend/util/DateUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

@Component
Expand All @@ -12,4 +13,18 @@ public class DateUtil {
public LocalDateTime convertToLocalDateTime(String date) {
return LocalDateTime.parse(date, FORMATTER);
}

public LocalDateTime calculateDailyStartDate() {
LocalDateTime now = LocalDateTime.now();
LocalDateTime startDate;

// 현재 시간이 오전 9시 이전이면 전날 오전 9시부터 필터링
if (now.toLocalTime().isBefore(LocalTime.of(9, 0))) {
startDate = now.minusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
} else {
startDate = now.withHour(0).withMinute(0).withSecond(0).withNano(0);
}

return startDate;
}
}
Loading