카테고리 없음

키움증권 OpenAPI 실행 및 로그인하기

  • -

앞의 포스팅에서는 개발 가이드의 사용 방법에 대해 알아보았고, 이제는 본격적으로 파이썬을 바탕으로 해서 키움증권의 Open API와 연결한 후에 여러 가지 동작을 실행하는 코드를 제작해보고자 한다.

 

Open API와 연결하기

키움증권에서 제공하는 Open API 개발가이드 내에서 라이브러리 구성 파일에 대한 설명이 있다. 

파일명 설명
KHOpenAPI.ocx OpenAPI 실행 모듈
OPCommApi.dll 통신 모듈
OPComms.dll 서버와의 TCP/IP 연결 모듈
OPSecurity.dll 통신 암호화 모듈
librsadlx.dll  
nsldap32v11.dll  
ZIPDLL.DLL 압축 모듈

우리는 이 중에서 가장 먼저 OpenAPI를 실행하도록 하는 모듈인 KHOpenAPI.ocx를 실행하도록 하는 코드를 구축해야 한다. 여기서 KHOpenAPI.ocx가 하나의 모듈이라 나와 있는데, 다른 포스팅에서 모듈을 사용하는 방법에 대해 다양하게 서술했었다. 간단하게 말해보자면, 모듈.함수의 형태로 입력하면 해당 정보를 사용할 수 있게 된다. 그를 바탕으로 OpenAPI를 실행하도록 하는 코드를 구축하면 아래와 같은 형태가 나오게 된다.

import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class system_trading():
    def __init__(self):
        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")

일단 위와 같은 코드를 작성을 하게 되면, 키움증권에서 제공하는 OpenAPI를 동작하도록 하는 코드는 모두 구축된 것이다. 클래스(class)와 함수(def)에 대한 내용은 크게 이해하려 하지 않아도 본인만 사용할 프로그램을 제작하는 데에는 큰 문제가 없다고 생각되니 생략하도록 하고, def __init__(self)는 단순하게 해당 클래스가 실행되었을 때, 가장 먼저 실행되는 함수이다. 즉, 이 클래스가 실행될 경우 def __init__(self) 안에 있는 코드를 먼저 실행하게 되는 것이다.
다만 위와 같은 코드는 실행을 하더라도 아무런 동작도 이루어지지 않는다는 것을 확인할 수 있는데, 그 이유는 바로 그 클래스가 동작하도록 하는 문구가 없기 때문이다.  다시 말해, class system_trading(): 이라는 클래스를 실행하기 위해서는 그 클래스가 실행되도록 하는 코드가 포함되어야 한다는 것이다. 

 

클래스(Class) 실행하기

그렇다면 클래스는 어떻게 실행할 수 있을까? 방법은 단순하다. 해당 클래스를 작성하면 그대로 실행하게 된다.

# 클래스 실행하는 방법
class_name()

다만 클래스를 실행하도록 하는 코드는 단순하게 class_name()만 제작한다고 실행되지는 않는다. 앞의 def __init__(self)에서 볼 수 있듯이 def __init__ (self)가 요구하는 변수를 입력해야 한다. 왜냐하면 Class가 실행됐을 때 가장 먼저 실행되는 함수이기도 하고, 그 함수에서 요구하는 변수가 없다면 실행에 있어서 오류가 발생하기 때문이다. 따라서 우리는 Class를 실행하고자 할 때 def __init__(self, 변수)가 있다면 class_name(변수)를 통해, def __init__(self)가 없거나 self 뒤에 변수가 없다면 class_name()을 통해 해당 클래스가 동작하도록 명령을 내릴 수 있다. 앞서 우리가 제작한 코드 내에는 __init__ (self)이며 self 뒤에는 추가적인 변수가 없으므로 아래와 같이 입력한다면 해당 클래스를 실행할 수 있게 된다.

또한 해당 클래스가 자동으로 실행하도록 하기 위해 우리는 __name__이라는 변수를 사용할 것이다. 이는 해당 파일이 직접 실행된 경우에는 __name__이 __main__이라는 값으로 반환되고 직접 실행된 게 아니라면 다른 값이 반환된다. 이를 바탕으로 아래와 같은 코드를 구축할 수 있다.

if __name__ == "__main__":
	app = QApplication(sys.argv)
	system_trading()

 

Open API를 통해 키움증권 서버에 로그인하기

앞전의 포스팅에서 다루었듯이, 개발 가이드를 보면 OnEventConnect 이벤트에 대한 설명이 있는데, 아직 읽지 않았다면 꼭 읽는 것을 권하는 바이다. 왜냐하면 어떤 상황에서 어떤 이벤트가 발생하는지를 정리해두었기 때문이다.

 

키움증권 Open API 개발 가이드 사용 설명서 (1)

키움증권에서는 자사의 Open API의 사용 방법에 대해 기본적인 가이드 자료를 제공하고 있다. 다만 기본적으로 제공하는 함수의 형태가 파이썬에서 사용하기가 다소 어려운 형태로 되어 있기 때

trustyou.tistory.com

본론으로 돌아와, 로그인을 요청할 때 사용할 함수는 CommConnect()이다. 개발가이드 내 이 함수에 대한 설명은 다음과 같이 서술되어 있다.

원형 LONG CommConnect()
설명 로그인 윈도우를 실행한다.
입력값 없음
반환값 0은 성공, 음수값은 실패
비고 로그인이 성공하거나 실패하는 경우 OnEventConnect 이벤트가 발생하고 이벤트의 인자 값으로 성공 여부를 알 수 있다.

참고로, 키움증권 OpenAPI 중에서 함수를 실행하기 위한 함수는 dynamicCall()이다. 앞서 이야기했듯이 우리는 self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")이라는 코드를 통해 OpenAPI를 실행하도록 하였으니 키움증권에서 제공하고 있는 함수를 실행하기 위한 사용 방법은 self.kiwoom.dynamicCall()이 되는 것이다. 따라서 CommConnect() 함수를 사용하기 위해서는 다음과 같이 작성하면 된다.

self.kiwoom.dynamicCall("CommConnect()")

CommConnect()에 대한 개발 가이드 내 설명에서 볼 수 있듯이 별도의 입력값이 필요하지 않으므로, 아무런 값을 입력하지 않고 실행해도 된다.

그렇다면 이제 위의 '비고' 란에서 확인했듯이 CommConnect()가 실행되면 OnEventConnect 이벤트가 발생한다고 했다. 그렇다면 OnEventConnect 이벤트가 발생했을 경우 그 이후의 동작을 처리해 줄 함수를 작성하고, 해당 이벤트와 해당 함수를 연결해주어야 할 필요가 있다. 왜냐하면 지금까지의 상황으로 보면 로그인 요청을 했고 그에 따라 서버에서 로그인이 성공했는지 실패했는지 등에 대한 결과 정보를 반환하였으나 지금까지 작성한 우리의 코드는 그 결과값을 처리할 수 있는 코드가 빠져 있는 셈이다. 다시 말해, 정보는 요청해놓고 그 결과는 안 보겠다는 것이다. 이벤트와 함수를 연결하는 방법은 앞서 이야기했듯이, 아래와 같이 작성할 수 있다.

self.kiwoom.OnEventConnect.connect(self.OnEventConnect)

뒤에 있는 self.OnEventConnect는 함수이고, 앞에 있는 OnEventConnect는 이벤트이다. 즉, self.kiwoom 내에서 OnEventConnect라는 이벤트가 발생했을 경우, self.OnEventConnect라는 함수로 연결(connect)하라는 내용이다. 

이제 연결되도록 했으니 코드 내에서 별도의 함수를 추가로 제작하면 된다. 다만 여기서 주의해야 할 점은, 앞서 개발 가이드 내에서의 설명에서도 보았듯이 로그인의 성공과 실패 여부를 확인하는 반환값을 제공한다. 그렇다면 그 값을 해당 함수 내에서 받아 올 필요가 있기 때문에, 다음과 같이 코드를 제작할 수 있다.

def OnEventConnect(self, err_code):

 

위 함수의 변수로 설정되어 있는 err_code는 에러 코드(error code)를 나타낸 것이다. 이제 이 값이 0이라면 로그인에 성공한 것이고 0이 아닌 음수라면 로그인에 실패했다는 결과값을 우리는 확인할 수 있게 되는 것이다. 그렇다면 if문을 통해 err_code가 0인 경우와 0이 아닌 경우로 나누어 로그인 요청의 결과값을 처리할 수 있다.

	def OnEventConnect(self, err_code):
		if err_code == 0:
			print("로그인에 성공하였습니다.")
		else:
			print("로그인에 실패하였습니다.")

 

지금까지 제작한 코드는 아래와 같다.

import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class system_trading():
	def __init__(self):
		self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
		self.kiwoom.dynamicCall("CommConnect()")	
        
		# 이벤트 발생 처리
		self.kiwoom.OnEventConnect.connect(self.OnEventConnect)

	def OnEventConnect(self, err_code):
		if err_code == 0:
			print("로그인에 성공하였습니다.")
		else:
			print("로그인에 실패하였습니다.")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    system_trading()

 

하지만 로그인을 요청했음에도 불구하고 별다른 반응 없이 시스템이 종료되는 현상이 발생하게 되는데, 그는 바로 로그인 요청 이후에 곧바로 다음 코드가 실행되는 등의 문제가 있기 때문이다. 따라서 이는 아래의 코드를 로그인 요청 이후에 추가함으로써, 다음 동작을 기다리라는 명령을 내릴 수 있게 된다.

self.login_event_loop = QEventLoop()
self.login_event_loop.exec_()

위 코드를 추가하기 전에는 연결되었다는 문구가 출력된 후 Process finished with exit code 0라는 메시지가 출력되었으나, 위 코드를 추가한 후에는 해당 메시지가 출력되지 않는다는 것을 확인할 수 있다.

다만, 이 내용은 바로 이벤트 루프를 동작하도록 하는 것이기 때문에 이벤트 루프를 종료하도록 하는 코드도 따루 구축해주어야 한다. 즉, 로그인을 요청한 후에 이벤트가 발생하게 되니 그 이벤트를 기다리라고 했다면, 이벤트가 발생하고 후처리를 완료하였다면 이벤트 루프를 종료해주어야 다음 코드로 넘어갈 수 있게 되는 것이다. 이와 관련해서는 다음 게시글, 차트 데이터 조회하기 (1)편의 마지막 부분에서 언급할 예정이다. 왜냐하면 차트 데이터를 조회할 때에도 이벤트 루프를 사용해야만 하기 때문에 차트 데이터에서 사용되는 이벤트 루프와 함께 설명할 예정이다.

 

이번 포스팅 최종 결과물

import sys
from PyQt5.QAxContainer import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

class system_trading():
	def __init__(self):
		self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")
		self.kiwoom.dynamicCall("CommConnect()")	
		self.login_event_loop = QEventLoop()
		self.login_event_loop.exec_()
        
		# 이벤트 발생 처리
		self.kiwoom.OnEventConnect.connect(self.OnEventConnect)

	def OnEventConnect(self, err_code):
		if err_code == 0:
			print("로그인에 성공하였습니다.")
		else:
			print("로그인에 실패하였습니다.")


if __name__ == "__main__":
    app = QApplication(sys.argv)
    system_trading()
728x90
반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.