지난 1편에 소개 글에 이어 실시간 TR을 추가하는 방법에 대하여 기술합니다.

 

어떻게 하면 초보자가 쉽게 코딩할 수 있을지 고민을 해 보았는데요.

초보자의 경우에는 가급적 어려운 부분이 가려져 있는 것이 좋을 듯합니다. websocket, send, recv 등등 

 

내가 필요한 실시간 TR Code 값과 메세지를 받는 부분, 그리고 관심있는 ticker 정도만 전달할 수 있다면 보다 쉽게 개발을 할 수 있을 것 같습니다.

 

단언컨데 더 이상 쉬울 수 없는 방법을 소개하고자합니다.

 

------------------------

본 셈플은 크게 두개의 .py로 이루어져 있습니다.

 

open_api_real_lib.py   # 실시간 real tr을 요청하는 부분. 일반 개발자는 신경안써도 되는 부분

my_open_api_real.py  # 개발하고자하는 real tr에 대한 코드, 일반 개발자가 짤 코드

 

open_api_real_lib.py 에 있는 내용은 관심있으신 분들만 코드를 보세요.

 

이 글에서는 my_open_api_real.py를 만드는 방법에 대해서만 기술합니다.

 

이전 글에 있던 sample 코드는 아래와 같은 방식으로 개발이 가능합니다. 이전 셈플에 비하여 관련없는 부분은 모두 삭제가 되어서 코드가 간단하고 보기도 좋습니다.

 

from open_api_real_lib import main_loop 

# 메세지 처리하는 함수
def on_future_sise(data):
    price    = float(data['price'])
    vol      = int(data['cvolume'])
    offerho1 = float(data['offerho1'])
    bidho1   = float(data['bidho1'])

    print(format(price, '5.2f'), format(vol, '4d'), '    ', format(offerho1, '5.2f'), '  ', format(bidho1, '5.2f'))
    
if __name__ == '__main__':
    # 실시간 TR 메세지 정의
    FUTURE_SISE       = 'FC0'
    
    # 관심있는 ticker 정보
    ticker = '101V3000'     # 2024년 3월 만기 선물

    main_loop(FUTURE_SISE, on_future_sise, ticker)

 

 

기본적인 구조는 실시간 TR을 정의하고 해당하는 TR에서 오는 메세지를 처리하는 함수를 만들면 됩니다. 

 

여기에 선물 호가창을 추가하는 방법에 대하여 정리합니다.

 

GUI가 아닌 command 창에 실시간 정보를 출력하기 때문에 창 하나에 한 TR을 출력하는 방식을 적용해야합니다. 실행할 때 마다 소스를 변경해서 실시간 호가창/실시간 체결 정보를 보는 것은 비효율적이니 간단하게 메뉴 방식으로 실행시 선택하는 방식을 사용해보겠습니다.

 

우선 선물 호가창 정보가 왔을 때 어떻게 출력할 것인지를 코딩합니다. 본 예제에서는 호가창 아래 위 2개만 출력합니다. 최대 5개까지 출력할 수 있으니 관심있으시분 들은 수정하여 사용하세요.

참고로 선물 호가창 TR을 통해서 받는 정보의 형태는 api 문서를 참고하세요.

def on_future_order_book(data):
    print(data['hotime'])
    print('--------------------------------')
    print(' 건수  수량   가격   수량  건수')
    print('--------------------------------')
    print(format(int(data['offercnt2']), '4,d'),
          format(int(data['offerrem2']), '4,d'), ' ',
          format(data['offerho2']))
    print(format(int(data['offercnt1']), '4,d'),
          format(int(data['offerrem1']), '4,d'), ' ',
          format(data['offerho1']))
    print(format(' ',  '11s'), 
          format(data['bidho1']), 
          format(int(data['bidcnt1']), '5,d'),
          format(int(data['bidrem1']), '5,d'))
    print(format(' ', '11s'), 
          format(data['bidho2']), 
          format(int(data['bidcnt2']), '5,d'),
          format(int(data['bidrem2']), '5,d'))

 

다음으로 추가하고 하는 실시간 TR 코드를 작성합니다.

if __name__ == '__main__':
    # TR codes
    FUTURE_SISE       = 'FC0'
    FUTURE_ORDER_BOOK = 'FH0'  # <- 새로 추가

 

간단한 선택 메뉴를 만듭니다.

    print('선택')
    
    # 새로운 REAL TR 추가시 print문에도 추가
    print('1: 선물시세  2:선물호가창')
    sel = input()

 

입력 값에 따라 실행할 TR code와 메세지를 받을 함수명을 정의합니다.

    if sel == '1' :
        tr_code = FUTURE_SISE
        func    = on_future_sise

    elif sel == '2' :  # <-  추가
        tr_code = FUTURE_ORDER_BOOK  
        func    = on_future_order_book

 

입력받은 Real tr code값, 불려질 함수명, ticker 정보를 open api를 담당하는 곳으로 전달합니다.

    main_loop(tr_code, func, ticker)

 

실행방법입니다.

 

1번 선물 시세를 선택하면 잠시 후 선택한 real tr 값을 처리한 결과가 화면에 출력됩니다.

 

 

동시에 여러 개의 실시간 TR 정보를 보고 싶으면 command 창을 여러 개 띄워서 메뉴 창에서 원하는 번호를 선택하면 됩니다.

 

------------------------------

본 lib를 사용하면 websocket에 대한 내용은 모두 몰라도 되기 때문에 보다 쉽게 open api를 이용할 수 있을 것으로 예상됩니다.

 

다음에는 화면을 좀 더 잘 볼 수 있게 하는 방법과 실시간 시세 정보를 가공해서 보여주는 방법에 대하여 기술하도록 하겠습니다.  

이런식으로 말이죠.  상승/하락시 색 변경, 체결 수량 10개 이상만 출력

 

 

 

-----------

소스코드는 아래 위치에 있습니다.  두 파일을 모두 다운받으세요.

https://github.com/multizone-quant/api_ex/blob/main/my_open_api_real.py

https://github.com/multizone-quant/api_ex/blob/main/open_api_real_lib.py

반응형

설정

트랙백

댓글

선물 실시간 데이터를 받을 일이 생겼습니다. 기존 xing api로 작업을 해서 돌리고 있는데, Open API에 실시간 TR이 있다는 말을 듣고 확인해보았습니다.

 

websocket을 이용하는 방식이라 개발하기 상당히 쉽게 되어 있습니다. 반면에 xing api는 callback 설정하고 등등 절차가 상당히 복잡합니다. 향후 기능 추가를 생각해서 이번 기회에 Open Api로 바꾸기로 했습니다.

 

ebest open api 사이트에 가면 실시간 TR 사용법에 대하여 기술되어 있는 글이 있습니다.

https://openapi.ebestsec.co.kr/howto-sample 

 

전체적인 흐름을 잘 정리해놓았으나 결정적으로 함수를 부르는 main 부분이 없습니다. 

 

그래서 동작하는 전체 소스를 공유하고자 합니다. Open API를 이용하여 실시간 데이터를 받고자 하는 경우에 유용하게 사용될 것입니다.

 

import requests
import json
import time
import asyncio
import websockets

APP_KEY = "본인의 key"
SECRET_KEY = "본인의 sec key"

 

우선 필요한 package import한 후 본인의 Open API 키를 넣습니다.  만약 관련 package가 없다고 나오면 아래와 같이 설치합니다.

 

pip install websockets

pip install asyncio

 

아래 코드는 그냥 묻지도 따지지도 말고 그냥 사용합니다.

# 이하 수정할 필요없는 부분
BASE_URL        = "https://openapi.ebestsec.co.kr:8080"
BASE_URL_WEBS   = "wss://openapi.ebestsec.co.kr:9443/websocket"

   
# 파생인의 쉼터 꿈에님 코드 인용
def get_token():
    PATH = "/oauth2/token"
    headers = {"content-type": "application/x-www-form-urlencoded"}
    body = {
        "appkey": APP_KEY,
        "appsecretkey": SECRET_KEY,
        "grant_type": "client_credentials",
        "scope": "oob"
    }
    result = requests.post(BASE_URL+PATH, headers=headers, data=body)

    body = result.json()

    return body["access_token"]


# 선물 실시간 시세용 message
def reg_future_real(cd, ticker):
    dt = {
        'header': {
            "token": get_token(),
            "tr_type": "3"  #3:실시간 등록
        },  
        'body' : {
            "tr_cd": cd,
            "tr_key": ticker,     
        }         
    }
    return json.dumps(dt) # json을 string으로 변환

지금 만들고자 하는 함수는 실시간 선물 시세입니다. 선물 실시간 체결이 되면 Open API를 통하여 아래 함수로 호출이 옵니다.

# 체결수량 출력
def on_future_sise(data):
    price    = float(data['price'])
    vol      = int(data['cvolume'])
    offerho1 = float(data['offerho1'])
    bidho1   = float(data['bidho1'])

    print(format(price, '5.2f'), format(vol, '4d'), format(offerho1, '5.2f'), format(bidho1, '5.2f'))

실제로 많은 정보들이 data에 들어옵니다. 자세한 정보는 KOSPI200 선물시세를 선택하면 나옵니다.

 

이제는 on_future_sise() 라는 함수가 호출되는 과정에 대하여 간단하게 정리합니다.

 

우선 코드부터 보죠.  KOSPI200 선물시세를 받을 수 있는 TR의 CODE는 'FC0'입니다. 

 

아래 real_api()라는 함수를 보면 async라는 문자가 앞에 있습니다. async with를 사용하는 경우도 있고, await와 함수명을 사용하는 경우도 있습니다. 비동기 함수를 사용하기 위한 절차라고 생각하시고 그냥 무시하셔도 됩니다. 앞으로 real_api 함수에서 connect/send/recv 부분은 손댈필요가 없기 때문입니다.

 

FUTURE_SISE       = 'FC0'

# 웹 소켓 관련 신경쓸 필요없음
import websockets
async def real_api(real_code, ticker):
    while True:
    # 웹 소켓에 접속을 합니다.
        async with websockets.connect(BASE_URL_WEBS) as websocket:
            str = reg_future_real(real_code, ticker)

            # 웹 소켓 서버로 데이터를 전송합니다.
            await websocket.send(str);
            print('wait')
            time.sleep(2)
            
            while True:
                # 웹 소켓 서버로 부터 메시지가 오면 콘솔에 출력합니다.
                data_s = await websocket.recv();
                data = json.loads(data_s)
                if data['body'] == None: # 시세가 바로 오지 않음 None이면 waiting
                    time.sleep(1)
                    continue
                if real_code == FUTURE_SISE:
                    on_future_sise(data['body'])

 

그래도 무슨 일을 하는지는 알아야겠지요?

reg_future_real() 함수는 실시간 TR을 등록하는 일을 합니다. 앞으로 이 함수에 등록하는 TR에서 주는 실시간 데이터를 받겠다는 의미입니다. 그 다음부터는 ebest server에서 전달하는 실시간 데이터를 받아서 사용할 함수로 전달하면 끝입니다.

 

이 중 특이한 부분은 websocket에서 받은 데이터를 json 형태로 변경시키는 아래 부분입니다. 실제로 recv한 data_s는 string 문자열입니다. 긴 문자열로 이루어진 데이터 중 원하는 값을 뽑아내기가 어렵기 때문에 json 형태로 변경해주는 절차가 필요합니다. 그게 바로 json.load입니다. 앞으로 data는 "key":value 형태로 접근이 가능합니다.

                data_s = await websocket.recv();
#                print(data_s)
                data = json.loads(data_s)

 

여기까지는 ebest sample에 나오는 내용과  비슷합니다.  결정적으로  ebest 문서에는 이렇게 많은 함수를 호출하는 부분이 빠져있는데요.

 

이렇게 만든 함수를 호출하는 방법은 다음과 같습니다.

if __name__ == '__main__':
    ticker = '101V3000'     # 2024년 3월 만기 선물
    cd = FUTURE_SISE
    asyncio.run(real_api(cd, ticker))

 

간단하죠.. 그냥 asyncio.run() 함수를 부르면 됩니다. 이때 인자로 위에서 만든 real_api(cd, ticker) 를 넣어줍니다. 즉 비동기적으로 real_api()를 실행하라의 의미입니다.

 

asyncio.run(real_api(cd, ticker))

 

결론적으로 websocket으로 연결하고 어쩌고 하는 부분은 모두 모르셔도 됩니다.

실제 선물이 체결되면 아래 함수로 data에 관련 정보가 저장된 상태로 아래 함수가 불리어진다는 것만 인지하면 됩니다.

def on_future_sise(data):

 

이 함수에서 여러 다양한 일들을 할 수 있습니다. 예를들어 10계약 이상 거래한 것만 출력하자 등등 (이건 다음 글에서 정리해보겠습니다.)

 

sample 소스코드는 아래 github에 있습니다.

https://github.com/multizone-quant/api_ex/blob/main/open_api_real_sample.py

 

 

------------

ebest open api 실시간 TR을 python으로 개발하는 방법을 간단하게 기술하였습니다.

다음에는 이러한 기본 코드를 바탕으로 빌드업을 해보겠습니다.

 

- 선물 거래량 n개 이상만 출력하기

- 선물 orderbook 실시간 정보 출력하기  

반응형

설정

트랙백

댓글

OpenAPI가 나오면서 API 접근성이 많이 개선이 된 것 같습니다.

하지만 처음 자동매매를 시작하시는 분들이 참고할만한 자료가 많지 않아서 진도가 잘 나가지 않을텐데요. 그래서 문서를 보고 직접 코드를 만드는 절차를 자세하게 기술하고자 합니다.

 

이베스트 증권 OpenAPI를 이용하기 위해서는 API key를 발급받아야합니다. 아래 내용 참고하세요.

 

API key를 받았다면 아래 API Guide로 이동합니다.

https://openapi.ebestsec.co.kr/apiservice


여기에 보시면 Open API가 지원하는 다양한 TR 정보들에 대한 자세한 정보가 나옵니다. 

 

"주식/시세/기간별주가" 어떻게 코딩을 하는지 알려드리겠습니다.

API Guide에 나오는 내용입니다.

 

기본정보에 나오는 값도 코드에 사용을 하여야하니 일단 참고만 합니다.

 

다음은 요청시에 필요한 header 정보입니다.

 

뭔가 좀 복잡한데요. t1305를 이용하기 위해서는 header에 이런 정보를 넣어야한다는 의미입니다.

 

큰 틀은 get_token() 함수를 이용하여 token을 받은 후 본인이 원하는 함수를 호출하는 형식입니다.

token = get_token()

ticker = '069500' # kodex 200
qrycnt = 2          # 몇 개를 받을지
dwmcode = 1         # 일봉:1,  주봉:2, 월봉:3

# infos : candle info
infos = get_stock_dwm_info(ticker, qrycnt, dwmcode)
for info in infos : 
    print(json.dumps(info, indent=4))

 

 

일반적으로 t1305를 한번만 부르지 않기 때문에 아래와 같이 함수를 만듭니다. 함수를 만들때에는 인자는 header와 body에 들어갈 정보를 보고 적절하게 만드시면 됩니다. 함수 작성하는 방법 default 값을 assign하는 방법 등은 파이썬 교재를 통하여 습득하시기 바랍니다.

 

-----------------------

t1305에 해당하는 get_stock_dwm_info()를 만드는 과정을 설명합니다.

 

header 부분입니다.

 

PATH는 기본정보의 URL 값을 입력하세요.

연속여부는 edate 값에 따라 결정합니다.

content-type과 authorization에 들어가는 부분은 꿈에님 코드를 활용하였습니다. 이 부분은 예제에 나오는 함수를 그냥 사용하시면 됩니다.

 

다음으로 각 항목은 tr 마다 모두 틀리기 각 tr에 대하여 guide 참고하여 적절한 값을 넣어야합니다. 만약 api가 작동하지 않는다면 header에 넣어주는 정보가 틀렸다는 의미이므로, guide를 다시 한번 자세하게 읽어서 정확한 값을 넣어주셔야 합니다. 특히 type 부분을 잘 보셔야 합니다. string인지 int인지 자리수는 몇자리인지 잘 확인하셔야 합니다.

 

def get_stock_dwm_info(ticker, qrycnt, dwmcode=1, edate = ' ', tr_cont_key=''):
    PATH = "/stock/market-data"
    # 연속여부 판단
    cont = 'N'
    if tr_cont_key != '' :
        cont = 'Y'
        
    headers = {
            "content-type": "application/json; charset=utf-8", "authorization": "Bearer "+token,
            "tr_cd": "t1305", 
            "tr_cont": cont, 
            "tr_cont_key": tr_cont_key
    }

 

 

다음은 body 부분입니다. header와 마찬가지로 정확한 값을 입력해야합니다. 

 

 

date 필드는 처음조회시와 연속조회시 다른 값이 들어갑니다. 일반적으로 한번에 받을 수 있는 자료의 크기가 정해져있으므로, 그 이상 받고 싶은 경우에는 연속조회를 해야합니다. 연속조회 방식은 이전 글 참고하세요.

 

body에 대응하는 실제 코드입니다. body와 1:1로 위치 맞춰서 적절한 값이 설정되도록 합니다.

    body = {
        "t1305InBlock": { 
            "shcode": ticker, 
            "dwmcode": dwmcode,   # 1@일, 2@주, 3@월
            "date": edate,   # 처음 조회시는 Space 연속 조회시에 이전 조회한 OutBlock의 date 값으로 설정
            "idx": 0,       # 무시
            "cnt": qrycnt   # 건수
            } 
        }

 

이제 query를 할 준비가 끝났습니다. query를 던집니다.

    result = requests.post(BASE_URL+PATH, headers=headers, data=json.dumps(body))
    
    header = result.headers
    body = result.json()

 

결과는 header와 body를 통하여 확인이 가능합니다.

 

header에는 tr 정보가 들어있습니다. 혹시라도 답이 제대로 나오지 않는다면 header 정보를 확인하시면 됩니다. 정상적인 경우에는 무시하셔도 됩니다.

 

body에는 query한 결과가 들어있습니다. 

 

body를 보시면 아래 두 key 값으로 결과 값이 저장되어 있습니다. 만약 연속조회를 한다면 "t1305OutBlock"에 있는 date 값을 이용하여 재 조회를 하시면 됩니다. 이렇게 글은 쉽게 썼지만 처음 접하시는 분들은 무슨 말이냐 하실텐데, 이전 선물 tick 받는 소스 참고하여 스스로 공부해보시기 바랍니다.

 

t1305OutBlock1에는 우리가 원하던 candle 정보가 들어있습니다.

 

query 결과는 json 형태로 돌려주는데 이 값을 출력할 때  아래 방식을 사용하면 보시기 편할겁니다.

        print(json.dumps(body, indent=4))

 

마지막으로 함수에서 돌려줄 때 OpenAPI로 받은 값을 그냥 돌려주면 사용하는 쪽에서 힘들어집니다. 앞으로 다양한 API를 이용할텐데 그때마다 t1305OutBlock1 이런 식으로 정해진 값을 key 사용하면 불편해집니다. 따라서 단순하게 dict list로 돌려주는 것이 사용하기 편해집니다. 아래와 같이요.

    return body["t1305OutBlock1"]

 

이제는 받은 값을 출력해봐야겠죠.

# infos : candle info
infos = get_stock_dwm_info(ticker, qrycnt, dwmcode)
for info in infos : 
    print(json.dumps(info, indent=4))

 

출력결과입니다.

 잘 나오는군요.

 

만약 query 하고자 하는 개수가 100개라면 이런식으로 출력하면 너무 양이 많습니다. 시간도 많이 걸리고요. 

이런 경우에는 1-2개만 잘 받는지 확인하고 그 다음부터는 print 문을 빼시면 됩니다.

 

query한 결과를 화면 출력하였다면 이번에는 파일에 저장하는 방법입니다.

 

저장하는 방법도 여러가지가 있겠지만 저는 csv 파일 형태로 저장하는 것을 선호합니다.

 

저장할 때와 읽을 때 사용하는 함수도 포함해놓았으니 필요할 때 사용하시기 바랍니다. 아래는 코드 사용 예입니다.

# 저장    
fname = ticker + '_day.csv'
save_to_file_csv(fname, infos)

# 읽기
data = read_csv_to_dict(fname)
print('읽은 값')
for info in data : 
    print(json.dumps(info, indent=4))

 

cvs 파일 형태로 저장이 되어 있으므로 excel을 이용하면 뭔가 하기 편합니다.

 

 

 

간단하게 Open API로 본인만의 파이썬 코드를 만드는 방법을 정리해보았습니다. OpenAPI는 많은 TR이 있으므로, 본인이 필요한 TR이 생기면 그때 그때 같은 방식으로 함수를 만들어서 사용하시면 됩니다.

 

개발하시다가 잘 안되는 경우가 생기면 댓글로 남겨주세요.

 

 

소스코드는 아래 github에 있습니다.  OpenAPI_Stock_Candle.py

https://github.com/multizone-quant/api_ex

 

GitHub - multizone-quant/api_ex

Contribute to multizone-quant/api_ex development by creating an account on GitHub.

github.com

 

반응형

설정

트랙백

댓글

기존 Xing Api에 비하여 Open Api가 사용하기 간편합니다. 우선 32bit cuda 설치할 필요가 없는 것이 엄청난 장점이고요. 그외 코드가 간단하기 때문에 앞으로는 Open API를 주로 사용할 듯 합니다.

 

이번에는 Open API를 이용하여 선물 tick 데이터를 받는 방법에 관하여 정리합니다. 

간단하게 생각하고 개발을 시작했는데, tick 데이터를 받는 API에 버그가 있어서 회피 코드 만들고 확인하느라 시간이 좀 많이 걸렸습니다. API 버그는 이전 글 참고하세요.

 

Xing API도 마찬가지지만 Open API도 10분 최대 qeury는 200회 횟수 제한이 있습니다. 문제는 tick 데이터는 200회 이상 받아야 하는 점인데요. 10분 기다렸다가 남은 부분 받으면 되지만 10분 기다리는 것이 아까운 것 같아서 약간의 편법을 동원했습니다. 다시 실행하는 경우에는 다시 10분에 200회 다운이 가능하다는 점을 활용하여 200회 query 후 종료한 후 다시 실행하는 방식을 사용합니다.

 

다시 실행할 때 이전에 받던 시간 다음부터 받아야하기 때문에 과거 정보가 필요합니다. 이것은 실행 중에  생성했다가 삭제하므로 신경쓰지 않으셔도 됩니다.

그래서 download 프로그램을 2번 연속으로 실행하여야 하므로 프로그램에서 알려주는 메세지에 따라서 진행하시면 됩니다. python이 없으시다면 python 부터 설치하세요.

 

OpenAPI를 이용하기 위해서는 key를 생성해야합니다. 아래 글은 꿈에님의 글에서 캡쳐해왔습니다.

 

KEY를 발급받으셨다고 가정하고 사용방법을 설명합니다.

 

우선 아래 깃허브에서 파일 두개를 다운 받은 후 다음의 절차대로 실행하시면 됩니다.

 

1. pip install websockets

 

2. tick-down.py 파일을 열어서 본인의 KEY 정보 추가

    APP_KEY = "본인의 key"
    SECRET_KEY = "본인의 sec key"

 

3. down하고자 하는 일자와 ticker(참고로 선물 ticker는 mts에서 선물을 클릭해보면 나옵니다.)

    date   = '20240125'
    ticker = '101V3000'

4. tick-download.py 실행

   python tick-download.py
   한번 더 실행하라는 메세지가 나오면 "위 화살표"를 눌러서 한번 더 실행


5. download 끝났으면 tick-download .py 실행
   python tick-download.py


6. down 받은 tick data는 future_tick 폴더에 있음

 

실행화면입니다.

tick-down.py 첫 번째 실행

 

두 번째 실행

 

tick-merge 실행

 

사용하기 최대한 간단하게 만들었으니, 사용 중 문제가 생기면 댓글 달아주세요. 바로 조치하도록 하겠습니다.

 

그리고 중간에 download받은 각각의 파일은 future_tick_seq 폴더에 기록이 되는데 계속 파일이 쌓입니다. 주기적으로 들어가셔서 지워주세요.

 

merge된 최종 tick 데이타는 future_tick 폴더에 차곡차곡 쌓입니다.

 

Ebest API 오류로 우여곡절을 겪었으나 코드가 완성이 되어서 기쁩니다. 그 과정에 많은 도움을 주신 꾸준님과 OpenAPI 샘플을 공유해주신 꿈에님께도 감사드립니다. 

 

소스코드가 있는 곳

https://github.com/multizone-quant/api_ex/tree/main

 

 

반응형

설정

트랙백

댓글

선물 tick 데이터를 연속으로 받는 중 발견한 오류입니다.

tick 데이터는 msec 해상도를 가지는데, msec까지 같은 경우가 가끔 있습니다. 그런데 연속 조회시 마지막 데이터와 다음 조회시에 받을 데이터가 같은 msec인 경우에 연속 조회시 받을 수 있는 두가지 오류가 발견되었습니다.

 

일단 원 데이터를 보겠습니다.

아래는 2024년 1월 29일 선물 tick 데이터입니다. 09:39:36초에 총 4번의 거래가 발생하였음을 알 수 있습니다.

 

첫 번째 오류는 최근에 받은 tick 자료에 msec이 같은 tick이 더 있는 경우에 발생하는 오류입니다. 

아래 자료 중 밑에 있는 것은 이전에 받은 tick 정보입니다. 09:39:36초에 2건의 거래가 있었음을 알려줍니다. querycnt 값이 차서 이 상태로 돌려줍니다. 이때 cts_time 정보는 0939363755가 돌아옵니다. API ref를 보면 돌려주는 cts_time 정보를 다음 연속 query할 때 입력으로 사용하라고 명시되어 있습니다.  다음 query의 결과값은 0939363755 보다 큰 값을 가진 tick 정보를 돌려주는 방식입니다. 이 가정에서 오류가 발생하는데요.

 

앞에서 설명하였듯이 09:39:36초에는 총 4건의 거래가 있습니다. 다음 query에서는 이 전에 몇 건을 보냈는 정보를 관리하지 않아서 무조건 cts_time보다 큰 값을 가진 tick을 돌려줍니다. 따라서 미처 받지 못한 2건은 사라지게 됩니다.

 

ebest api를 수정할 방법은 없으니 회피 방법을 찾아봅니다.

 

cts_time을 전달할 때 query에서 준 값이 아닌 tick 정보 중 최근 값보다 큰 값을 전달하면 될 듯합니다. 기본 가정은 최신 tick 시간에는 중복된 데이타가 있다고 가정을 하는 것이죠. 이렇게 해보니 msec이 중복된 tick 정보는 모두 받을 수 있는데  또 한가지 처리하여할 문제가 발생합니다. 바로 중복 저장 문제입니다.

 

수정한 방식으로 연속 query를 하면 아래와 같이 09:39:36초 데이터가 중복으로 받아집니다. api 입장에서는 0939363755 틱을 이전에 받았는지 알 수가 없는 것이죠. 그래서 중복된 모든 tick 정보를 다시 전달해줍니다. 

 

이 또한 어쩔 수 없는 것이므로, 중복된 tick을 제거하는 방식으로 처리하여야합니다.

 

방법은 간단한데요. 이전에 받은 자료 중 같은 시간에 해당하는 tick의 수를 계산해서 이번에 받은 자료에서 그 만큼 차감하여 저장하면 됩니다. 이렇게 하면 아래와 같이 중복된 자료가 사라짐을 알 수 있습니다.

 

결과적으로 msec이 같은 tick 정보를 모두 받을 수 있고, 중복된 tick 정보도 제거할 수 있었습니다.

 

이런 과정없이 tick을 저장하신 분들이 msec이 같은 경우에 이빨이 빠져있을 수 있으니 이점 참고하시기 바랍니다.

 

반응형

설정

트랙백

댓글

ebest api에서 t8413을 이용하여 특정 주식의 일봉 자료를 얻을 수 있습니다. 자료에 보면 jongchk와 rate라는 항목이 있는데 여기에 주가 변동 사항에 대하여 정리가 되어 있습니다.

 

이동 평균선을 구할 때 이 항목을 잘 확인을 해야하는데요. 이걸 무시하면 엉뚱한 결과가 나올 수 있습니다.

 

삼성전자 예를 들어보겠습니다. 아시다시피 삼성전자는 액면가 5,000원을 100으로 변경하는 액면분할을 하였습니다. 당시 일봉자료를 보면 아래와 같은 값이 표기되어 있습니다.

 jongchk : 4100

rate : -98

 

그 의미를 이해하려면 4100을 hex 값으로 변환하여야 합니다. 4100의 hex값은 1004가 됩니다. 위에 그림에서 보면 0x1000은 기준가 조정이고 마지막 4는 액면분할을 의미합니다. 

 

 

그리고 rate값인 -98은 액면가가 98% 줄어들었다는 의미입니다.

주가 보정을 위해서는 아래와 같은 방식으로 하면 됩니다.

삼성전자 2018/05/03 주가 2,650,000  

수정주가 => 2,650,000 * (100+rate)/100  = 53,000

 

반대로 액면병합인 경우에는 rate 값이 양수로 표기됩니다.

 

액면병합, 연말 배당, 유상증자 등으로 권리변동이 계속 발생하므로 변경이 생긴 원인을 파악하고 이에 맞는 적절한 가격 계산을 해 주어야 합니다.

 

반응형

설정

트랙백

댓글

 

월요일 만기 weekly option이 상장되었습니다.

자동매매를 하시는 분들은 새로운 변화에 대응을 해야하는데요.

다행히 기존 목요일 만기 weekly option은 문제없이 작동을 했습니다.

 

다만 월요일 만기 weekly option도 매매 대상으로 넣기 위해서는 추가 작업을 해 주셔야 합니다.

 

우선 코드입니다.

아래 그림과 같이 기존 목요일 만기 weekly 코드는 변화가 없습니다. 월요일 만기 weekly 옵션 용 코드가 신규로 생성되었습니다. 월요일 만기 weekly 옵션 코드는 AF 이고 이번 주가 01로 시작해서 쭉 올라갈 듯 합니다. 다다음 주 코드가 나오면 확실한 규칙을 알 수 있을 것 같습니다.

 

 

 

다음은 검색방법입니다.

옵션 전광판 t2301을 보면 위클리의 경우에는 yyyymm 필드에 W1MON 혹은 W1THU를 입력하도록 변경되었습니다. 기존에는 아래 그림과 같이 W1을 입력했습니다. 즉 뒤에 행사요일 정보가 추가된 형태입니다. 기존과 같이 W1을 입력하여도 목요일 만기 옵션 정보가 출력되기는 합니다.

 

아래는 월요일 만기 wekly 옵션 현재 가격을 얻는 방법임.

 

결론적으로 기존 목요일 만기 weekly 옵션 코드는 변경없이 동작합니다. 월요일 만기 weekly 옵션을 추가하면 W1으로 query를 하던 부분을 월/목에 따라 뒤에 MON/THU를 추가하면 됩니다.

 
 

 

반응형

설정

트랙백

댓글

 

weekly 옵션은 기존 옵션 정보를 얻는 TR을 함께 사용합니다. tr2301을 이용하여 weekly 옵션 코드를 구해서 특정 option에 대한 정보만 요청할 수도 있습니다.

 

weekly 옵션과 관련된 TR입니다.

1) tr2301 : 옵션 전광판, 해당 물 전체 옵션의 가격 정보를 받을 수 있다.

사진 삭제

사진 설명을 입력하세요.

미니 정규의 경우에는 만기 년월을 표시하면 되지만 weekly의 경우에는 W1 - W5로 표시합니다. 예를들어 1주차는 "W1 " 인데 주의할 사항은 W1 뒤에 공백(space)를 4개 더 넣어야합니다. 이는 기존 정규/미니 선물/옵션 월물 형태인 yyyymm 6자리를 맞추기 위함입니다.

 

2) tr2101 : 특정 선/옵션 코드에 대한 보다 자세한 정보를 돌려줍니다.

 

3) tr8434 : 복수 개의 선/옵션 정보를 돌려줍니다. 관심 있는 복수 개의 코드를 한번에 받을 수 있어도 유용합니다.

tr2301로 weekly 옵션 정보를 모두 받아 오는 파이썬 코드입니다. 보다 정교하게 현재 일자 기준 거래되는 weekly option 코드를 만들 수 있지만 그냥 간단하게 전체를 받아오면 됩니다. 만약 해당 주 거래 물이 없다면 list가 empty로 돌아옵니다.

 

def get_weekly_option_prices() :
     # weekly W1 - W5  yyyymm이 W1 - W5임
     for i in range(1,6) :
         yyyymm = 'W' + str(i)+'    '

        ret = self.exchange.get_2301(yyyymm, 'W') #  yyyymm(예, 첫 번재 주 : "W1    ")의 weely option 정보를 요청한다.
        if 'error' in ret[0] : # 오류임
            return 0

        if len(ret[0]) == 0 :  # 정보가 없음. 해당 주는 거래가 안됨
            continue

        for each in ret[0] : # for call
            print(each)

        for each in ret[1] : # for put
            print(each)

 

옵션 전광판 TR에서 주는 정보를 바탕으로 hts 옵션 전광판과 유사하게 출력해보았습니다.

 

사진 삭제

사진 설명을 입력하세요.

마지막으로 오늘같이 weekly의 옵션의 경우에는 만기 일에는 다음 주 weekly option이 상장되어 같이 거래가 됩니다.

코드 상으로 W1 - W5까지 모두 검색을 하므로, 이러한 부분은 신경 쓸 필요는 없습니다.

 

 

 

반응형

설정

트랙백

댓글

선물/옵션 매매시 사용하는 8자리 코드에 해석하는 함수에 대하여 정리합니다. 

코드에 대한 자세한 설명은 아래 글을 참고하세요.

https://agibbyeongari.tistory.com/897

 

[선물옵션 거래] 종목코드 의미

[선물옵션 거래] 종목코드 의미 선물거래나 옵션거래를 할 때, 자주 접하게 되는 선물옵션 종목코드의 각 자리의 숫자와 영어 알파벳의 의미에 대해 알아보았다. 선물옵션 거래를 할 때, 선물옵

agibbyeongari.tistory.com

 

주식 선물, 스프레드, 변동성지수 등등은 제외하고, 주로 사용하는 선물/옵션과 미니, weekly에 대하여 해석한 함수입니다.

 

주의할 부분은 월인데요. 숫자와 혼란을 방지하기 위하여 I, O 등은 빠져있습니다. 그래서 그냥 손코딩했습니다.

code_4 = {'Q':2020, 'R':2021, 'S':2022, 'T':2023, 'V':2024, 'W':2025, '6':2026, '7':2027, '8':2028, '9':2029, '0':2030, '1':2031, '2':2032, '3':2033, '4':2034, '5':2035}

 

잘 동작하는지 확인해보겠습니다.

 

지수/옵션 코드를 입력하면 오른쪽에 있는 형태로 돌려줍니다. 이 값을 참고하면 입력 코드가 어떤 종류인지 구분이 가능할 것 같습니다.

 

관련코드는 아래 github에 있습니다.

https://github.com/multizone-quant/xing-api/blob/master/get_code_info.py

반응형

설정

트랙백

댓글

xing api 관련하여 오랜만에 글 올립니다.

 

오늘은 xing에서 제공하는 선물/옵션 관련 tr에 대하여 정리합니다.

작업할 tr은 다음과 같습니다.

 

tr0441 : 선물/옵션 보유종목 조회
tr8432 : 코스피200 지수선물 마스터 조회
tr8435 : 파생 코드 조회
tr2301 : 선물옵션 상세 정보 조회
tr2101 : 선물/옵션 현재가 조회 

 

선물/옵션 자동 매매를 하기 위한 아주 기본적인 TR 들입니다.

 

코드는 최대한 있는 그대로 개발하였기 때문에 이해하기 아주 쉬울 것으로 보입니다. 코드와 관련하여 특별하게 언급할 사항은 없기 때문에 아래 github에 있는 소스코드를 참고하시면 될 것 같습니다.

 

https://github.com/multizone-quant/xing-api/blob/master/xing_api_future.py

반응형

설정

트랙백

댓글