본문 바로가기

키움 OpenAPI

키움 증권 Open API 파이썬 연동 개발환경 셋업 (윈도우즈 10)

가치투자를 위한 첫걸음

오롯이 감에 의존하여 손에 들고 있는 한푼 돈으로 소위 인기있다는 종목을 남들 따라 사고 나서 겪었던 좌절감들. 왜 내가 사면 떨어지고 내가 팔면 오르는지. 투자에 대한 철학도 없고 지식도 없고 마구잡이 식으로 하다가 소위 '가치투자'라는 어찌보면 흔해빠진, 그러나 어떻게 하는지는 당췌 모르겠는, 용어를 접하고 인터넷을 이리저리 찾아 헤매다 몇몇 선인의 유튜브 영상들을 접하고 왠지 내가 가야할 방향은 이게 아닌가 싶었다.

어느날 '슈퍼개미 김정환'이라는 분의 영상에서 '퀀트'라는 익숙치 않은 용어와 동시에 '파이썬'이라는 익숙한 용어를 동시에 들었을 때 '우선 숫자를 기반으로 기업의 가치를 따지는 밸류에이션 작업을 해야 하는구나' 라는 걸 알게되었다. 이 분이 좋고 싼 기업을 걸러내는 작업을 할 때 가장 처음에 하는 기본적인 작업이었다.

키움증권의 영웅문같은 프로그램을 잘 찾아보면 내가 원하는 기능이 이미 있는지도 모르겠다. 그러나 이미 내가 할 수 있는 방법을 찾았으므로 이 방법으로 한번 내가 원하는 데이타를 뽑아내 그 분의 결과와 비교해 보기로 했다.

 

'퀀트'란 모형을 기반으로 금융상품의 가격을 산정하거나, 이를 바탕으로 투자를 하는 사람을 말한다. 퀀트(Quant)라는 단어가 '계량적'을 의미하는 Quantitative의 앞글자를 따왔다고 한다. 퀀트 투자란 수학과 통계를 기반으로 전략을 만들고 이를 바탕으로 투자를 하는 정량적인 투자법을 의미한다. 그러나, 제공된 모든 데이타들이 가짜이거나 유리하게 조작된 경우가 있을 수 있으므로 전적으로 이 데이타 결과만으로 투자를 하는 것은 위험할 수 있다.

필요 패키지 설치

개발 환경 셋업은 너무나도 고맙게도 인터넷의 많은 분들이 키움증권의 OpenAPI와 파이썬을 연동해서 테스트해보는 예제를 소개하고 있어서 굳이 내가 중복된 글을 쓸 필요가 없을 것 같다.

 

한가지 궁금한 건 wine을 사용하면 리눅스나 맥OS에서 OpenAPI ocx컨트롤을 사용할 수 있지 않을까 하는 것인데 지금 당장 필요성을 못느껴서 다음에 시간이 남아 돌고 할일이 없을 때 해봐야 겠다고 생각을 해본다. 이론적으로는 아무 문제없이 될 것 같다. 다행이 윈도우즈 10 환경이 있어서 굳이 리눅스나 맥OS를 고집할 이유가 없다.

 

다음은 내가 설치한 패키지들의 리스트와 순서이다. 기본적으로 toptrader님의 블로그를 따라했다. 링크참조.

1. 키움 OpenAPI 설치

2. 키움 모의투자 신청

3. KOA Studio 다운로드 및 설치

   개발자 용 어플정도로 보면 된다. 모의투자로만 접속이 가능하고 제공하는 API의 예제코드를 친절히 보여준다.

   신청 후 모의투자 접속을 하게 되면 버전처리에 관한 팝업이 뜨는데 하라는대로 진행하면 된다.

4. 아나콘다 32bit 버전 설치

5. VSCode 설치

   예전에는 아나콘다 내에서 설치가 가능했던 것 같은데 지금은 보이지 않아서 VSCode사이트에서 다운받아 설치했다.

   python extension 플러그인까지 설치를 해야 한다.

6. PIP 설치

   PyQt5 설치를 위해서 필요하여 PIP사이트에서 다운받아 설치하였다.

7. PyQt5 설치

   pip 명령어로 간단히 인스톨 가능했다.

8. helloworld.py 테스트

   VSCode에서 conda환경 사용하기 참조. conda 사용에 관한 설정문제가 있었는데 Settings.json 수정으로 해결되었다.

9. OpenAPI & PyQt5 테스트

   VSCode에서 PyQt5패키지를 인식못하는 문제가 있었는데 Settings.json 수정으로 해결되었다.

   테스트 코드는 t9story님의 블로그에 첨부된 opt10001.py를 사용했다.

 

모든 문제 수정 후 Settings.json의 결과 파일이다.

{
    "editor.suggestSelection": "first",
    "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue",
    "terminal.integrated.shellArgs.windows": null,
    "terminal.integrated.shell.windows": "C:\\Windows\\System32\\cmd.exe",
    "terminal.integrated.shellArgs.windows": ["/K", "C:\\Users\\mole\\anaconda3\\Scripts\\activate.bat C:\\Users\\mole\\anaconda3"],
    "python.linting.pylintArgs": ["--extension-pkg-whitelist=PyQt5"]
}

 

10. t9story님의 opt10001.py 수정.

   보기 편하도록 몇가지를 수정했다.

   - 함수를 좀더 모듈화하였다.

   - 레이아웃을 조금 바꾸었다. 박스레이아웃을 사용하려 했으나 kiwoom모듈이 setLayout함수 오류를 일으켜 그대로 고정 레이아웃을 이용했다.

   - QLineEdit를 상속한 MyLineEdit를 만들어 포커스가 갔을 때 안내 문자열이 사라져 종목코드 입력을 편하게 했다.

   - 상태바에 로그인 상태를 표시하도록 추가했다.

 

링크

OpenAPI 설치 & 설정 가이드: https://toptrader.tistory.com/9

VsCode에서 PyQt5 패키지 인식문제 Settings.json 수정으로 해결: https://toptrader.tistory.com/9

VsCode에서 conda환경 사용하기: https://m.blog.naver.com/hankrah/221813093799

PIP 설치: https://pip.pypa.io/en/stable/installing/

VSCode: code.visualstudio.com/

파이썬으로 배우는 알고리즘 트레이딩 (개정판-2쇄): https://wikidocs.net/4240

기본정보가져오기 파이썬 코드 (이 글 코드의 베이스코드이다.): https://t9story.tistory.com/4

키움 OpenAPI 매뉴얼: https://download.kiwoom.com/web/openapi/kiwoom_openapi_plus_devguide_ver_1.5.pdf

PyQt5 튜토리얼: https://wikidocs.net/22413

 

테스트 코드

위에서 밝혔듯이 https://t9story.tistory.com/4 의 opt10001.py를 바탕으로 입맛에 맞게 수정하였다. 이 소스를 더 수정하여 나만의 투자기업 리스트를 뽑을려고 한다.

 

import sys
import time
import pandas as pd

from PyQt5.QtWidgets import *
from PyQt5.QAxContainer import *
from PyQt5.QtGui import *

class MyLineEdit(QLineEdit):
	def focusInEvent(self, event):
		if self.text() == "종목코드를 입력하세요":
			self.setText('')
			self.setMaxLength(6)
		super(MyLineEdit, self).focusInEvent(event)

class Kiwoom(QMainWindow):
	def initUI(self):
		self.setWindowTitle("Opt10001")
		self.setGeometry(300, 300, 800, 600)

		self.statusBar().showMessage("Not Connected")

		self.JongMok_label = QLabel('종목코드:', self)
		self.JongMok_label.move(20, 20)

		self.JongMok_lineedit = MyLineEdit(self)
		self.JongMok_lineedit.setGeometry(130, 20, 200, 30)
		self.JongMok_lineedit.setText('종목코드를 입력하세요')

		self.JongMok_button = QPushButton('조회', self)
		self.JongMok_button.move(350, 20)
		self.JongMok_button.clicked.connect(self.jongmok_button_clicked)
		self.JongMok_button.setFocus()

		self.JongMok_result = QTextEdit(self)
		self.JongMok_result.setGeometry(10, 60, 780, 500)
		self.JongMok_result.setEnabled(True)

	def login(self):
		# Connect
		self.kiwoom = QAxWidget()
		self.kiwoom.setControl("KHOPENAPI.KHOpenAPICtrl.1")
		self.kiwoom.dynamicCall("CommConnect()")

		# OpenAPI+ Event
		self.kiwoom.OnEventConnect.connect(self.event_connect)
		self.kiwoom.OnReceiveTrData.connect(self.receive_tr_data)

	def __init__(self):
		super().__init__()
		self.initUI()
		self.login()

	def event_connect(self, err_code):
		if err_code == 0:
			self.statusBar().showMessage("Connected")
		else:
			self.statusBar().showMessage("Connection Failed (err:%d)" % err_code)

	def jongmok_button_clicked(self):
		code = self.JongMok_lineedit.text()
		self.JongMok_result.append("종목코드:" + code)

		# SetInputValue
		self.kiwoom.dynamicCall("SetInputValue(QString, QString)", "종목코드",  code)
		# CommRqData
		self.kiwoom.dynamicCall("CommRqData(QString, QString, int, QString)",
								"opt10001_req", "opt10001", 0, "0101")

	def receive_tr_data(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2):
		print("리시브로 들어옴 err_code:%s, msg1=%s, msg2=%s"%(err_code, msg1, msg2))
		if rqname == "opt10001_req":
			name = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString",
										   trcode, recordname, 0, "종목명")
			volume = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString",
											 trcode, recordname, 0, "거래량")
			numStocks = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString",
											 trcode, recordname, 0, "상장주식")
			prices = self.kiwoom.dynamicCall("GetCommData(QString, QString, int, QString",
											 trcode, recordname, 0, "시가")

			self.JongMok_result.append("종목명:" + name.strip())
			self.JongMok_result.append("거래량:" + volume.strip())
			self.JongMok_result.append("상장주식:" + numStocks.strip())
			self.JongMok_result.append("시가:" + prices.strip())


if __name__=="__main__":
	app = QApplication(sys.argv)
	myWindow = Kiwoom()
	myWindow.show()
	app.exec_()

소스코드

https://github.com/mole-cricket/kiwoom-openapi

 

mole-cricket/kiwoom-openapi

Contribute to mole-cricket/kiwoom-openapi development by creating an account on GitHub.

github.com

테스트한 소스코드는 위 github에서 모두 다운받을 수 있습니다.