eBest xing API
이베스트 xing API
* 이베스트 투자증권 (URL)
- 이베스트 투자증권에서 제공하고 있는 xingAPI는 비교적 쉽게 자동화 시스템을 개발할 수 있는 환경을 제공하고 있다.
- 또한, Python을 이용한 API 호출이 간단한 편에 속한다.
xingAPI
* xingAPI Official Guide Document (URL)
* Package Installation (URL)
- 이베스트 투자증권에서 제공하는 xingAPI는 클라이언트 프로그램에서 사용할 수 있는 API를 제공한다.
- xingAPI는 DLL, COM 버전을 제공하고 있다.
- DLL 방식은 속도가 빠르지만, 사용자 편의성이 COM 방식보다 떨어진다.
- COM 방식은 DLL을 기반으로 실행되지만, 사용자 편의 기능이 포함되어 있다.
- xingAPI는 DevCenter에서 실행한 TR 목록을 DLL이나 COM 방식으로 제공하여
프로그래밍 방식으로 TR을 호출할 수 있게한다.
COM 방식 (URL)
- 컴포넌트 오브젝트 모델로 Microsoft에서 제공하는 응용프로그램의 Binary Interface이다.
- Python에서 COM을 호출하기 위해선 \(\texttt{pywin32}\) Library가 필요하다.
* \(\texttt{pywin32}\) Installation Instruction
pip install pywin32
COM Object in xingAPI | Description |
XASession | - 서버 연결을 확인한다. - 로그인에 사용된다. |
XAQuery | - TR 조회에 사용된다. |
XAReal | - 실시간 정보 조회에 확인된다. (실시간 TR) - 장 중 특정 종목에 대한 거래 정보를 실시간으로 받아볼 수 있게 한다. |
XASession Object (XASession 객체)
- 서버 연결과 로그인에 관련된 기능들을 제공하는 COM 객체이다.
XASession Property | Description |
SendPacketSize | - 한번에 전송되는 데이터의 크기이다. - 기본값은 -1이다. |
ConnectTimeOut | - 서버에 연결을 시도할 때 소요된 시간이다. - ms 단위이다. - 기본값은 10초이다. - Connect 시도 시에 입력된 시간 동안 연결이 되지 않을 경우 TimeOut이 발생한다. |
XASession Methods | Description |
ConnectServer(szServerIP, nServerPort) | - 서버에 연결한다. [Parameters] - szServerIP : 서버 주소 - nServerPort : 포트 번호 [Returns] - True : 연결에 성공 - False : 연결에 실패 |
DisconnectServer | - 서버와의 연결을 종료한다. |
IsConnected | - 서버와의 연결 여부를 확인한다. [Returns] - True : 서버에 연결되어 있는 상태 - False : 서버에 연결되어 있지 않은 상태 |
Login(szID, szPwd, szcertPwd, nServerType, bShowCertErrDlg) | - 서버에 로그인한다. [Parameters] - szID : 사용자 ID - szPwd : 계정 비밀번호 - szcertPwd : 공인인증서 비밀번호 - nServerType : 사용 안 함 - bShowCertErrDlg : 인증 과정 중 에러 표시 여부 |
Logout | - 로그인한 서버에서 로그아웃한다. |
GetAccountListCount | - 보유중인 계좌의 개수를 구한다. |
GetAccountList | - 보유중인 계좌리스트를 구한다. |
GetAccountName | - 계좌 이름을 구한다. |
GetAcctDetailName | - 계좌 상세명을 구한다. |
GetAcctNicname | - 계좌 별명을 구한다. |
GetLastError | - 마지막에 발생한 에러 코드 값을 구한다. - ErrorCode를 리턴한다. |
GetErrorMessage | - 에러 코드 값에 대한 에러 메시지를 구한다. |
IsLoadAPI | - API DLL이 Load되었는지의 여부를 구한다. |
GetServerName | - 접속한 서버의 이름을 구한다. |
Example. Usage of \(\texttt{ConnectServer()}\) Method
>>> import win32com.client
>>> client = win32com.client.Dispatch("XA_Session.XASession") # COM 타입의 XASession 객체를 불러온다.
>>> client.ConnectServer("demo.ebestsec.co.kr", 20001) # 이베트스 모의투자 서버 주소, 포트번호
True
XASession Events | Description |
OnLogin(code, msg) | - 서버에 로그인됐을 때 발생한다. [Parameters] - code : 서버에서 받은 메시지 코드 - msg : 서버에서 받은 메시지 |
OnDisconnect() | - 서버와의 연결이 끊어졌을 때 발생한다. |
- Event들이 발생되었을 때 대처 방법들은 구현이 필요하다.
- Event들은 라이브러리에서 특정 이벤트가 발생하는 시점에 호출되는 Callback-Method 개념으로 정의되어 있다.
Example. Implementation of XASession Events
class XASession:
#로그인 상태를 확인하기 위한 클래스변수
login_state = 0
def OnLogin(self, code, msg):
"""
로그인 시도 후 호출되는 이벤트.
code가 0000이면 로그인 성공
"""
if code == "0000":
print(code, msg)
XASession.login_state = 1
else:
print(code, msg)
def OnDisconnect(self):
"""
서버와 연결이 끊어지면 발생하는 이벤트
"""
print("Session disconntected")
XASession.login_state = 0
* \(\texttt{configparser}\) Library (URL)
XAQuery Object (XAQuery 객체)
- TR 조회에 관련된 기능들을 제공하는 COM 객체이다.
XAQuery Property | Description |
ResFileName | - Res 파일을 의미한다. |
IsNext | - 연속조회 여부를 의미한다. - 연속조회가 있는지를 확인할 때 사용한다. |
XAQuery Methods | Description |
Request(bNext) | - 조회 TR을 요청한다. - bNext : False이면 이번 TR을 조회하고, True이면 다음 TR을 조회한다. [Returns] - 0 이상의 값 : 조회 성공 - 0 미만의 값 : 에러코드 (조회 실패) |
GetFieldData(szBlockName, szFieldName, nOccursIndex) | - 블록의 필드 데이터(값)를 얻는다. [Parameters] - szBlockName : TR의 블록명 - szFieldName : 블록의 필드명 - nOccursIndex : 블록의 Occurs Index [Returns] - 블록의 필드 데이터 값 |
SetFieldData(szBlockName, szFieldName, nOccursIndex, szData) | - 블록의 필드 데이터(값)를 설정한다. [Parameters] - szBlockName : TR의 블록명 - szFieldName : 블록의 필드명 - nOccursIndex : 블록의 Occurs Index - szData : 데이터 값 [Returns] - 없음 |
GetBlockCount(szBlockName) | - 블록이 Occurs인 경우, Occurs의 개수를 구한다. [Parameters] - szBlockName : TR의 블록명 [Returns] - Occurs의 개수 |
SetBlockCount | - 블록의 개수를 설정한다. - InBlock의 경우에만 사용 가능하다. |
LoadFromResFile(szFileName) | - Res 파일을 지정한다. [Parameters] - szFileName : RES 파일의 경로 [Returns] - True : Res 파일 정보를 읽는데 성공 - False : Res 파일 정보를 읽는데 실패 |
ClearBlockData(szBlockName) | - 지정한 Block의 내용을 삭제한다. [Parameters] - szBlockName : TR의 블록명 [Returns] - 없음 |
GetBlockData(szBlockName) | - 블록 전체의 데이터를 구한다. [Parameters] - szBlockName : TR의 블록명 [Returns] - 블록의 전체 데이터 값 |
GetTRCountPerSec | - TR의 초당 전송 가능 횟수를 구한다. |
RequestService | - 부가 서비스 TR을 요청한다. |
RemoveService | - 부가 서비스 TR을 해제한다. |
RequestLinkToHTS | - HTS와 연동한다. |
Decompress | - t8411처럼 압축데이터 수신이 가능한 TR에 압축해제용으로 사용한다. |
GetFieldChartRealData | - 차트 지표 실시간 데이터를 수신했을 때, 필드 데이터(값)를 구한다. - 차트 지표데이터 조회 시, 실시간 자동 등록을 1로 했을 경우에 해당된다. |
GetAttribute | - Attribute 속성이 있는 TR의 속성값을 확인한다. |
GetTRCountBaseSec | - TR의 Base시간을 구한다. - 초 단위이다. |
GetTRCountRequest | - TR의 10분내 요청한 총 횟수를 구한다. |
GetTRCountLimit | - TR의 10분당 제한 건수를 구한다. |
XAQuery Events | Description |
ReceiveData(tr_code) | - 서버로부터 데이터를 수신했을 때 발생한다. [Parameters] - tr_code : TR 이름 |
ReceiveMessage(is_system_error, Message_code, Message) | - 서버로부터 메시지를 수신했을 때 발생한다. [Parameters] - is_system_error : 시스템 오류이면 True, 그 외 오류이면 False - message_code : 메시지 코드 - message : 메시지 |
ReceiveChartRealData | - 차트 지표 실시간 데이터를 수신했을 때 발생한다. - 차트 지표데이터 조회 시, 실시간 자동 등록을 1로 했을 경우에 해당된다. |
ReceiveSearchRealData | - 종목검색 실시간 데이터를 수신했을 때 발생한다. - 종목검색 조회 시, 실시간 등록을 1로 했을 경우에 해당된다. |
XAReal Object (XAReal 객체)
- 실시간 TR을 처리하는 기능들을 제공하는 COM 객체이다.
XAReal Property | Description |
ResFileName | - Res 파일을 의미한다. |
XAReal Methods | Description |
AdviseRealData | - 실시간 TR을 등록한다. |
UnadviseRealData | - 실시간 TR을 해제한다. |
UnadviseRealDataWithKey | - 한 종목의 실시간 TR을 해제한다. |
AdviseLinkFromHTS | - HTS에서 API로 연동한다. |
UnAdviseLinkFromHTS | - HTS에서 API로의 연동을 해제한다. |
GetFieldData | - 블록의 필드 정보를 구한다. |
SetFieldData | - 블록의 필드 정보를 설정한다. |
LoadFromResFile | - Res 파일을 지정한다. |
GetBlockData | - 블록 전체의 데이터를 구한다. |
XAReal Events | Description |
ReceiveRealData | - 서버로부터 데이터를 수신했을 때 발생한다. |
ReceiveLinkData | - HTS로부터 연동 정보를 수신했을 때 발생한다. |
DevCenter
- API의 테스트를 위해 이베스트에서 제공하는 프로그램이다.
- 각 API에 대한 상세 정보를 확인하고, API를 테스트할 수 있는 환경을 제공한다.
- DevCenter를 처음 설치한 경우 Res 파일 전체를 다운받아야 하는데,
Res파일이 Transaction(TR)을 요청하는데 필요하기 때문이다.
- TR은 크게 InBlock과 OutBlock으로 구분된다.
InBlock
- TR을 실행하는 데 필요한 값을 의미하고 사용자가 직접 입력해주어야 한다.
예를 들어, t8436(주식종목조회 API용)에서는 gubun이라는 파라미터가 필요하며
0(전체), 1(코스피), 2(코스닥) 중에 하나로 입력할 수 있다.
OutBlock
- TR을 실행한 다음 얻을 수 있는 필드에 대한 정보를 나타낸다.
- OutBlock에 Postfix로 OCCURS가 붙어있다면, 이는 데이터가 반복적으로 나오는 구조임을 의미한다.
(Data Type이 Array임을 의미한다.)
_execute_query() Method
def _execute_query(self, res, in_block_name, out_block_name, *out_fields, **set_fields):
"""
TR코드를 실행한다.
이 때, 10분에 200회를 초과하는 TR을 수행시키지 않도록
TR을 수행할 때 마다 리스트에 TR 수행 시각을 저장하고
저장된 수행 시각과 현재 시각을 비교해 10분이 넘은 값은
리스트에서 제거하는 방식으로 수행 시간을 조정한다.
이 리스트의 길이는 200을 초과하지 않는다.
[Parameters]
res : TR 리소스 이름 (str)
in_block_name : 인블록 이름 (str)
out_block_name : 아웃 블록 이름 (str)
*out_fields : 출력필드 리스트 (list)
**set_fields : 인블록에 설정할 필드 딕셔너리 (dict)
[Returns]
result : 결과 (list)
"""
time.sleep(1)
print("current query cnt:", len(self.query_cnt))
print(res, in_block_name, out_block_name)
while len(self.query_cnt) >= EBest.QUERY_LIMIT_10MIN: # 현재 수행된 퀴리의 개수가 200개 이상인 경우
time.sleep(1) # 프로세스를 1초간 정지
print("waiting for execute query... current query cnt:", len(self.query_cnt))
self.query_cnt = list( filter( lambda x: (datetime.today() - x).total_seconds() < EBest.LIMIT_SECONDS, self.query_cnt ) ) # 호출된지 10분 미만인 TR만 추출
xa_query = win32com.client.DispatchWithEvents("XA_DataSet.XAQuery", XAQuery) # XAQuery 객체 생성
xa_query.LoadFromResFile(XAQuery.RES_PATH + res+".res") # 리소스 파일 로드
#in_block_name 셋팅
for key, value in set_fields.items():
xa_query.SetFieldData(in_block_name, key, 0, value)
errorCode = xa_query.Request(0) # TR 요청
#요청 후 대기
waiting_cnt = 0
while xa_query.tr_run_state == 0: # OnReceiveData 이벤트가 발생되면 tr_run_state는 1로 설정됨 (즉, 0인 경우는 아직 TR 결과가 나오지 않았음을 의미함)
waiting_cnt +=1
if waiting_cnt % 1000000 == 0 :
print("Waiting....", self.xa_session_client.GetLastError())
pythoncom.PumpWaitingMessages()
result = [] # 결과 블럭을 담을 리스트
count = xa_query.GetBlockCount(out_block_name) # 결과의 개수 계산
# TR 요청 결과를 result에 저장
for i in range(count):
item = {}
for field in out_fields: # out_fields Argument에서 정의된 필드값만 추출
value = xa_query.GetFieldData(out_block_name, field, i)
item[field] = value
result.append(item)
"""
print("IsNext?", xa_query.IsNext)
while xa_query.IsNext == True:
time.sleep(1)
errorCode = xa_query.Request(1)
print("errorCode", errorCode)
if errorCode < 0:
break
count = xa_query.GetBlockCount(out_block_name)
print("count", count)
if count == 0:
break
for i in range(count):
item = {}
for field in out_fields:
value = xa_query.GetFieldData(out_block_name, field, i)
item[field] = value
print(item)
result.append(item)
"""
XAQuery.tr_run_state = 0 # TR 요청 및 결과반환까지 종료
self.query_cnt.append(datetime.today()) # TR 처리시간 저장
#영문필드를 한글필드명으로 변환
for item in result:
for field in list(item.keys()):
if getattr(Field, res, None): # Field 객체에 res 필드를 추출
res_field = getattr(Field, res, None)
if out_block_name in res_field:
field_hname = res_field[out_block_name]
if field in field_hname:
item[field_hname[field]] = item[field] # 한글 필드에 영문 필드의 값 복사
item.pop(field) # 영문 필드명 삭제
return result
Usage for Transactions
* \(\texttt{gubun}\) Field (시장구분)
"0" (ALL, 모든 종목)
"1" (KOSPI, 코스피 종목)
"2" (KOSDAQ, 코스닥 종목)
res (리소스) |
in_block_name (인 블록명) |
out_block_name (아웃 블록명) |
out_fields (출력 필드) |
set_fields (인블록 필드) |
"t8436" (주식 종목 조회) |
"t8436InBlock" | "t8436OutBlock" | ["hname", "shcode", "expcode", "stfgubun", "memedan", "gubun", "spac_gubun"] |
{"gubun":"시장구분"} |
"t1305" (주식 기간별 주가 조회) |
"t1305InBlock" | "t1305OutBlock1" | ["date", "open", "high", "low", "close", "sign", "change", "diff", "volume", "diff_vol", "chdegree", "sojinrate", "changerate", "fpvolume", "covolume", "value", "ppvolume", "o_sign", "o_change", "o_diff", "h_sign", "h_change", "h_diff", "l_sign", "l_change", "l_diff", "marketcap"] |
{"shcode":"종목코드", "dwmcode":"1", "date":"", "idx":"", "cnt":"기간"} |
"t1921" (신용거래 동향) |
"t1921InBlock" | "t1921OutBlock1" | ["mmdate", "close", "sign", "jchange", "diff", "nvolume", "svolume", "jvolume", "price", "change", "gyrate", "jkrate", "shcode"] |
{"gubun":"시장구분", "shcode":"종목코드", "date":"날짜8자리", "idx":"0"} |
"t1717" (외인·기관별 종목별 동향) |
"t1717InBlock" | "t1717OutBlock" | ["date", "close", "sign", "change", "diff", "volume", "tjj0000_vol", "tjj0001_vol", "tjj0002_vol", "tjj0003_vol", "tjj0004_vol", "tjj0005_vol", "tjj0006_vol", "tjj0007_vol", "tjj0008_vol", "tjj0009_vol", "tjj0010_vol", "tjj0011_vol", "tjj0018_vol", "tjj0016_vol", "tjj0017_vol", "tjj0001_dan", "tjj0002_dan", "tjj0003_dan", "tjj0004_dan", "tjj0005_dan", "tjj0006_dan", "tjj0007_dan", "tjj0008_dan", "tjj0009_dan", "tjj0010_dan", "tjj0011_dan", "tjj0018_dan", "tjj0016_dan", "tjj0017_dan" ] |
{"gubun":"시장구분", "fromdt":"조회시작날짜", "todt":"조회종료날짜", "shcode":"종목코드"} |
"t1927" (공매도 일별추이) |
"t1927InBlock" | "t1927OutBlock1" | ["date", "price", "sign", "change", "diff", "volume", "value", "gm_vo", "gm_va", "gm_per", "gm_avg", "gm_vo_sum"] |
{"date":"날짜", "sdate":"조회시작날짜", "edate":"조회종료날짜", "shcode":"종목코드"} |
Reference: 파이썬과 리액트를 활용한 주식 자동 거래 시스템 구축
(박재현 저, 위키북스, 2020)
Reference: 이베스트투자증권 (URL)
Reference: 이베스트투자증권 xingAPI Official Guide Document (URL)