PYTHON/AUTO TRADE SYSTEM

[자동 매매 시스템 구축하기] 주문 정보 관리하기 (1) - 주문 접수 함수 제작하기

  • -

키움증권 Open API를 활용한 자동 매매 시스템을 구현하기 위해서는 주문과 그 결과로 발생하는 데이터, 그리고 그 과정에서 발생하는 데이터를 관리해줘야 할 필요성이 있다. 그렇게 하기 위해 가장 먼저 구현해야 하는 기능은 주문 기능인데, 이 역시 다른 함수와 마찬가지로 캡슐화된 주문 함수를 제작해보도록 하자.

 

주문 함수 제작하기

여느 함수와 마찬가지로, 주문 함수를 제작하는 것은 크게 어렵지 않다. 개발가이드 내에서는 SendOrder라는 개념을 사용하고 있기 때문에, 다른 함수와 동일한 로직에 따라 주문 함수를 제작하면 된다.

"""SendOrder 함수 실행"""
def __sendorder(self):
    pass

 

그렇다면 여기서 함수를 실행하기 위해 함수 내에 전달해줘야 하는 인자로는 어떤 인자들이 있을까? 이는 개발 가이드를 살펴보면 된다. 아래의 사진을 보면 되며, 그 내용이 다소 어려워보일 수도 있겠지만 어려워할 필요는 없다. 하나씩 구현해보도록 하자.

 

일단 SendOrder 함수를 사용하기 위해 입력해야 하는 값의 목록으로는 RqName, ScreenNo, AccNo, OrderType, Code, Qty, Price, HogaGb, OrgOrderNo의 9가지이다.

"""SendOrder 함수 실행"""
def __sendorder(self, rqname, scrno, accno, ordertype, code, qty, price, hogagb, orgorderno):
    pass

 

그리고 이제 해당 함수를 실행하기 위해   self.kiwoom.dynamicCall  을 사용해서 SendOrder 함수를 실행하면 된다. 물론 SendOrder 뒤 부분에서는 입력값의 데이터 형태를 알려주는 QString과 int를 입력해주면 된다. 이 QString과 int 중 어떤 데이터를 사용할지는 위 개발가이드 상 설명서를 참고하면 된다.

"""SendOrder 함수 실행"""
def __sendorder(self, rqname, scrno, accno, ordertype, code, qty, price, hogagb, orgorderno):
    self.kiwoom.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
                            [rqname, scrno, accno, ordertype, code, qty, price, hogagb, orgorderno])

 

이 주문 함수를 제작하는 과정에 있어서, 사전에 따로 입력하지 않아도 되는 인자에 대해서는 별도의 파라미터로 지정하지 않고,   def __sendorder   함수 내에서 데이터를 얻어다가 직접 전달해주는 방식으로 함수를 실행할 수도 있다. 가장 대표적인 것이 계좌번호(accno)나 화면번호(scrno)가 이에 해당하는데, 계좌번호나 화면번호는 상황에 따라 값이 변동되지 않고 항상 거의 일정한 데이터를 전달(고정성)해줘야 하기 때문이다. 

하지만 이와 달리 매수 수량이나 가격, 호가 구분, 주문정보 등의 경우에는 해당 함수를 실행하는 지점이나 시장의 상황에 따라 서로 각기 다른 데이터를 전달(변동성)해줘야 하기 때문에 함수 내에서 별도로 규정하지 않는 것이 좋다.

 

 


728x90

 

 

주문 데이터 관리하기

주문이 접수되면 주문 접수 번호가 생성되는데, 키움증권 Open API에서는 이 데이터를 원주문번호라 한다. 이 원주문번호 데이터는 추후 주문을 취소하거나 재접수하거나 하는 상황에서 반드시 필요한 데이터이기 때문에, 주문이 접수됐을 경우에는 이 데이터를 반드시 저장해줘야만 추후에 재주문이 필요할 때에 바로 불러와서 사용할 수 있다. 

추가적으로, 특정 가격에 지정가매도로 접수되어 있는 주문에 대해 손절매가 진행되어야 할 때에는 곧바로 시장가매도로 정정 주문을 넣을 수 없다. 따라서 해당 주문의 원주문번호를 얻어다가 ①주문을 취소한 후에 시장가매도로 접수하던지 ②손절 가격보다 낮은 가격으로 정정 주문을 접수하던지 해야 한다. 이러한 경우 외에도 원주문번호는 다양한 지점에서 필요하기 때문에 반드시 필요한 데이터에 해당하는데, 그렇다면 원주문번호는 언제 발생할까?   OnReceiveChejanData   이벤트에서 sGubun == 0으로 구분되는 "주문 체결 통보"가 발생했을 때 얻어올 수 있다. 그럼   OnReceiveChejanData  는 언제 발생할까? 주문이 접수되거나 해당 접수로부터 주문이 체결되었을 때 발생한다. (sGubun == 1로 구분되는 계좌잔고통보도 있는데, 이는 계좌에 새로운 종목이 추가되거나 기존 보유 종목이 매도로 인해 삭제됐을 때 발생한다.)

따라서 우리가 위에서 만들었던 주문 함수가 실행됐을 때   OnRecieveChejanData   이벤트가 발생하게 되므로, 해당 이벤트가 발생했을 때 실행할 함수를 제작해주도록 하자.
※ Line : 29

class tradesystem(QMainWindow, form_class):
    def __init__(self):
        super().__init__()
        self.setupUi(self)  ## GUI 켜기
        self.setWindowTitle("주식 프로그램")  ## 프로그램 화면 이름 설정
        self.condition_list = {'index':[], 'name':[]}

        self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1")  ## OpenAPI 시작
        self.kiwoom.dynamicCall("CommConnect()")  ## 로그인 요청

        self.setrealreg = _df.setrealreg()

        """데이터 요청 구간"""
        self.pushButton.clicked.connect(self.request_opt10016)
        self.pushButton_2.clicked.connect(self.request_opt10080)
        self.pushButton_3.clicked.connect(self._pushbtn_3)
        self.pushButton_4.clicked.connect(self._pushbtn_4)
        self.pushButton_5.clicked.connect(self.__getconditionload)
        self.pushButton_6.clicked.connect(self._pushbtn_6)
        self.pushButton_7.clicked.connect(self._pushbtn_7)

        """이벤트 처리 구간"""
        self.kiwoom.OnReceiveTrData.connect(self.receive_trdata)        ## 데이터 조회 요청 처리 함수
        self.kiwoom.OnEventConnect.connect(self.process_login)          ## 로그인 반환값 처리 함수
        self.kiwoom.OnReceiveRealData.connect(self.receive_realdata)    ## 실시간 데이터 수신 처리 함수
        self.kiwoom.OnReceiveConditionVer.connect(self.OnReceiveConditionVer)
        self.kiwoom.OnReceiveTrCondition.connect(self.OnReceiveTrCondition)
        # self.kiwoom.OnReceiveRealCondition.connect(self.OnReceiveRealCondition)
        self.kiwoom.OnRecieveChejanData.connect(self.receive_chejandata)

 

그렇다면 우리는   self.recieve_chejandata  라는 함수에서 어떤 인자를 파라미터로 전달받아야 할까? 이전에 차트 데이터를 받아올 때 제작했던   def recieve_trdata  에서는 ScrNo, RqName, TrCode, RecordName, PreNext라는 다섯 개의 인자를 전달받았던 것처럼   def recieve_chejandata  내에서도 전달받아야 하는 인자가 있다. 이 역시 개발가이드를 살펴보면 된다.

위 사진을 보면 sGubun, nItemCnt, sFidList라는 세 개의 데이터만을 전달받을 수 있음을 알려주고 있는데, 사실 우리는 이 셋 중 맨 처음에 나오는 sGubun에 의해 기본적으로 어떤 데이터가 발생한 것인지만 구분해주면 되기 때문에, 나머지 두 인자는 사용하지 않는다.

def receive_chejandata(self, Gubun, ItemCnt, FidList):
    """
    Gubun(string) - 0:주문체결통보, 1:국내주식잔고통보, 4:파생상품잔고통보
    FidList(string) - 데이터 구분은 ;이다.
    """
    pass

 

 

 

다음 게시글에서   def receive_chejandata  내에서 Gubun이라는 변수에 따라 어떤 데이터가 발생하는지 살펴보고, 코드를 구현해보도록 하자.

 

 


728x90
반응형
Contents

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

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