상한가 자동 매매 - 6. 조건검색식 사용하기
조건검색식 사용하기
전체 종목에 대한 일정 조건에 일치할 경우 자동 매수 매도를 하기 위해
전체 종목의 현재가를 계속 조회하는 방식은 비효율적입니다.
그렇기 때문에 키움 사용자 조건검색식을 사용하여 원하는 조건의 종목을 1차로 걸러내어 사용하는 방식을 사용하도록 하겠습니다.
먼저 조건검색식 API를 사용하기 위해
KOAStudio를 통해 사용방법을 알아보도록 하겠습니다.
KOAStudioSA.exe 파일을 더블 클릭하여 실행합니다.
아래의 화면처럼 왼쪽 하단에 개발가이드 항목을 클릭 후 노출되는 목록에서
왼쪽 중앙에 조건검색 + 기호를 클릭합니다.
그럼 아래 기본설명과 관련함수가 노출되는데요.
그중 관련함수 + 기호를 클릭합니다.
그럼 아래와 같이 사용가능한 함수들이 노출됩니다.
이중 SendCondition 함수를 살펴보도록 하겠습니다.
왼쪽 중앙에 long SendCondition(BSTR ...) 항목을 클릭합니다.
그럼 중앙에 해당 함수에 대한 설명이 노출됩니다.
화면번호, 조건식명, 조건식 인덱스, 조회구분 값을 넣고 호출하면 된다고 나와 있습니다.
실시간 조건검색을 할 경우 한 화면번호당 조회 가능한 종목코드는 100개 까지이며,
실시간 조건검색 가능 화면번호 갯수는 최대 10개 까지입니다.
다음으로 SendCondition 함수로 호출할 경우 받는 반환값에 대해서 알아보도록 하겠습니다.
SendCondition 함수로 호출할 경우 2가지 방식으로 받게됩니다.
첫째는 호출하자 마자 받게되는 값이며, 두번째는 호출 이후 실시간으로 받는 방법이 있습니다.
먼저 호출 하자마자 받는 OnReceiveTrCondition 함수를 살펴보도록 하겠습니다.
아래와 같이 void OnReceiveTrCondition(BSTR ...) 목록을 클릭합니다.
그럼 중앙에 해당 함수에 대한 설명이 노출됩니다.
화면번호, 종목코드 리스트(';' 구분되어 전달), 조건식이름, 조건명 인덱스, 연속조회 여부 항목이 전달된다고 합니다.
다음으로 호출 이후 실시간으로 전달 받는 OnReceiveRealCondition 함수를 살펴보도록 하겠습니다.
아래와 같이 void OnReceiveRealCondition(BSTR ...) 목록을 클릭합니다.
그럼 중앙에 해당 함수에 대한 설명이 노출됩니다.
종목코드, 이벤트 종류(편입 및 이탈), 조건식 이름, 조건명 인덱스가 전달된다고 합니다.
편입 및 이탈은 만약 일봉 기준 현재 종가가 1봉전 종가보다 27.5% 이상 일 경우의 조건식이라면
27.5% 이상 오르면 편입(I)으로 전달된 후 다시 27.5% 이하로 떨어질 경우 이탈(D)로 값이 전달됩니다.
그럼 해당 코드가 적용된 소스 코드를 살펴보도록 하겠습니다.
아래의 소스 코드를 upperLimitPriceTrading.py 파일에 작성 또는 전체를 변경해줍니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | import sys from PyQt5.QtWidgets import * from PyQt5 import uic from PyQt5.QAxContainer import * import logging import logging.handlers from datetime import datetime form_class = uic.loadUiType("upperLimitPriceTrading.ui")[0] # ui 파일을 로드하여 form_class 생성 class MyWindow(QMainWindow, form_class): # MyWindow 클래스 QMainWindow, form_class 클래스를 상속 받아 생성됨 def __init__(self): # MyWindow 클래스의 초기화 함수(생성자) super().__init__() # 부모클래스 QMainWindow 클래스의 초기화 함수(생성자)를 호출 self.setupUi(self) # ui 파일 화면 출력 global globalPrice # 전체에서 투입금을 사용하기 위해 global로 선언을 해줌(전역변수) globalPrice = '0' # 투입금에 0을 셋팅해줌 global logger # 전체에서 로그를 사용하기 위해 global로 선언을 해줌(전역 변수) logger = logging.getLogger('upperLimitPriceTradingLogger') # 로그 인스턴스를 만든다 self.set_logger() # 로그 인스턴스 환경 설정을 셋팅함 self.kiwoom = QAxWidget("KHOPENAPI.KHOpenAPICtrl.1") # 키움증권 Open API+의 ProgID를 사용하여 생성된 QAxWidget을 kiwoom 변수에 할당 self.btnStart.setDisabled(True) # 거래시작 버튼을 비활성화 상태로 변경 self.btnStop.setDisabled(True) # 거래중지 버튼을 비활성화 상태로 변경 self.btnReStart.setDisabled(True) # 재시작 버튼을 비활성화 상태로 변경 self.lePrice.setDisabled(True) # 투입금 입력란을 비활성화 상태로 변경 self.cbAcctNo.setDisabled(True) # 계좌번호 선택란을 비활성화 상태로 변경 self.leD2Price.setDisabled(True) # D2예수금 입력란을 비활성화 상태로 변경 self.cbCdtNm.setDisabled(True) # 조건검색명 선택란을 비활성화 상태로 변경 self.leTotalPrice.setDisabled(True) # 총투입금 입력란을 비활성화 상태로 변경 self.leProfits.setDisabled(True) # 수익금 입력란을 비활성화 상태로 변경 self.leProfitsPc.setDisabled(True) # 수익률 입력란을 비활성화 상태로 변경 self.pteBuyLog.setDisabled(True) # 매도 종목 노출란을 비활성화 상태로 변경 self.pteSellLog.setDisabled(True) # 매수 종목 노출란을 비활성화 상태로 변경 self.pteLog.setDisabled(True) # 전체 내역 노출란을 비활성화 상태로 변경 self.btnLogin.clicked.connect(self.btn_login) # ui 파일을 생성할때 작성한 로그인 버튼의 objectName 으로 클릭 이벤트가 발생할 경우 btn_login 함수를 호출 self.kiwoom.OnEventConnect.connect(self.event_connect) # 키움 서버 접속 관련 이벤트가 발생할 경우 event_connect 함수 호출 self.kiwoom.OnReceiveConditionVer.connect(self.receive_condition_var) # 키움 사용자 조건검색식 수신 관련 이벤트가 발생할 경우 receive_condition_var 함수 호출 self.kiwoom.OnReceiveTrCondition.connect(self.receive_tr_condition) # 키움 사용자 조건검색식 초기 조회 시 반환되는 값이 있을 경우 receive_tr_condition 함수 호출 self.kiwoom.OnReceiveRealCondition.connect(self.receive_real_condition) # 키움 사용자 조건검색식 실시간 조회 반환되는 값이 있을 경우 receive_real_condition 함수 호출 self.kiwoom.OnReceiveMsg.connect(self.on_receive_msg) # 키움 기타 메시지가 발생할 경우 on_receive_msg 함수 호출 self.btnStart.clicked.connect(self.btn_start) # ui 파일을 생성할때 작성한 거래시작 버튼의 objectName 으로 클릭 이벤트가 발생할 경우 btn_start 함수를 호출 self.kiwoom.OnReceiveTrData.connect(self.receive_trdata) # 키움 데이터 수신 관련 이벤트가 발생할 경우 receive_trdata 함수 호출 def set_logger(self): # 로그 환경을 설정해주는 함수 fomatter = logging.Formatter('[%(levelname)s|%(lineno)s] %(asctime)s > %(message)s') # 로그를 남길 방식으로 "[로그레벨|라인번호] 날짜 시간,밀리초 > 메시지" 형식의 포매터를 만든다 logday = datetime.today().strftime("%Y%m%d") # 로그 파일 네임에 들어갈 날짜를 만듬 (YYYYmmdd 형태) fileMaxByte = 1024 * 1024 * 100 # 파일 최대 용량인 100MB를 변수에 할당 (100MB, 102,400KB) fileHandler = logging.handlers.RotatingFileHandler('./log/stock_' + str(logday) + '.log', maxBytes=fileMaxByte, backupCount=10) # 파일에 로그를 출력하는 핸들러 (100MB가 넘으면 최대 10개까지 신규 생성) streamHandler = logging.StreamHandler() # 콘솔에 로그를 출력하는 핸들러 fileHandler.setFormatter(fomatter) # 파일에 로그를 출력하는 핸들러에 포매터를 지정 streamHandler.setFormatter(fomatter) # 콘솔에 로그를 출력하는 핸들러에 포매터를 지정 logger.addHandler(fileHandler) # 로그 인스턴스에 파일에 로그를 출력하는 핸들러를 추가 logger.addHandler(streamHandler) # 로그 인스턴스에 콘솔에 로그를 출력하는 핸들러를 추가 logger.setLevel(logging.DEBUG) # 로그 레벨을 디버그로 만듬 def btn_login(self): # Login 버튼 클릭 시 실행되는 함수 logger.debug("Login 버튼 클릭") # debug 레벨 로그를 남김 ret = self.kiwoom.dynamicCall("CommConnect()") # 키움 로그인 윈도우를 실행 def btn_start(self): # 거래시작 버튼 클릭 시 실행되는 함수 logger.debug("거래시작 버튼 클릭") # debug 레벨 로그를 남김 tempPrice = self.lePrice.text().strip().replace(',', '') # 입력된 종목당 투입금을 가져옴 if tempPrice == None or tempPrice == '': # 투입금이 있는지 체크 QMessageBox.about(self, "message", "종목당 투입금을 입력해주세요.") # 투입금이 없다면 안내 얼럿 노출 return # 아래 로직을 진행하지 않도록 처리함 else: globalPrice = tempPrice # 투입금을 전역변수에 셋팅 logger.debug("투입금(globalPrice): " + str(globalPrice)) # debug 레벨 로그를 남김 acctNo = self.cbAcctNo.currentText().strip() # 선택된 계좌번호를 가져옴 if acctNo == None or acctNo == '': # 계좌번호가 있는지 체크 QMessageBox.about(self, "message", "계좌번호를 선택해주세요.") # 계좌번호가 없다면 안내 얼럿 노출 return # 아래 로직을 진행하지 않도록 처리함 else: logger.debug("예수금상세현황요청 시작") # debug 레벨 로그를 남김 ret = self.kiwoom.dynamicCall('SetInputValue(QString, QString)', "계좌번호", acctNo) # 계좌번호 셋팅 ret = self.kiwoom.dynamicCall('SetInputValue(QString, QString)', "비밀번호", "") # 비밀번호 셋팅 ret = self.kiwoom.dynamicCall('SetInputValue(QString, QString)', "비밀번호입력매체구분", "00") # 비밀번호입력매체구분 셋팅 ret = self.kiwoom.dynamicCall('SetInputValue(QString, QString)', "조회구분", "1") # 조회 구분 셋팅 ret = self.kiwoom.dynamicCall('CommRqData(QString, QString, int, QString)', "opw00001_req", "opw00001", 0, "0102") # 키움 dynamicCall 함수를 통해 CommRqData 함수를 호출하여 opw00001 API를 구분명 opw00001_req, 화면번호 0102으로 호출함 def event_connect(self, err_code): # 키움 서버 접속 관련 이벤트가 발생할 경우 실행되는 함수 if err_code == 0: # err_code가 0이면 로그인 성공 그외 실패 logger.info("로그인 성공") # info 레벨 로그를 남김 self.pteLog.appendPlainText("로그인 성공") # ui 파일을 생성할때 작성한 plainTextEdit의 objectName 으로 해당 plainTextEdit에 텍스트를 추가함 account_num = self.kiwoom.dynamicCall("GetLoginInfo(QString)", ["ACCNO"]) # 키움 dynamicCall 함수를 통해 GetLoginInfo 함수를 호출하여 계좌번호를 가져옴 logger.debug("계좌번호: " + account_num.rstrip(';')) # debug 레벨 로그를 남김 self.pteLog.appendPlainText("계좌번호: " + account_num.rstrip(';')) # 키움은 전체 계좌를 반환하며 각 계좌 번호 끝에 세미콜론(;)이 붙어 있음으로 제거하여 plainTextEdit에 텍스트를 추가함 self.cbAcctNo.addItem(account_num.rstrip(';')) # 계좌번호 선택 박스에 계좌번호 셋팅 self.btnStart.setDisabled(False) # 거래시작 버튼을 활성화 상태로 변경 self.lePrice.setDisabled(False) # 투입금 입력란을 활성화 상태로 변경 self.cbAcctNo.setDisabled(False) # 계좌번호 선택란을 활성화 상태로 변경 self.cbCdtNm.setDisabled(False) # 조건검색명 선택란을 활성화 상태로 변경 self.pteBuyLog.setDisabled(False) # 매도 종목 노출란을 활성화 상태로 변경 self.pteSellLog.setDisabled(False) # 매수 종목 노출란을 활성화 상태로 변경 self.pteLog.setDisabled(False) # 전체 내역 노출란을 활성화 상태로 변경 self.btnLogin.setDisabled(True) # 로그인 버튼을 비활성화 상태로 변경 self.leTotalPrice.setDisabled(True) # 총투입금 입력란을 비활성화 상태로 변경 self.leProfits.setDisabled(True) # 수익금 입력란을 비활성화 상태로 변경 self.leProfitsPc.setDisabled(True) # 수익률 입력란을 비활성화 상태로 변경 self.leTotalPrice.setText('0') # 총투입금을 0원으로 셋팅 self.leProfits.setText('0') # 수익금을 0원으로 셋팅 self.leProfitsPc.setText('0%') # 수익률을 0%으로 셋팅 self.kiwoom.dynamicCall('GetConditionLoad()') # 키움 서버에 사용자 조건식 목록을 요청 QMessageBox.about(self, "message", "계좌 비밀번호 입력 및 환경 설정을 진행해주세요.") # 안내 얼럿 노출 else: logger.info("로그인 실패") # info 레벨 로그를 남김 self.pteLog.appendPlainText("로그인 실패") # ui 파일을 생성할때 작성한 plainTextEdit의 objectName 으로 해당 plainTextEdit에 텍스트를 추가함 def receive_condition_var(self, bRet, sMsg): # 사용자 조건검색식 수신 함수 logger.debug("receive_condition_var bRet: "+str(bRet)) # debug 레벨 로그를 남김 logger.debug("receive_condition_var sMsg: "+str(sMsg)) # debug 레벨 로그를 남김 conditionNameList = self.kiwoom.dynamicCall('GetConditionNameList()') # 수신된 사용자 조건검색식 리스트를 받아옴 (ex. 인덱스^조건명;) conditionNameListArray = conditionNameList.rstrip(';').split(';') # 조건검색식 리스트에 마지막 ";" 기호를 삭제하고 ";" 기호 기준 분리 logger.info("conditionNameListArray:" + str(conditionNameListArray)) # info 레벨 로그를 남김 for i in range(0, len(conditionNameListArray)): # 조건검색식 개수만큼 반복 self.cbCdtNm.addItem(conditionNameListArray[i]) # 콤보 박스에 조건 셋팅 index = self.cbCdtNm.findText('191^ULPTrading') # 조건검색식 명으로 순번을 찾음 if index >= 0: # 해당 순번이 있다면 (해당 조건검색식 명이 있다면) self.cbCdtNm.setCurrentIndex(index) # 해당 순번을 선택 (해당 조검검색식을 선택) # sScrNo : 화면번호 # strCodeList : 종목코드 리스트 (ex:039490;005930;036570;…;) # strConditionName: 조건식 이름 # nIndex: 조건명 인덱스 # nNext : 연속조회 여부(0:연속조회없음, 2:연속조회 있음) def receive_tr_condition(self, sScrNo, strCodeList, strConditionName, nIndex, nNext): # 조건검색 초기 조회시 반환되는 값을 받는 함수 logger.info("receive_tr_condition sScrNo: " + str(sScrNo) + ", strCodeList: " + str(strCodeList) + ", strConditionName: " + str(strConditionName) + ", nIndex: " + str(nIndex) + ", nNext: " + str(nNext)) # info 레벨 로그를 남김 # strCode : 종목코드 # strType : 이벤트 종류, "I":종목편입, "D", 종목이탈 # strConditionName : 조건식 이름 # strConditionIndex : 조건명 인덱스 def receive_real_condition(self, strCode, strType, strConditionName, strConditionIndex): # 조건검색 실시간 조회시 반환되는 값을 받는 함수 logger.info("receive_real_condition strCode: " + str(strCode) + ", strType: " + str(strType) + ", strConditionName: " + str(strConditionName) + ", strConditionIndex: " + str(strConditionIndex)) # info 레벨 로그를 남김 logDateTime = datetime.today().strftime("%Y-%m-%d %H:%M:%S") # 화면에 노출할 날짜를 만듬 (YYYY-mm-dd HH:MM:SS 형태) strCodeName = self.kiwoom.dynamicCall("GetMasterCodeName(QString)", [strCode]).strip() # 종목 코드로 종목 이름을 가져옴 if str(strType) == "I": # 편입 종목이라면 self.pteLog.appendPlainText(str(logDateTime) + " 편입 신호 : " + str(strCode) + ", " + str(strCodeName)) # 트레이딩 화면 내역에 로그를 남김 elif str(strType) == "D": # 이탈 종목이라면 self.pteLog.appendPlainText(str(logDateTime) + " 이탈 신호 : " + str(strCode) + ", " + str(strCodeName)) # 트레이딩 화면 내역에 로그를 남김 def receive_trdata(self, screen_no, rqname, trcode, recordname, prev_next, data_len, err_code, msg1, msg2): # 키움 데이터 수신 함수 if rqname == "opw00001_req": # 수신된 데이터 구분명이 opw00001_req 일 경우 (예수금상세현황) d2Price = self.kiwoom.dynamicCall('CommGetData(QString, QString, QString, int, QString)', trcode, "", rqname, 0, "d+2추정예수금") # d+2추정예수금을 가져옴 d2Price = self.change_amt_format(d2Price, 0) # 금액을 천단위 콤마(",")를 추가함 logger.debug("D2예수금: " + str(d2Price)) # debug 레벨 로그를 남김 self.leD2Price.setText(str(d2Price)) # 2추정예수금을 D2예수금 입력란에 표기함 self.btnStop.setDisabled(False) # 거래중지 버튼을 활성화 상태로 변경 self.btnStart.setDisabled(True) # 거래시작 버튼을 비활성화 상태로 변경 conditionArray = self.cbCdtNm.currentText().strip().split('^') # 선택한 조건검색명을 가져와서 ^ 기호를 기준 분리 conditionIndex = conditionArray[0] # 선택한 조건검색 번호를 가져옴 conditionName = conditionArray[1] # 선택한 조검검색 이름을 가져옴 # 조건검색 종목조회TR송신한다. # strScrNo : 화면번호 # strConditionName : 조건식 이름 # nIndex : 조건명 인덱스 # nSearch : 조회구분(0:조건검색, 1:실시간 조건검색) # 1:실시간조회의 화면 개수의 최대는 10개 ret = self.kiwoom.dynamicCall("SendCondition(QString,QString, int, int)", "0156", conditionName, conditionIndex, 1) # 선택한 조건검색을 화면번호 0156 실시간 조건검색 타입으로 호출 def on_receive_msg(self, sScrNo, sRQName, sTrCode, sMsg): # 키움 기타 메시지 수신 함수 logger.info("OnReceiveMsg sScrNo: " + sScrNo + ", sRQName: " + sRQName + ", sTrCode: " + sTrCode + ", sMsg: " + sMsg) # info 레벨 로그를 남김 def change_amt_format(self, data, percent): # 금액을 천단위 콤마(",")를 추가하여 반환하는 함수 is_minus = False # 마이너스 표기를 거짓으로 지정 if data.startswith('-'): # 입력된 금액의 앞자리가 - 일 경우 is_minus = True # 마이너스 표기를 참으로 지정 strip_str = data.lstrip('-0') # 입력된 금액의 앞자리에 - 기호나 0을 삭제하여 반환 if strip_str == '': # 입력된 금액이 공백이라면 if percent == 1: # 퍼센트 구분 기호가 1이라면 return '0.00' # 0.00 으로 반환 else: # 퍼센트 구분 기호가 1이 아니라면 return '0' # 0 으로 반환 if percent == 1: # 퍼센트 구분 기호가 1이라면 strip_data = int(strip_str) # 입력값을 int로 변환 후 strip_data = strip_data / 100 # 100으로 나눠주고 form = format(strip_data, ',.2f') # 소수점 2자리까지 자름 elif percent == 2: # 퍼센트 구분 기호가 2이라면 strip_data = float(strip_str) # 입력값을 float로 변환 후 form = format(strip_data, ',.2f') # 소수점 2자리까지 자름 else: # 퍼센트 구분 기호가 1 또는 2가 아니라면 strip_data = int(strip_str) # 입력값을 int로 변환 후 form = format(strip_data, ',d') # 정수형으로 만듬 if form.startswith('.'): # 변환된 금액의 앞자리가 . 으로 시작한다면 form = '0' + form # 변환된 금액에 앞에 0을 붙여줌 if is_minus: # 입력된 금액이 마이너스 였다면 form = '-' + form # 변환된 금액에 앞에 - 기호를 붙여줌 return form # 변환됨 금액을 반환함 # py 파일 실행시 제일 먼저 동작 if __name__ == "__main__": app = QApplication(sys.argv) myWindow = MyWindow() # MyWindow 클래스를 생성하여 myWondow 변수에 할당 myWindow.show() # MyWindow 클래스를 노출 app.exec_() # 메인 이벤트 루프에 진입 후 프로그램이 종료될 때까지 무한 루프 상태 대기 |
기존 소스 코드에서 수정된 부분에 대해 살펴보겠습니다.
먼저 사용자 조건검색식 초기 조회 시 전달되는 값을 받도록 receive_tr_condition 함수에 연결하였습니다.
1 | self.kiwoom.OnReceiveTrCondition.connect(self.receive_tr_condition) # 키움 사용자 조건검색식 초기 조회 시 반환되는 값이 있을 경우 receive_tr_condition 함수 호출 |
먼저 사용자 조건검색식 실시간 조회 시 전달되는 값을 받도록 receive_real_condition 함수에 연결하였습니다.
1 | self.kiwoom.OnReceiveRealCondition.connect(self.receive_real_condition) # 키움 사용자 조건검색식 실시간 조회 반환되는 값이 있을 경우 receive_real_condition 함수 호출 |
조건검색식 초기 조회 시 전달되는 값을 받는 receive_tr_condition 함수를 만들었습니다.
단순 로그만 남기도록 처리되었습니다.
1 2 3 4 5 6 7 | # sScrNo : 화면번호 # strCodeList : 종목코드 리스트 (ex:039490;005930;036570;…;) # strConditionName: 조건식 이름 # nIndex: 조건명 인덱스 # nNext : 연속조회 여부(0:연속조회없음, 2:연속조회 있음) def receive_tr_condition(self, sScrNo, strCodeList, strConditionName, nIndex, nNext): # 조건검색 초기 조회시 반환되는 값을 받는 함수 logger.info("receive_tr_condition sScrNo: " + str(sScrNo) + ", strCodeList: " + str(strCodeList) + ", strConditionName: " + str(strConditionName) + ", nIndex: " + str(nIndex) + ", nNext: " + str(nNext)) # info 레벨 로그를 남김 |
조건검색식 실시간 조회 시 전달되는 값을 받는 receive_real_condition 함수를 만들었습니다.
로그를 남기고 키움 GetMasterCodeName 함수를 통해 종목코드로 종목이름을 가져옵니다.
해당 GetMasterCodeName 함수는 배열만 받으니 종목코드를 [ ] 안에 넣어주셔야 합니다.
이후 편입, 이탈을 구분하여 트레이딩 화면 내역 영역에 로그를 출력하도록 하였습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | # strCode : 종목코드 # strType : 이벤트 종류, "I":종목편입, "D", 종목이탈 # strConditionName : 조건식 이름 # strConditionIndex : 조건명 인덱스 def receive_real_condition(self, strCode, strType, strConditionName, strConditionIndex): # 조건검색 실시간 조회시 반환되는 값을 받는 함수 logger.info("receive_real_condition strCode: " + str(strCode) + ", strType: " + str(strType) + ", strConditionName: " + str(strConditionName) + ", strConditionIndex: " + str(strConditionIndex)) # info 레벨 로그를 남김 logDateTime = datetime.today().strftime("%Y-%m-%d %H:%M:%S") # 화면에 노출할 날짜를 만듬 (YYYY-mm-dd HH:MM:SS 형태) strCodeName = self.kiwoom.dynamicCall("GetMasterCodeName(QString)", [strCode]).strip() # 종목 코드로 종목 이름을 가져옴 if str(strType) == "I": # 편입 종목이라면 self.pteLog.appendPlainText(str(logDateTime) + " 편입 신호 : " + str(strCode) + ", " + str(strCodeName)) # 트레이딩 화면 내역에 로그를 남김 elif str(strType) == "D": # 이탈 종목이라면 self.pteLog.appendPlainText(str(logDateTime) + " 이탈 신호 : " + str(strCode) + ", " + str(strCodeName)) # 트레이딩 화면 내역에 로그를 남김 |
마지막으로 예수금상세현황 조회 요청이 완료되었을 경우
사용자가 선택한 조건검색명을 가져와 실시간 조회 요청을 하도록 처리되었습니다.
1 2 3 4 5 6 7 8 9 10 11 | conditionArray = self.cbCdtNm.currentText().strip().split('^') # 선택한 조건검색명을 가져와서 ^ 기호를 기준 분리 conditionIndex = conditionArray[0] # 선택한 조건검색 번호를 가져옴 conditionName = conditionArray[1] # 선택한 조검검색 이름을 가져옴 # 조건검색 종목조회TR송신한다. # strScrNo : 화면번호 # strConditionName : 조건식 이름 # nIndex : 조건명 인덱스 # nSearch : 조회구분(0:조건검색, 1:실시간 조건검색) # 1:실시간조회의 화면 개수의 최대는 10개 ret = self.kiwoom.dynamicCall("SendCondition(QString,QString, int, int)", "0156", conditionName, conditionIndex, 1) # 선택한 조건검색을 화면번호 0156 실시간 조건검색 타입으로 호출 |
이상으로 조건검색식 사용법을 알아보았습니다.
다음 챕터에서는 해당 조건검색식에서 추출된 종목에 대해 이어서 진행하도록 하겠습니다.
주식 자동매매, 주식 어플, 주식 정보 웹 스크래이핑, 공시 정보 연동 등
주식에 관심이 있는 사람들에게 도움이 될 정보를 기본부터 차근차근 정리할 예정입니다.
해당 글을 보고 지적 사항, 수정 사항이 있다면 언제든지 댓글, 또는 메일로 연락 부탁드립니다.
여러분의 관심이 글을 보는 다음 누군가에겐 큰 도움이 될 것입니다. 감사합니다.