키움 증권 API를 이용하여 주식 자동 매매 프로그램 개발하기 - sqlite3 DB에 저장된 일봉 데이터를 업데이트하는 방법 [Python]
안녕하세요? 코딩중독입니다.
저번 시간에는 SQLite3에 일봉 데이터를 저장하는 방법에 대해서 알아보았습니다. 오늘은 SQLite3에 저장된 일봉데이터를 업데이트해 보겠습니다.
업데이트 방법
저번 포스팅까지 따라오셨더라면 2021년 1월 27일까지의 일봉데이터가 저장되어있으실 겁니다. 그리고 이 데이터들은 주말이나 공휴일을 제외한 날에는 매일 업데이트를 해 줘야 합니다. 그래야 그랜빌의 매수 신호에 따라 얻어지는 종목이 달라지기 때문이죠.
그래서 두 가지 케이스로 나누어서 업데이트를 할 것입니다. 전자는 종목이 DB 내의 테이블에 존재하지 않을 경우 새로 테이블에 추가하고 상장일부터 오늘 날짜까지 일봉 데이터를 추가하는 것이고, 후자는 오늘 날짜부터 튜플 내의 이미 존재하는 날짜 다음날까지 일봉 데이터를 추가하는 것입니다. 후자의 경우, 만약 2021년 1월 27일까지 일봉 데이터가 있다면, 1월 28일, 1월 29일, ..., 오늘 날짜까지 일봉 데이터를 추가한다는 뜻입니다.
전자는 단순히 테이블에 종목을 추가하고, 모든 일봉 데이터를 업데이트하는 것이라서 어렵지 않습니다. 하지만, 후자는 일봉 데이터를 받아오려면 트랜잭션을 요청하는데, 트랜잭션의 요청 결과를 받아오는 tr_data()의 인자를 바꿀 수도 없고, 고작 며칠 간의 일봉 데이터를 받아오기 위해서 상장일부터 현재까지 모든 일봉 데이터를 가져올 필요가 없습니다. 따라서, GetCommDataEx() 함수를 이용하여 600일 간의 일봉 데이터 한 번만 받아 오고 이 데이터를 이용해서 DB를 업데이트할 것입니다.
트랜잭션 요청하는데 딜레이 시간 3.6초와 약간의 연산 시간 합쳐서 하나 업데이트하는 데 4초가 채 걸리지 않고, 현재 코스닥 종목이 1476개이므로 늦어도 2시간 안쪽으로 업데이트가 끝나게 됩니다.
전체 소스코드
DB 업데이트 함수
먼저, 가장 핵심이 되는 함수입니다. 처음에는 테이블 내의 해당 종목이 존재하는지 확인하고 그 종목을 추가해 주고 일봉 데이터를 넣어 줍니다. 해당 종목이 존재한다면 오늘 날짜의 일봉 데이터가 없을 경우에만 새롭게 일봉 데이터를 업데이트해 주어야 합니다. 이때, 오늘 날짜를 구하기 위해서 date 모듈을 사용하였습니다. today() 함수를 이용하여 date 객체를 얻어오고, isoformat() 함수를 통해 "2021-01-30"와 같은 문자열 형태로 받아올 수 있습니다. 그리고 튜플 내의 날짜 데이터는 '-'이 없는 '20210127'과 같은 int 형태이므로 '-'을 제거해 줍니다. 이후에 튜플 내의 날짜 데이터 중 가장 최신 날짜와 오늘 날짜와 비교해서 오늘 날짜가 더 나중이라면 일봉 데이터를 업데이트하면 됩니다. 그리고 이때, day_kiwoom_db() 함수를 호출합니다.
이 함수는 트랜잭션을 요청하는 함수인데, isUpdate라는 인자가 하나 추가되었습니다. 이것은 True일 경우 sRQName을 "주식일봉차트업데이트요청"으로 적용하여 트랜잭션 요청하도록 설계하였습니다. sRQName을 다르게 설정한 이유는 tr_data의 인자를 기존의 형태말고 다르게 넘겨줄 방법을 찾지 못해서 그렇습니다.
여기서 GetCommDataEx() 함수를 통해 최대 600일 간의 일봉 데이터를 얻어오고, 그 리스트를 self.calculator_list에 넘겨준 뒤, save_day_kiwoom_db() 함수를 호출합니다.
save_day_kiwoom_db() 함수도 isUpdate 인자를 추가하였고, 이것이 True일 경우에만 DB에 데이터를 다르게 추가합니다. 먼저, calculator_tuple을 보면 item[1:8]로 slice를 취했는데, 이것은 GetCommDataEx() 함수를 통해 얻어낸 2차원 리스트가 8번째 인덱스이후로는 쭉 빈 문자열이기 때문입니다. (각각의 요소의 길이는 참고로 15입니다.) 그리고 튜플 내의 날짜 데이터가 중복되는 순간에는 함수를 종료하도록 설계하였습니다.
문제점
사실 위와 같은 방식에는 모든 작업이 수행될 동안 프로그램이 불의의 에러로 종료되지 않는다면 정상적으로 동작합니다. 하지만, 업데이트 도중에 프로그램이 종료된다면 문제가 발생할 수 있습니다.
save_day_kiwoom_db() 함수를 보면, 오늘 날짜부터 시작하여 중복되는 날짜까지 역순으로 데이터를 넣는 것을 알 수 있습니다. 만약, 오늘 날짜가 20210130이고, 중복되는 날짜가 20200127이라고 가정해 봅시다. 그렇다면, 20210130, 20210129, 20210128까지의 일봉데이터가 들어가는 것이 정상적입니다.
하지만, 20210129의 일봉데이터를 저장하고 프로그램이 종료된다면 어떻게 될까요? 맞습니다. 20210128의 일봉데이터는 생략이 되는 것입니다. 왜냐하면, save_day_kiwoom_db()의 반복문을 보면 중복된 날짜가 있는 순간 종료하도록 만들었기 때문이죠.
그렇다면, 중복된 날짜가 있는 순간 종료가 아니라 continue를 사용한다면 어떨까요? 물론, 이 방법이 확실하지만, 하나의 테이블의 모든 데이터를 검사해야하므로 시간이 기하급수적으로 증가합니다. 따라서, 저는 시간을 단축하기 위해서 중복된 날짜가 있는 순간 종료하도록 만들되, 장 중이 아닌 주말에는 모든 데이터를 검사해서 업데이트를 하는 방법을 택하였습니다.
정리
지금까지 DB를 업데이트하는 방법을 알아 보았습니다. 사실, 이 방법은 바람직하지는 않다고 생각합니다. 시간 상으로도 여전히 불만족스럽고 프로그램이 비정상적으로 종료된다면 데이터의 손실도 우려되기 때문이죠. 하지만, 저는 뾰족한 방법은 찾지 못해서 이대로 진행하되, 나중에 더 좋은 방안이 생각난다면 수정하도록 하겠습니다. 또한, 여러분의 적극적인 피드백 댓글도 환영합니다.
댓글