[일상] 이베스트 증권 API를 이용한 자동매매(5)

오늘도 주식 시장이 많이 빠졌죠. 이렇게 변동성이 큰 장에 몸을 실어야할텐데요. 그래서 주말동안 자동매매 관련 개발을 마무리하느라 시간을 많이 투자했습니다. 이제 거의 된 것 같은데, 장 중에 명령어 하나하나 확인을 해야해서 좀 더 시간이 걸릴 것 같습니다.

API를 이용해서 개발을 하다 보면 항상 문제가 되는 것이 명확한 문서가 없다는 것입니다. 이때 다른 사람이 먼저 개발해 놓은 것이 있으면 많은 도움이 되죠. 특히나 블로그가 있으면 엄청나게 많은 시간을 절약할 수 있습니다.

개발하는 과정에서 많은 도움을 받은 블로그 혹은 github입니다.

https://wikidocs.net/74972
https://github.com/safenumero/Xing-API
https://wikidocs.net/4130

저도 개발 마무리되면 개발하면서 배운 것들을 자세하게 정리해볼 예정입니다.


우선 해야할 일들을 정리해보겠습니다.

  1. 잔고받기
  2. 주문하기
  3. 미체결 혹은 체결 종목 받기
  4. 매매하기

이 중 1, 3번(체결종목)은 동작하는 것까지 확인하였습니다. 2번 주문하기는 장 중에만 가능해서 내일 점심시간에 확인해볼 예정입니다. 4번은 암호화폐를 대상으로 개발한 것을 사용할 예정이기 때문에 큰 문제는 없을 것 같습니다.


우선 잔고 받기에 대하여 설명합니다.

함수 명은 아래와 같이 정의했습니다. 잔고받기에 해당하는 tr 번호인 t0424를 입력으로 넣어주면 됩니다.
아래 코드에서 보듯이 변수명 하나 하나 코딩을 해야하기에 시간이 많이 걸렸습니다. 중간에 실수라도 하면 시간이 더 걸리고요. 집중해서 한 땀 한 땀 입력을 정확하게 해야 하더군요.

def get_stock_balance(tr_code) :
    INBLOCK = "%sInBlock" % tr_code
    INBLOCK1 = "%sInBlock1" % tr_code
    OUTBLOCK = "%sOutBlock" % tr_code
    OUTBLOCK1 = "%sOutBlock1" % tr_code
    OUTBLOCK2 = "%sOutBlock2" % tr_code
    OUTBLOCK3 = "%sOutBlock3" % tr_code

    query = win32com.client.DispatchWithEvents("XA_DataSet.XAQuery", XAQueryEventHandler)
    query.ResFileName = "C:\\eBEST\\xingAPI\\Res\\"+tr_code+".res"

    query.SetFieldData(INBLOCK, "accno", 0, account_number)#계좌번호)
    query.SetFieldData(INBLOCK, "passwd", 0, account_pwd) #비밀번호)
    query.SetFieldData(INBLOCK, "prcgb", 0, '1')#단가구분)
    query.SetFieldData(INBLOCK, "chegb", 0, '0')#체결구분)
    query.SetFieldData(INBLOCK, "dangb", 0, '0')#단일가구분)
    query.SetFieldData(INBLOCK, "charge", 0, '1')#제비용포함여부)
    query.SetFieldData(INBLOCK, "cts_expcode", 0, '')#CTS_종목번호)
    query.Request(0)

이전 코드에서는 tr 번호마다 이벤트를 받기 위한 클래스를 만들었었는데요. 너무 불편해서 그냥 wait_for_event 함수로 처리할 수 있도록 변경했습니다.

def wait_for_event(code) :
    while XAQueryEventHandler.query_state == 0:
        pythoncom.PumpWaitingMessages()
    if XAQueryEventHandler.query_code != code :
        print('diff code : wish(',code,')', XAQueryEventHandler.query_code)
        return 0
    XAQueryEventHandler.query_state = 0
    XAQueryEventHandler.query_code = ''
    return 1

따라서 앞으로는 아래 방식의 코드만 추가하면 tr 코드에 상관없이 동작합니다.

    ret = wait_for_event(tr_code)
    if ret == 0 :
        return

결과에 대해서도 명령어를 줄 때와 비슷하게 한 땀 한 땀 정확하게 입력을 해야합니다. 엄청나게 많은 결과 데이터가 오는데 이중 필요한 것만 뽑아서 list를 만들고 다시 panda 형태로 바꾸어서 돌려줍니다.


    result = []
    nCount = query.GetBlockCount(OUTBLOCK)
    for i in range(nCount):
        cur_asset = int(query.GetFieldData(OUTBLOCK, "sunamt", i).strip()) #추정순자산
        profit = int(query.GetFieldData(OUTBLOCK, "dtsunik", i).strip()) #실현손익
        org_inv = int(query.GetFieldData(OUTBLOCK, "mamt", i).strip()) #매입금액
        est_amount = int(query.GetFieldData(OUTBLOCK, "tappamt", i).strip()) #평가금액
        est_profit = int(query.GetFieldData(OUTBLOCK, "tdtsunik", i).strip()) #평가손익

        lst = [cur_asset, profit, org_inv, est_amount, est_profit]
        result.append(lst)

    columns=['추정순자산','실현손익','매입금액','평가금액','평가손익']
    df1 = DataFrame(data=result, columns=columns)

    result = []
    nCount = query.GetBlockCount(OUTBLOCK1)
    for i in range(nCount):
        stock_code = query.GetFieldData(OUTBLOCK1, "expcode", i).strip()
        a3 = query.GetFieldData(OUTBLOCK1, "jangb", i).strip() #잔고구분
        balance = int(query.GetFieldData(OUTBLOCK1, "janqty", i).strip()) #잔고수량
        sellable_balance = int(query.GetFieldData(OUTBLOCK1, "mdposqt", i).strip()) #매도가능수량
        avg_price = int(query.GetFieldData(OUTBLOCK1, "pamt", i).strip())#평균단가
        buy_amount = int(query.GetFieldData(OUTBLOCK1, "mamt", i).strip()) #매입금액
        buying_today = int(query.GetFieldData(OUTBLOCK1, "msat", i).strip()) #당일매수금액
        bt_avg_price = int(query.GetFieldData(OUTBLOCK1, "mpms", i).strip()) #당일매수단가
        selling_today = int(query.GetFieldData(OUTBLOCK1, "mdat", i).strip()) #당일매도금액
        st_avg_price = int(query.GetFieldData(OUTBLOCK1, "mpmd", i).strip()) #당일매도단가
        stock_name = query.GetFieldData(OUTBLOCK1, "hname", i).strip() #종목명
        cur_price = int(query.GetFieldData(OUTBLOCK1, "price", i).strip()) #현재가

        lst = [stock_code,stock_name,balance]
        result.append(lst)

    columns=['종목번호','이름','잔고수량']
    df2 = DataFrame(data=result, columns=columns)
    return (df1, df2)

잔고가 필요할 때 아래와 같이 호출하면 그 결과가 panda 구조로 받을 수 있습니다.

~
#잔고받기
df1, df2 = get_stock_balance('t0424')
print(df2)

~

실행결과입니다.

소량의 종목들이 많이 있는데, 그 이유는 AI기법을 이용해서 자동 매매하는 프로그램을 돌리고 있기 때문입니다. 얼마나 수익이 날지 지켜보고 있습니다.

비슷한 방식으로 체결결과도 확인이 가능합니다.

이베트스 API의 문서가 부실해서 하나 하나 해 보면서 작업을 진행하고 있어서 속도가 느립니다. 그래도 이만큼 온 것을 보면 조만간 마무리할 수 있을 것 같습니다.

이제 좋은 전략만 있으면 되는데 말이죠.


Sort:  

JCAR 4월 구독보팅입니다.

수익이 많이 나야할텐데...

Coin Marketplace

STEEM 0.04
TRX 0.32
JST 0.081
BTC 61383.18
ETH 1642.90
USDT 1.00
SBD 0.41