개발 이야기/주식 자동 매매 프로그램

키움 증권 API를 이용하여 주식 자동 매매 프로그램 개발하기 - 계좌 잔고 조회 (2) [Python]

제이온 (Jayon) 2021. 1. 22.

 

 

안녕하세요? 코딩중독입니다.

 

저번 시간에는 싱글 데이터를 얻어 와서 계좌의 수익률을 출력해 보았습니다. 오늘은 각 종목별 수익률을 알 수 있는 멀티 데이터를 얻어오는 방법을 설명하겠습니다.

 

 

알아야 하는 이론

저번 포스팅에서 KOA Studio를 이용하여 계좌평가잔고내역 트랜잭션을 요청한 적이 있습니다. 그리고 거기에 대한 출력 결과로는 아래와 같이 나왔습니다.

 

 

 

 

[0] ~ [8]까지는 싱글 데이터에 해당하고, 그 아래 2차원 배열 형태로 나열되는 것이 바로 멀티 데이터입니다. 그렇다면, 이러한 멀티 데이터를 어떻게 받아올 수 있을까요?

 

간단합니다. 우리는 처음에 GetCommData() 함수를 활용하여 싱글 데이터를 얻어 왔는데, 이를 한 번 호출 더 하면 [0][0] ~ [0][x]까지 데이터를 받아올 수 있고, 또 호출하면 [1][0] ~ [1][x]까지의 데이터를 받아올 수 있는 것입니다.

 

중요한 것은 추가로 GetCommData() 함수를 몇 번 호출해야 되는 것인데, 이는 GetRepeatCnt() 함수를 통해 알 수 있습니다. 예를 들어, 여러분이 가지고 있는 종목의 개수가 8개라면, GetRepeatCnt() 함수에서 8이 반환되는 것입니다. 그리고 반복문을 통해서 8번 GetCommData() 함수를 호출하면 되는 것입니다.

 

그런데, 여기서 문제가 하나 있습니다. 만약, 여러분이 가지고 있는 종목의 개수가 20개가 넘어간다면, GetRepeatCnt() 함수에서는 20이 반환됩니다. 즉, 모든 종목을 가져올 수 없다는 의미죠. 이럴 때는 트랜잭션 요청을 한 번 더 해야합니다.

 

위의 내용을 게시판으로 예시를 들겠습니다. 우리가 어떠한 커뮤니티를 운영하고 있는데, 현재 게시물이 1000개가 있다고 칩시다. 이것을 한 페이지에 전부 보여줘도 되지만, 양이 방대하고 쓸데없이 스크롤이 길어질 것입니다. 그래서 보통 한 페이지에 20개의 게시물 정도로 제한하고, 다음 페이지로 이동해야 새로운 20개의 게시물을 볼 수 있도록 설계합니다.

 

키움증권 api도 마찬가지입니다. 한 번에 모든 데이터를 조회하지 않고, 일정한 개수 제한을 둔 후, '다음' 버튼을 눌러야 새로운 데이터를 조회하도록 만들어졌습니다. 그리고 이러한 '다음' 버튼이 바로 sPrevNext 변수입니다. 전에 포스팅에서 말씀드렸듯이, sPrevNext는 "2"일 경우 다음 페이지가 있으니 더 데이터를 조회할 수 있다는 의미라고 말씀드린 적이 있습니다. 그리고 조사해보니, 처음에는 이 sPrevNext는 0으로 초기화해야합니다. 만약, 처음부터 2로 초기화한다면 요청 결과를 영원히 가져오질 못하였습니다. (이 부분은 이유는 잘 모르곘습니다.)

 

제가 디버그하는 과정 일부분을 보여드리겠습니다. 저는 현재 종목의 개수가 22개이고, 맨 처음 트랜잭션 요청할 때 nPrevNext으로 초기화해 두었습니다.

 

 

 

 

i는 무시하고, cnt는 GetRepeatCnt() 함수를 통해 얻어온 값입니다. 위 사진을 보면 알 수 있듯이, 제 종목은 22개인데도 cnt의 값이 22가 아닌 20임을 알 수 있습니다. 또한, 맨 처음 트랜잭션 요청할 때 nPrevNext를 0으로 넘겼지만, 프로그램 내에서 자동으로 '다음' 버튼을 눌러서 조회할 데이터가 있다면 자동으로 sPrevNext의 값이 '2'로 초기화된다는 사실을 알 수 있습니다.

 

 

 

 

그리고 한 번 더 트랜잭션 요청을 하면, 위와 같이 남은 종목의 개수 2개가 반환되고, sPrevNext는 빈 문자열로 반환됩니다. '0'으로 반환될 줄 알았는데 빈 문자열인 이유는 잘 모르겠습니다.

 

 

사용될 함수

싱글 데이터에서 사용하였던 함수는 그대로 이용됩니다. 이번 시간에 새로 사용할 함수는 GetRepeatCnt() 밖에 없습니다.

 

 

 

 

내용은 간단합니다. 트랜잭션 이름과 레코드 이름을 인자로 넘기면, 조회할 멀티 데이터의 개수를 얻어올 수 있습니다. 다만, 설명에 아쉬운 점은 최대 20개라고 표시해 주었으면 더 좋았을 것 같습니다.

 

 

전체 소스코드

 

 

__init__()

 

 

__init__() 함수에서 계좌평가잔고내역 멀티데이터를 위한 변수와 함수가 추가되었고, 초기값을 모두 None으로 수정하였습니다. 특히, 종목들은 딕셔너리로 관리해야 나중에 쉽게 써먹을 수 있습니다.

 

 

트랜잭션 요청 함수

 

 

기존의 tr_slot()에서 추가된 점은 위와 같습니다. 종목의 개수를 GetRepeatCnt() 함수를 통해 최대 20개까지 얻어오고, cnt번만큼 반복문을 돌면서 종목명, 평가손익, 수익률(%), 매입가, 보유수량, 매매가능수량, 현재가에 관한 데이터를 GetCommData() 함수를 이용하여 얻어 옵니다. 그리고 각 데이터를 int또는 float로 형변환하여 딕셔너리에 저장하는 것입니다.

 

중요한 것은 종목의 코드를 가져올 때, 0번째 인덱스는 제외하고 가져와야 한다는 것입니다. 이상하게 필요없이 A라는 문자가 붙어서 코드가 나오더라고요. 그리고 strip() 함수를 통해 쓸데없는 공백을 지워주셔야합니다. 안 그러면, 뒤로 쭈욱 공백이 생깁니다.

 

그 외에 종목의 데이터를 받아올 때, 종목명만 strip() 처리를 해 주시고 나머지는 int와 float로 형변환해 주시면 됩니다. int나 float로 형변환할 때는 자동으로 공백이 지워지는 것을 확인하였습니다.

 

딕셔너리는 기본적으로 key를 종목의 코드를 갖고, value는 또 다른 딕셔너리를 갖는데, value에는 {'종목명': '수젠텍'}과 같이 들어갑니다.

 

마지막으로, 만약 조회할 종목이 더 있다면 (sPrevNext가 "2"라는 의미) 계속해서 트랜잭션 요청을 시도하고, 그렇지 않다면 수행한 이벤트 루프를 종료하고 화면 번호를 끊어주면 됩니다.

 

 

여기까지 멀티 데이터를 조회하는 로직은 끝났습니다. 다만, 한 가지를 주의해 주셔야합니다.

 

 

 

 

이 함수가 계좌평가잔고내역요청 트랜잭션을 요청하는 함수인데, 연속으로 반복할 때, 이미 이벤트 루프가 수행 중인지 확인해 주셔야합니다. QEventLoop.isRunning()를 통해 현재 이벤트 루프가 수행 중인지 확인할 수 있으며, 이벤트 루프가 이미 수행 중일 때는 패스하도록 설계하면 됩니다.

 

 

출력 과정 (선택)

 

 

출력을 보시면 웬 처음 보시는 것이 있을 겁니다. 저는 종목의 정보를 이쁘게 표로 그리고 싶어서 BeautifulTable이라는 라이브러리를 설치하였습니다. 설치는 "pip3 install BeautifulTable" 명령어를 입력하시면 되고, 자세한 사용 설명은 이곳에 잘 나와 있습니다.

 

만약, 굳이 표로 하고 싶지 않고 글로 나열하고 싶다면 자유롭게 하시면 되겠습니다.

 

 

출력 결과

 

 

메뉴 구성은 동일합니다. 4번을 입력해 봅시다.

 

 

 

 

싱글 데이터와 멀티 데이터가 모두 잘 나오는 군요! 멀티 데이터는 22개인데, 분량상 이정도면 올렸습니다.

 

 

정리

지금까지 종목별 정보를 얻어오는 방법에 대해서 학습하였습니다. 다음 시간에는 미체결 종목을 가져오는 방법을 다뤄보겠습니다.

 

 

출처

프로그램 동산(장용준)님이 집필하신 '손가락 하나 까딱하지 않는 주식 거래 시스템 구축' 교재를 참고하여 작성하였습니다.

 

그 외에 프로그램 동산님은 깃허브, 카페, 유튜브를 운영 중이십니다. 굉장히 도움이 되는 내용이 많으니 참고하셔도 좋을 것 같습니다.

 

(깃허브) github.com/programgarden

(유튜브) www.youtube.com/channel/UCq7fsrxP6oi6vnYgPkw92jg

(네이버 카페) cafe.naver.com/programgarden

댓글

추천 글