PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 실시간 데이터 얻기 (2) - self.setrealreg 업데이트하기

  • -

지난 게시글에서 이야기했듯이,   def __setrealreg()  함수를 사용하기 위해서는 현재 실시간으로 등록되어 있는 종목들이 입력되어 있는   self.setrealreg  변수 내에 입력되어 있는 종목 데이터가 가장 정확해야 한다. 다시 말해, RealType의 인자로 0을 전달할지 1을 전달할지는 실시간으로 등록되어 있는 종목의 개수에 따라 좌우되니 실시간으로 등록되어 있는 종목들의 리스트가 담겨 있는 self.setrealreg 변수는 항상 데이터를 정확하게 유지해야 한다는 것이다.

 

 

데이터를 정확하게 유지해야 한다?

실제로 거래를 진행하다보면 실시간 등록을 해야 할 때도 있겠지만, 사전에 설정해두었던 로직대로 거래가 모두 이루어진 후에는 실시간을 해지해야 하는 경우가 있을 수 있고 이외에도 거래 조건에 어긋나서 실시간을 그만 해지해야 하는 경우도 있을 수 있다. 이런 경우에는 실시간 등록을 해지하는 동시에   self.setrealreg  변수 내에서의 종목 데이터를 삭제해줘야 할 것이다. 일단은 실시간 등록 시에   self.setrealreg  변수에 종목코드를 입력하는 절차부터 진행해보도록 하자.

 

 

데이터프레임의 사용법

데이터프레임의 사용법에 대해서는 다양한 방법들이 있지만, 본인이 가장 애용하는 방법은 인덱스 값을 얻어서 .loc 메서드와 함께 사용하는 것이다. 인덱스 값을 얻어오는 것은 의외로 간편하다. 인덱스란 무엇인지 조금 어렵게 느껴질 수 있는데, 파이썬 언어에서는 어떤 자료의 순서를 0부터 시작하게 된다는 점만 인지하고 있으면 된다. 첫 번째 자료의 인덱스 값은 0이고, 두 번째 자료의 인덱스 값은 1이고, 세 번째 자료의 인덱스 값은 2이고, 99번째 자료의 인덱스 값은 98이다.

그렇다면 우리가 이전에 사용했던 len(self.setrealreg)의 경우에는 데이터의 개수를 반환시켜주는 코드를 생각해보도록 하자. 이 len() 데이터를 곧바로 인덱스 값으로 활용할 수 있다는 점이 큰 메리트가 된다. 만약 데이터의 개수가 0개일 경우에는 우리는 0번째 자리에 데이터를 입력해주면 된다. 만약 데이터의 개수가 2개일 경우에는 len()값이 2가 되지만, 사실 첫 번째 데이터의 인덱스값은 0이고 두 번째 데이터의 인덱스 값은 1이기 때문에, 우리는 데이터의 개수(2)를 인덱스값으로 전달해서 인덱스가 2인 자리에 데이터를 새롭게 입력해주면 된다는 것이다. 백문이 불여일견, 코드를 만들어보자.

>>> import pandas as pd
>>> aa = {'item_code':['005930'], 'buy_date':['20220101']}
>>> df = pd.DataFrame(aa, columns=['item_code', 'buy_date'])
>>> df
  item_code  buy_date
0    005930  20220101

>>> len(df)
1

>>> idx = len(df)		## idx에는 1이 입력되어 있음

>>> df.loc[idx, 'item_code'] = '066570'   ## idx가 1인 자리의 'item_code' 칼럼에 '066570'을 입력해라.

>>> df         ## idx가 1인 자리의 'item_code'에 '066570'이 입력된 모습
  item_code  buy_date
0    005930  20220101
1    066570       NaN

 

위의 내용처럼, 데이터프레임의 개수가 곧 새롭게 입력할 자리의 인덱스(index) 번호가 된다는 점을 확인할 수 있다. 이를 조금만 더 응용해보면, 데이터프레임의 개수에서 1만큼 뺀 값은 곧 마지막 데이터의 인덱스 번호가 된다. 따라서 우리는 이 len()이라는 메서드를 통해   self.setrealreg  변수 내에서 새롭게 입력할 종목코드가 들어가야 할 인덱스 번호를 자동적으로 얻어올 수 있는 것이다. 그렇다면 add_to_setrealreg라는 함수를 제작해서 종목코드(item_code)를 하나의 인자로 전달받아 self.setrealreg 변수 안에 추가해주는 코드를 구축해보도록 하자.

 

일단 여기까지의 내용만 보면 알 수 있듯이, loc이라는 메서드는 단순하게 인덱스 값을 기반으로 해서 데이터에 접근하는 방법을 의미한다.   DataFrame.loc[0]  를 사용하면 0번째 인덱스에 해당하는 모든 데이터를 얻어올 수 있고,   DataFrame.loc[0, 'column_name'을 사용하면 0번째 인덱스의 'column_name'에 해당하는 데이터만 정확하게 얻어올 수 있다.

이를 이용해서, 반대로   DataFrame.loc[0, 'column_name'] = Value  를 사용하게 되면 0번째 인덱스의 'column_name'에 해당하는 위치에   Value  라는 데이터를 입력할 수 있고,   DataFrame.loc[0] = DataFrame  을 사용하게 되면 0번째 인덱스 자체에   DataFrame  이라는 데이터를 입력할 수 있게 된다. 이 개념을 바탕으로   self.setrealreg  변수에 종목코드를 입력하는 코드는 아래와 같다.

    def add_to_setrealreg(self, item_code):
        idx = len(self.setrealreg)
        self.setrealreg.loc[idx, 'item_code'] = item_code

 

 


728x90

 

 

add_to_setrealreg 함수 위치 지정하기

실시간 등록은 단순하게   def __setrealreg()  함수에서 이루어졌기 때문에, 해당 함수 내에서 실시간 등록이 이루어지기 전에   def add_to_setrealreg  함수를 실행해서   self.setrealreg  변수 내에 종목코드가 입력된 후, 실시간 등록이 이루어지도록 해야 한다. 그러기 위해서는 self.kiwoon.dynamicCall("SetRealReg~~~") 부분의 위 지점에서 함수를 실행해야 할 것이다.
※ Line : 4, 7

    """실시간 등록 함수"""
    def __setrealreg(self, item_code):
        if len(self.setrealreg['item_code']) == 0:
            self.add_to_setrealreg(item_code)
            return self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", item_code, '10', 0])
        else:
            self.add_to_setrealreg(item_code)
            return self.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", ["0101", item_code, '10', 1])

    """실시간 등록 종목 데이터 동기화 함수"""
    def add_to_setrealreg(self, item_code):
        idx = len(self.setrealreg)
        self.setrealreg.loc[idx, 'item_code'] = item_code

 

위의 코드에서 4번째 줄과 7번째 줄을 보면   def _setrealreg()  함수에서 if: 조건문의 하단과 else: 조건문의 하단에 작성되어 있는데, 해당 위치에 입력한 이유는 간단하다. 실시간으로 등록되어 있는 종목의 개수를 기반으로 해서 실시간으로 등록할 때 전달할 인자로 0을 입력할지 1을 입력할지 구분해야 하기 때문이다. 만약 if: 조건문의 위 지점에서   self.add_to_setrealreg  를 사용하게 된다면 일단 종목을 변수에 입력한 후에 실시간으로 등록되어 있는 종목 개수를 판단해내기 때문에 실시간 등록이 이루어져 있지 않은 상태에서 전달해야 할 0을 전달하지 않고 실시간으로 등록돼있는 종목이 몇 개이든지 간에 항상 1을 전달하기 때문에 오류가 발생하게 된다.

 

 

실시간 등록을 위한 GUI 구현하기

이제 def __setrealreg(self, item_code)라는 함수를 실행시키면 해당 종목을 실시간으로 등록한 후 실시간 등록 종목 리스트가 담겨 있는 변수(self.setrealreg)를 자동적으로 생성하며, 장중에 실시간으로 발생하는 데이터를 얻어올 수 있는 상태가 되었다. 그렇다면 해당 함수를 실행하기 위해 GUI를 구현하고, 특정 버튼이 눌렸을 때 실시간 등록이 이루어지도록 구현해야 해당 기능을 사용할 수 있게 된다. 

GUI 파일을 열어서 위와 같이 종목코드를 입력할 칸(LineEdit)과 실시간으로 등록할 버튼(pushButton)을 추가한 후에 저장해주도록 하자. 종목코드를 입력할 칸을 만들어주는 것은 def __setrealreg()함수에서 item_code라는 인자를 전달해줄 것을 요구하고 있기 때문이다. 이 GUI를 파이썬을 통해 기능을 연결하고 사용하고 결과 데이터를 확인하는 방법은 다음 게시글에서 확인해보도록 하자.

 

 


728x90
반응형
Contents

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

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