Xing API 모의투자 - Xing API mouituja

퀀트투자를 위한 xing API 파이썬 레시피 01. 개발환경 준비하기 01) 아나콘다 설치하기 02) PyCharm 설치하기 02. xingAPI 사용 준비하기 01) 비대면 계좌개설 02) API 사용등록 및 설치 03. xingAPI 기초 01) 로그인 02) 계좌 가져오기 03) DevCenter 사용하기 04) 단일 데이터 조회 04. COM과 스레드 01) COM 기초 02) threading 모듈 03) COM과 스레드 04) COM 아파트먼트 모델 05) queue 사용하기 05. pyxing 01) pyxing 설치하기 02) pyxing으로 로그인 03) pyxing으로 TR 요청하기 04) pyxing으로 Real 요청하기 06. 주문 01) 계좌 이체 및 모의투자 신청하기 09. DDE 01) DDE 사용해보기 10. TR 목록 01) 주식 t8430 주식종목조회 20. 부록 1) 클래스 문법

Archive

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)

구성 요소 개체 모델 - Win32 apps

구성 요소 개체 모델

docs.microsoft.com

Xing API 모의투자 - Xing API mouituja

- 컴포넌트 오브젝트 모델로 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)을 요청하는데 필요하기 때문이다.

Xing API 모의투자 - Xing API mouituja

- 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)