개발자의 삶/코인

JAVA로 바이낸스(binance) API 활용하여 매매 프로그램 작성 1

비전공돌이 2021. 10. 7. 14:10

주식도 하고 코인도 합니다.

그래서 주식도 잃고 코인도 잃었어요. ㅠㅠ

 

명색이 개발자이니 자동매매 프로그램을 만들어봐야겠다는 생각을 합니다.

 

가장 먼저 빗썸 API를 활용하여 로직을 구현했습니다.

그 후에 업비트 쪽 거래 로직을 구현했구요.

최근에는 바이낸스 매매 프로그램을 작성했습니다.

 

보통 생각하는 자동 매매 프로그램은 크게 다음 조건을 충족해야 할 것 같습니다.

  1. 사람이 직접 매수/매도를 하지 않아도 프로그램을 실행해두면 자동으로 매수/매도를 진행한다.
  2. 자동으로 사고 팔면서 수익을 발생시킨다.

저는 1번만 구현을 했습니다.

개발자분들은 아시겠지만, 그냥 API 연동만 했다는 이야기죠 ㅎㅎ

 

결국 수익을 발생시키기 위해서는 언제 사고, 언제 팔지에 대한 명확한 규칙을 정하고 그것을 로직으로 구현해야 합니다.

그런데 이 규칙을 세우는 것이 어렵더군요. 저는 그 부분에 대한 해답을 아직 못찾았어요.

 

어쨌든 1번이 되어야 2번에 대한 로직도 가능하니까, 1번을 어떻게 하는지 설명해보고자 합니다.

 

빗썸, 업비트는 나중에 적을게요. 먼저 가장 최근에 구현한 바이낸스부터 적어봅니다.

저는 자바가 가장 익숙해서 자바로 개발했습니다.


 

먼저 바이낸스 API Key를 발급 받습니다.

잘 정리된 블로그가 많으므로 제가 따로 적진 않겠습니다.

https://www.google.com/search?client=safari&rls=en&q=%EB%B0%94%EC%9D%B4%EB%82%B8%EC%8A%A4+api+key&ie=UTF-8&oe=UTF-8 

 

이 포스팅에서는 바이낸스에 가진 코인 수량을 조회하는 로직을 다루겠습니다.

 

기본적인 API 스펙과 가이드는 바이낸스 공식 문서를 참조하시면 됩니다.

https://binance-docs.github.io/apidocs/spot/en/#change-log

 

Binance API Documentation

 

binance-docs.github.io

 

개인 지갑을 조회하는 부분이므로 당연히 인증이 필요합니다.

인증은 HMAC SHA256으로 하도록 되어있습니다.

Mac hmacSha256 = Mac.getInstance("HmacSHA256");
SecretKeySpec secKey = new SecretKeySpec(secretKey.getBytes(), "HmacSHA256");
hmacSha256.init(secKey);

여기서 secretKey는 처음에 언급한 API Key 발급시에 함께 알려주는Secret Key를 의미합니다.

아래와 같은 형태로 되어 있습니다.

 

apiKey 예시 : vmPUZE6mv9SD5VNHk4HlWFsOr6aKE2zvsw0MuIgwCIPy6utIco14y7Ju91duEh8A
secretKey 예시 : NhqPtmdSJYdKjVHjA7PZj4Mge3R5YNiP1e3UZjInClVN65XAbvqqM6A7H5fATj0j

 

저의 경우에는 스프링을 사용하므로 아래와 같이 변수 선언을 해두었습니다.

@Value("${restapi.binance.accessKey}")
private String accessKey;

@Value("${restapi.binance.secretKey}")
private String secretKey;

프로퍼티에 해당 key를 암호화하여 입력해두었구요. 복호화 key는 jvm 옵션으로 넣도록 했습니다.

스프링 관련 포스팅이 아니므로 따로 설명하진 않습니다.

 

다른 거래소도 그렇지만 바이낸스 API 중에 GET 방식의 API와 POST 방식의 API가 있습니다.

조회성 API들은 GET으로 되어 있습니다.

이번에 다룰 계좌 조회도 GET 방식입니다.

바이낸스 API 문서 중 계좌 조회 부분

 

GET

/api/v3/account

HMAC SHA256

timestamp YES (Mandatory)

 

먼저 이렇게 4가지 항목이 중요합니다.

GET 방식으로 요청을 해야합니다.

호출할 API URL은 /api/v3/account 이구요.

앞서 언급한 HMAC SHA256 인증을 태워야 합니다.

그리고 필수 파라미터는 timestamp 하나네요.

 

GET 방식의 인증은 어떻게 수행할까요?

앞서 언급한 인증 로직에서 선언한 hmacSha256 변수가 있습니다.

이 변수를 이용하여 파라미터를 해싱합니다.

그 해싱값을 signature라는 파라미터에 추가로 넣어주면 됩니다.

String actualSign = new String(Hex.encodeHex(hmacSha256.doFinal(queryString.getBytes())));
queryString = queryString + "&signature=" + actualSign;

이제 이 파라미터를 이용해 API를 호출하면 됩니다.

String serverUrl = "https://api.binance.com";

HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(serverUrl + "/api/v3/account?" + queryString);
request.addHeader("Content-Type", "application/json");
request.addHeader("X-MBX-APIKEY", accessKey);

HttpResponse response = client.execute(request);
HttpEntity entity = response.getEntity();

String entityString = EntityUtils.toString(entity, "UTF-8");

아 한가지 설명을 안했네요.

accessKey는 해더에 세팅합니다. 위 로직에 "X-MBX-APIKEY" 부분 참조하세요.

 

파라미터에 대해 부연 설명을 하자면...

String timestamp = Long.toString(System.currentTimeMillis())

이런 식으로 현재 시간을 long 타입의 문자열로 추출하면 됩니다.

인증이 없이 호출한다면 아래와 같이 되겠죠.

 

/api/v3/account?timestamp=1499827319559

 

여기에서 파라미터 부분을 해싱을 해서 추가하면...

/api/v3/account?timestamp=1499827319559&signature=c8db56825ae71d6d79447849e617115f4a920fa2acdcab2b053c4b2838bd6b71

이렇게 되겠죠.

 

이렇게 호출하게되면 json 형태로 응답이 오게 됩니다. (제 계좌 아닙니다. 공식 문서의 샘플이에요. 이 정도 비트 있었으면 좋겠네요 ㅎㅎ)

{
  "makerCommission": 15,
  "takerCommission": 15,
  "buyerCommission": 0,
  "sellerCommission": 0,
  "canTrade": true,
  "canWithdraw": true,
  "canDeposit": true,
  "updateTime": 123456789,
  "accountType": "SPOT",
  "balances": [
    {
      "asset": "BTC",
      "free": "4723846.89208129",
      "locked": "0.00000000"
    },
    {
      "asset": "LTC",
      "free": "4763368.68006011",
      "locked": "0.00000000"
    }
  ],
  "permissions": [
    "SPOT"
  ]
}

여기서 balances 부분에 본인이 보유한 코인이 나오게 됩니다.

JSONParser jsonParser = new JSONParser();
JSONObject account = (JSONObject) jsonParser.parse(entityString);

JSONArray balances = (JSONArray) account.get("balances");

위와 같이 파싱해서 사용하면 됩니다.

보유한 코인에 대해서만 나올 것 같았는데, 전체 코인이 다 내려오더군요.

free 또는 locked가 0보다 큰 것만 보시면 될 듯 하네요.

 

참고로 free와 locked는 모두 보유한 코인 수량인데, locked는 매도를 걸어둔 수량 등을 의미합니다.

 

이렇게 본인의 계좌를 조회하여 코인의 수량을 확인할 수 있습니다.

 

참고로 조회성 API는 모두 동일 방식으로 구현하시면 됩니다.

 

다음 번에는 특정 코인의 현재가 조회하는 부분을 포스팅할게요.

그리고 매매 API도 설명할 예정입니다.

 

다들 성투 하시길....