IT 서비스 제작과정/개발

[업비트/코인] 급등종목 모니터링 시스템 구현

세가사 2024. 4. 13. 02:21
반응형

 

 

코인 단타 매매를 위한 모니터링 시스템 디자인

최근 업비트 코인 근황을 살펴보니 갑작스레 수급이 쏠려 급등하는 종목이 전체 코인 시장 하락장이 아닌 이상 하루에 한개에서 세가지 정도 발생하고 있으며 한번 상승하면 10-40 프로정도의 상

gran007.tistory.com

 

업비트 OPEN API를 사용해 코인 단타를 위한 모니터링 시스템을 개발해보자.

 

일단 내가 모니터링할 마켓 데이터의 코드가 필요하다.

 

업비트 마켓데이터는 다음 주소( https://api.upbit.com/v1/market/all )를 통해 얻어올수 있다.

 

마켓 정보를 얻어서 json파일로 저장해 둔다.

 

편의를 위해 원화로 구입가능한 코인들만을 모니터링 하고자 한다.

 

code 앞자리가 KRW로 시작하는 데이터만 읽어온다.

const markets = require('./market.json').filter(item=>item.market.startsWith('KRW'));

 

모니터링 할 데이터는 ["KRW-1", "KRW-2"] 같은 형태로 웹소켓 API에 전달해주어야 한다. 이를 위한 code 필드를 선언하자.

const codes = markets.map((item) => `"${item.market}"`).join(",")

 

코드기준으로 들어오는 데이터를 저장할 변수도 필요하다. 저장될 데이터의 형태는 다음과 같다.

const coinData = {
  "KRW-1": { // 코드명 & 인식키값
    name : "1코인", // 코드 한글명    
    data: [ // 1분간의 데이터를 저장
      {"price": 100, "timestamp": 100000000},
      {"price": 101, "timestamp": 100000010},
      {"price": 102, "timestamp": 100000020},
      {"price": 103, "timestamp": 100000030},
      ...
    ]
  }
}

 

앞의 market 값을 사용해 coinData를 자동 생성하자.

const coinData = {};
markets.forEach((item) => {
    coinData[item.market] = { name: item.korean_name, data: [] };
});

 

웹소켓의 기본적인 사용법은 업비트 실시간 OPEN API 사용법 중 websocket 사용법을 따르고

 

 

[비트코인] 업비트 실시간 시세 받아오기

업비트 시세를 받는 방식은 두가지로 나뉘어져 있다. 1. REST API를 사용하는 방식 2.웹소켓을 이용하는 방식 1. REST API 호출방식 REST API를 사용하는 방식을 사용할때는 따로 IP 등록이나 OPEN API 전용

gran007.tistory.com

 

이중 ws.send할때 위에 선언한 마켓코드 묶음을 같이 보내는 부분만 수정해준다.

ws.on("open", () => {
    console.log("connected!");
    ws.send(`[{"ticket":"${uuidv4()}"},{"type":"ticker","codes":[${codes}],"isOnlyRealtime": true}]`);
});

 

중요한것은 메시지를 받아왔을 때의 처리이다. 일단 내가 원하는 기준 시간과 퍼센트를 선언한다.

const ONE_MINUTE = 60 * 1000;
const TARGET_PERCENT = 1;

1분의 시간동안 1퍼센트 이상 튀는 데이터는 콘솔출력을 하게 할것이다.

일단 메시지를 받아오면 message 데이터를 string형태로 바꿔서 이중 코인코드, 코인가격, 시간값을 추출한다.

ws.on("message", (message) => {
    const json = JSON.parse(message.toString())
    const { code, trade_price: price, timestamp } = json;

 

처음 선언해두었던 coinData에서 해당 코드 값을 키값으로 data를 받아온다. 앞으로 이 data 필드에 받아온 데이터를 차곡차곡 쌓아놓고 가장 빠른 시간의 데이터와 마지막에 받아온 데이터의 가격을 비교해서 1프로를 초과할 경우 콘솔 출력을 하도록 한다.

 

하지만 계속 쌓아가는 방법을 사용하면 1시간 2시간 전의 데이터와도 비교를 하게 되기 때문에 해당 data 필드의 값들은 마지막 데이터와 비교해서 1분을 넘지 못하도록 계속 앞부분을 제거해 주어야 한다.

const { data } = coinData[code];
// 1분 전의 데이터 삭제
const dataBeforeOneMinute = data.filter(x => x.timestamp >= (timestamp - ONE_MINUTE));
// 맨 앞의 데이터를 가져오기 위한 시간별 정렬
dataBeforeOneMinute.sort((a, b) => a.timestamp - b.timestamp);
if (dataBeforeOneMinute.length > 0) {
    // 제일 앞의 가격 가져오기
    const { price: first_price } = dataBeforeOneMinute[0];
    // 퍼센트 계산
    const percentage = (price - parseFloat(first_price)) / parseFloat(first_price) * 100;
    // 기준 퍼센트인 1을 초과하면
    if(percentage >= TARGET_PERCENT) {
      // 알림 출력
    }
}
dataBeforeOneMinute.push({ price, timestamp });
coinData[code].data = dataBeforeOneMinute;

 

퍼센트는 0.34213 이런식으로 표기 되기 때문에 이를 2자리수 내림으로 보여주기 위해 다음 함수를 추가한다.

0.34213 => 0.34

const getPercent = (price) => Math.floor(price * 100) / 100;

 

마지막으로 알림을 출력할때 1분 0초와 2분 0초의 가격차가 1퍼센트를 넘으면 알림을 보내지만 1분 1초와 2분 2초에도 이 간격이 유지되면 알림을 계속 보내야한다. 너무 잦은 알림은 기존의 설계의도와 일치하지 않기 때문에 한번 알림을 보내면 1분간은 알림을 보내지 않도록 기록을 해두어야 할 필요가 있다. 이를 위해 코드별 마지막 알림 시간을 기록해두는 변수가 필요하다.

const lastAlert = {}

 

알림을 보낼때는 마지막 알림 보낸 시간이 있는지 여부를 검사해서 처음보내는 알림이거나 마지막 보낸시간에서 1분이 지나면 다시 알림을 보내도록하고, 1분이 안지났으면 알림이 가지 않도록 코드를 구성한다.

if(code in lastAlert && lastAlert[code] <= timestamp - ONE_MINUTE) {
    delete lastAlert[code];
}
if(!(code in lastAlert)) {
    lastAlert[code] = timestamp;
    console.log(`${coinData[code].name}/${code}`, 
    `${first_price}->${price} / (${getPercent(percentage)})`, 
    new Date(timestamp));
}

 

 

이제 프로그램을 실행하면 다음과 같이 1분동안 1프로 이상 오른 코인에 대해서 콘솔에 출력을 해준다.

 

일단 몇번의 테스트 뒤에 추출된 결과가 쓸만하면 슬랙 웹훅을 연동해 실시간 알림을 내 스마트폰으로 받도록 할 예정이다.

반응형