2024.05.11 - [프로젝트/SpringBoot 업비트 자동매매 프로젝트] - [자동매매, SpringBoot] 1. 프로젝트 생성 및 계획
이전 글에서 프로젝트 생성 및 계획을 마쳤고, 계좌 조회 기능을 추가할 것 이다.
업비트 개발자센터에서 API Reference를 보면
https://api.upbit.com/v1/accounts 로 GET 요청을 보내면 내가 보유한 자산 리스트를 Response 받을 수 있다고 한다.
화폐, 수량, 묶여있는 수량, 매수평균가, 매수평균가 수정 여부, 평단가 기준 화폐 정보를 받을 수 있는데
화폐, 수량 정보만 있으면 될 것 같다.
1. Util Class
API 요청을 보내려면 Header로 Authorization token을 보내야 하는데
업비트에서 지급 받은 accessKey, secretKey를 가지고 token을 만들 수 있다.
이 토큰은 앞으로 다른 요청을 보낼 때도 계속 쓰일 것 같으니 Util 클래스를 만들어서 재사용 할 것이다.
Util 클래스에는 token을 만드는 함수와, 요청을 보낼 때 쓸 restTemplate을 Bean으로 등록 해 주었다.
앞으로 재사용 할 함수들은 Util에 추가할 예정
Dependency에 jwt 라이브러리도 추가
2. AccountService
계좌관련 서비스는 AccountService에 추가를 할 것이다.
계좌 조회 요청을 보내면 화폐, 수량, 묶여있는 수량, 매수평균가, 매수평균가 수정 여부, 평단가 기준 화폐 정보를 받을 수 있는데
화폐, 수량, 평균 매수가 정도가 필요 할 것 같아서
보유한 화폐의 수량을 return 해주는 getBalances, getBalance
보유한 화폐의 평균 매수가를 return 해주는 getAvgBuyPrices, getAvgBuyPrice 를 만들었다.
Util Class 의 generateAuthenticationToken 함수로 JWT Token을 만들고
이 토큰을 담아서 https://api.upbit.com/v1/accounts 로 GET 요청을 보낸다.
@Slf4j
@Service
@RequiredArgsConstructor
public class AccountService {
private final Util util;
private final RestTemplate restTemplate;
/**
* 보유한 화폐들의 수량
* @return Map<화폐, 수량>
* @throws IOException
*/
public Map<String, Double> getAllBalances() throws IOException {
Map<String, Double> balances = new HashMap<>();
String authenticationToken = util.generateAuthenticationToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authenticationToken);
headers.set("Content-Type", "application/json");
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(SERVER_URL + "/v1/accounts", HttpMethod.GET, request, String.class);
List<Map<String, Object>> list = new ObjectMapper().readValue(response.getBody(), new TypeReference<List<Map<String, Object>>>() {});
for( Map<String, Object> account : list) {
String currency = account.get("currency").toString();
double balance = Double.parseDouble(account.get("balance").toString());
balances.put(currency, balance);
log.info("[" + currency + "] 수량 : " + balance);
}
return balances;
}
/**
* 보유한 화폐들의 평균 매수가
* @return Map<화폐, 평균 매수가>
* @throws JsonProcessingException
*/
public Map<String, Double> getAllAvgBuyPrices() throws JsonProcessingException {
Map<String, Double> avgBuyPrices = new HashMap<>();
String authenticationToken = util.generateAuthenticationToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authenticationToken);
headers.set("Content-Type", "application/json");
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(SERVER_URL + "/v1/accounts", HttpMethod.GET, request, String.class);
List<Map<String, Object>> list = new ObjectMapper().readValue(response.getBody(), new TypeReference<List<Map<String, Object>>>() {});
for( Map<String, Object> account : list) {
String currency = account.get("currency").toString();
double avgBuyPrice = Double.parseDouble(account.get("avg_buy_price").toString());
avgBuyPrices.put(currency, avgBuyPrice);
log.info("[" + currency + "] 평균 매수가 : " + avgBuyPrice);
}
return avgBuyPrices;
}
/**
* currency 수량
* @param currency 화폐
* @return 수량
*/
public double getBalance(String currency) throws JsonProcessingException {
String authenticationToken = util.generateAuthenticationToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authenticationToken);
headers.set("Content-Type", "application/json");
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(SERVER_URL + "/v1/accounts", HttpMethod.GET, request, String.class);
List<Map<String, Object>> list = new ObjectMapper().readValue(response.getBody(), new TypeReference<List<Map<String, Object>>>() {});
for( Map<String, Object> account : list) {
if (currency.equals(account.get("currency").toString())) {
double balance = Double.parseDouble(account.get("balance").toString());
log.info("[" + currency + "] 수량 : " + balance);
return balance;
}
}
return 0.0;
}
/**
* currency 평균 매수가
* @param currency 화폐
* @return 평균 매수가
*/
public double getAvgBuyPrices(String currency) throws JsonProcessingException {
String authenticationToken = util.generateAuthenticationToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", authenticationToken);
headers.set("Content-Type", "application/json");
HttpEntity request = new HttpEntity(headers);
ResponseEntity<String> response = restTemplate.exchange(SERVER_URL + "/v1/accounts", HttpMethod.GET, request, String.class);
List<Map<String, Object>> list = new ObjectMapper().readValue(response.getBody(), new TypeReference<List<Map<String, Object>>>() {});
for( Map<String, Object> account : list) {
if (currency.equals(account.get("currency").toString())) {
double avgBuyPrice = Double.parseDouble(account.get("avg_buy_price").toString());
log.info("[" + currency + "] 평균 매수가 : " + avgBuyPrice);
return avgBuyPrice;
}
}
return 0.0;
}
}
3. 결과
함수를 실행해서 로그를 확인해보면 나의 계좌가 출력 된다.
스케줄링 함수에 넣거나 테스트를 만들어서 테스트 해보면 된다.
'프로젝트 > SpringBoot 업비트 자동매매 프로젝트' 카테고리의 다른 글
[자동매매, SpringBoot] 3. 매도, 매수 (0) | 2024.05.16 |
---|---|
[자동매매, SpringBoot] 1. 프로젝트 생성 및 계획 (0) | 2024.05.11 |