Websocket 이란?
실시간 데이터를 받는것 (채팅)
- 필요한 라이브러리 추가
ticker의 값 중 UUID로 호출하면 됩니다.
파라미터 객체는 어떤 타입(현재가, 체결, 호가)으로 호출하고 어떤 코드(마켓)에 해당하는 데이터를 수신할 것인지를 전달해주어야 합니다.
로직은 웹소켓 컨트롤러를 이용해 연결을 하고, 데이터를 화면에 출력
@Scheduler 이란?
일정한 시간 간격으로, 혹은 특정 일정에 코드가 실행되는 것
코인은 매일 9시마다 전일대비%가 업데이트 갱신되기 때문에 스케쥴러를 사용하였습니다.
결과는 0.1초에 한번 upbitMarket 메소드를 실행
Websocket 실시간 시세 가져오기
1. Task 파일에 내 시세 현재가 불러오기 (Java application)
@Component
public class Task {
@Autowired private UpbitService upbitService;
private static int running_cnt = 0;
private static List<MarketVo> listMarketVo;
private static Api api;
private static boolean is_running = false;
@Scheduled(fixedDelay = 100, initialDelay = 0)
public void upbitMarket() throws IOException {
try {
if(!is_running) {
is_running = true;
if(running_cnt == 0) {
// Cmd 생성
api = new Api();
// 모든 마켓 정보 수신
listMarketVo = api.markets();
}
// 모든 마켓 실시간 수신
for (MarketVo v : listMarketVo) {
if(v.getMarket().substring(0, 3).equals("KRW")) {
Thread.sleep(100);
List<TickerVo> listTickerVo = api.ticker(v.getMarket());
TickerVo tickerVo = listTickerVo.get(0);
}
}
running_cnt++;
is_running = false;
}
} catch (Exception e) {
}
}
}
2. WebSocketChatHandler 클래스
@Component
public class WebSockChatHandler extends TextWebSocketHandler {
private List<WebSocketSession> sessionList = new ArrayList<WebSocketSession>();
// 클라이언트가 서버로 메세지 전송 처리
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String msg = message.getPayload();
ChatMsg chatMsg = new Gson().fromJson(msg, ChatMsg.class);
if(chatMsg.getType().equals("market")) {
Api api = new Api();
String ret = new Gson().toJson(api.markets());
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(ret));
}
}
if(chatMsg.getType().equals("price")) {
Api api = new Api();
String ret = new Gson().toJson(api.markets());
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(new Gson().toJson(CashMemory.CashMemoryListTickerVo)));
}
}
}
// 클라이언트가 연결을 끊음 처리
@Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
// 채팅방에서 퇴장한 사용자 세션을 리스트에서 제거
sessionList.remove(session);
// 모든 세션에 채팅 전달
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
//s.sendMessage(new TextMessage(session.getId() + "님이 퇴장 했습니다."));
}
}
화면에 market, ticker에대한 정보들을 보낼 메소드 생성
3. 화면 (jsp)
<script type="text/javascript">
//MarketVO 정보 받기
function onMessage(msg) {
var s = '';
var ob = $.parseJSON(msg.data);
if(status == 'open'){
console.log(ob.message);
}else if(status == 'market'){
for (var i = 0; i < ob.length; i++) {
var market = ob[i].market;
var korean_name = ob[i].korean_name;
var english_name = ob[i].english_name;
if(market.substring(0,3) =='KRW'){
s+='<tr>';
s+=' <td>'+korean_name+'['+market+']</td>';
s+=' <td class="'+market+'"><span style ="color:black">0</span></td>';
s+=' <td class="'+market+'_rate">0</td>';
s+='</tr>';
}
}
$('tbody').html(s);
status = 'price';
setInterval(function() {
sock.send('{"type":"price"}');
}, 5000);
}
//tickerVO에 대한 정보
if(isFirstPrice){
for (var i = 0; i < tickers.length; i++) {
var market = tickers[i].market;
var trade_price = tickers[i].trade_price;
var signed_change_rate = (Number(tickers[i].signed_change_rate)*100).toFixed(2);
$('.'+market).html('<span style ="color:black">'+trade_price+'</span>');
if(signed_change_rate == 0){
$('.'+market+'_rate').html('<span style ="color:black">'+signed_change_rate+'%</span>');
}else if(signed_change_rate > 0){
$('.'+market+'_rate').html('<span style ="color:red">+'+signed_change_rate+'%</span>');
}else{
$('.'+market+'_rate').html('<span style ="color:blue">'+signed_change_rate+'%</span>');
}
}
isFirstPrice = false;
}
컨트롤러에서 쏜 MarketVO와 TickerVO를 메소드를 ajax로 받는다.
4. 출력 결과
Websocket 내 자산 불러오기
1. Test 파일
Api api = new Api();
//해당 account 호출문 이용
List<MyBankVo> listMyBankVo = api.accounts();
String markets = "";
int i = 0;
List<MarketVo> listMarketVo = api.markets();
for (MarketVo v : listMarketVo) {
if(v.getMarket().substring(0, 3).equals("KRW")) {
//System.out.println("["+v.getMarket()+"]["+v.getEnglish_name()+"]["+v.getKorean_name()+"]");
if(i==0) markets += v.getMarket();
else markets += ","+v.getMarket();
i++;
}
}
System.out.println(new Gson().toJson(listMyBankVo));
해당 account 호출 + for 문으로 마켓정보 띄우기
2. Task.java (메모리에 저장된 정보들을 전송)
@Scheduled(fixedDelay = 100, initialDelay = 0)
public void upbitMarket() throws IOException {
try {
if(!is_running) {
is_running = true;
if(running_cnt == 0) {
// Cmd 생성
api = new Api();
// 모든 마켓 정보 수신
listMarketVo = api.markets();
}
// 나의 계좌 실시간 수신
List<MyBankVo> accounts = api.accounts();
double krw_money = 0;
double market_money = 0;
for (MyBankVo account : accounts) {
Thread.sleep(100);
if(account.getCurrency().equals("KRW")) krw_money = Double.parseDouble(account.getBalance());
else market_money += Double.parseDouble(account.getBalance()) * Double.parseDouble(account.getAvg_buy_price());
System.out.println(account.getAvg_buy_price());
}
CashMemory.krw_money = new NumberHelper().doubleDotdouble(krw_money,3);
CashMemory.all_money = new NumberHelper().doubleDotdouble(market_money + krw_money,3);
running_cnt++;
is_running = false;
}
} catch (Exception e) {
System.out.println(e.toString());
}
}
cashmemory에 나의 계좌 정보 삽입
3. VO
public class UpbitClient {
private double krw_money;
private double all_money;
private List<TickerVo> CashMemoryListTickerVo;
private List<MyBankVo> accounts;
4. WebSocketChatHandler 클래스
// 클라이언트가 서버로 메세지 전송 처리
@Override
protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
String msg = message.getPayload();
ChatMsg chatMsg = new Gson().fromJson(msg, ChatMsg.class);
UpbitClient upbitClient = new UpbitClient();
if(chatMsg.getType().equals("price")) {
upbitClient.setKrw_money(CashMemory.krw_money);
upbitClient.setAll_money(CashMemory.all_money);
upbitClient.setCashMemoryListTickerVo(CashMemory.CashMemoryListTickerVo);
upbitClient.setAccounts(CashMemory.accounts);
for (int i = 0; i < sessionList.size(); i++) {
WebSocketSession s = sessionList.get(i);
s.sendMessage(new TextMessage(new Gson().toJson(upbitClient)));
}
}
}
UpbitClient에 대한 정보들을 보낼 메소드 생성
5. 화면
//UpbitclientVO 호출
var krw_money = ob.krw_money;
var all_money = ob.all_money;
var tickers = ob.CashMemoryListTickerVo;
var accounts = ob.accounts;
$('#krw_money').text('보유 KRW : '+krw_money+' KRW');
$('#all_money').text('총 보유자산 : '+all_money+' KRW');
// 나의 코인 정보 MybankVO 호출
var s = '';
for (var i = 0; i < accounts.length; i++) {
var o = accounts[i];
var avg_buy_price = o.avg_buy_price;
var avg_buy_price_modified = o.avg_buy_price_modified;
var balance = o.balance;
var currency = o.currency;
var locked = o.locked;
var unit_currency = o.unit_currency;
var korean_name = o.korean_name;
if(currency != 'KRW'){
s+='<div class="card shadow mb-4">';
s+=' <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">';
s+=' <h6 class="m-0 font-weight-bold text-primary">'+unit_currency+'-'+currency+'['+korean_name+']</h6>';
s+=' </div>';
s+=' <div class="card-body">';
s+=' [평가손익:-12.3%][평가금액:-234,340]';
s+=' </div>';
s+=' <div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">';
s+=' <h6 class="m-0 font-weight-bold text-primary">[보유수량:41][매수평균가:178원][매수금액:345,459][평가금액:980,023]</h6>';
s+=' </div>';
s+='</div>';
}
}
$('#coin_box').html(s);
총 보유 자산 계산을 위해 Cashmemory에 담겨있는 unit_currency - currency를 한다.
6. 출력 결과
현재 모두 매도처리해서 0원
Appendix
static(정적)의 의미 : 정적 필드와 정적 메소드는 객체(인스턴스)에 소속된 멤버가 아니라 클래스에 고정된 멤버입니다.
싱글톤이 뭔지? : 싱글톤(Singleton) 패턴의 정의는 객체의 인스턴스가 오직 1개만 생성되는 패턴
파라미터 :
'Back_end > Api (업비트) 자동매매' 카테고리의 다른 글
[Spring Project] 코인 자동매매 프로그램 만들기 - 4. 슬랙 api 연동 (0) | 2022.10.26 |
---|---|
[Spring Project] 코인 자동매매 프로그램 만들기 - 2. 업비트 매수, 매수 취소 (0) | 2022.10.21 |
[Spring Project] 코인 자동매매 프로그램 만들기 - 1. 업비트 API 호출 + 시세 종목 조회 (0) | 2022.10.20 |
댓글