파이썬 키움openAPI 원하는 종목리스트 10호가까지 피라미드 매수주문하기
매수할 바닥저점을 정확히 안다면 굳이 이런 매수방법은 필요가 없다.
그냥 매일 모아가는 투자를 한다면 상당히 유용하다.
self.item_codes = 종목코드 리스트를 입력한다.
코딩이 어딘가에서 문제가 발생한 것 같은데 어디서 잘못된것인지 마지막 종목코드는 읽어오지 않는다.
그래서 허수의 종목하나를 기입했다.
###########[스케쥴링]############ ### [self.item_codes 끝에 허수종목을 하나 넣어줘야함. 뭐가 잘못된건지 감 안옴.] ### self.item_codes = "002200","008420","008420"
buyprice 변수는 한번 주문시 총 주문금액을 말한다.
1호가에 buyprice 금액의 4%를 정수화하여 매수주문한다.(정수화되기 때문에 실제 4%의 주문량보다는 적을것이다)
2호가에 5%
3호가 7%
.
.
.
delay_time = 0.37
buyprice = 1000000
buytemp = self.bunhal_stock_dict[self.hoga_x[iiiiii]]['현재가'] #종목현재가
buy_temp = int(int(buyprice) / int(buytemp))
buy_ea = []
buy_ea.append(int(buy_temp * 0.04)) # 4
buy_ea.append(int(buy_temp * 0.05)) # 9
buy_ea.append(int(buy_temp * 0.07)) # 16
buy_ea.append(int(buy_temp * 0.09)) # 25
buy_ea.append(int(buy_temp * 0.11)) # 36
buy_ea.append(int(buy_temp * 0.13)) # 49
buy_ea.append(int(buy_temp * 0.15)) # 64
buy_ea.append(int(buy_temp * 0.17)) # 81
buy_ea.append(int(buy_temp * 0.19)) # 90
buy_ea.append(int(buy_temp * 0.10)) # 100
이렇게 계산되어 주문을 한다.
실투에 주문을 해보면 잘된다.
import sys import os import time #import logging.conf from PyQt5.QtWidgets import * from PyQt5.QAxContainer import * from PyQt5.QtCore import * from beautifultable import BeautifulTable from PyQt5.QtTest import * from pandas import DataFrame TR_REQ_TIME_INTERVAL = 0.2 class Kiwoom(QAxWidget): def __init__(self): self.app = QApplication(sys.argv) print("Ui_class 입니다.") super().__init__() # 이벤트 루프 관련 변수 self.login_event_loop = QEventLoop() self.account_event_loop = QEventLoop() self.calculator_event_loop = QEventLoop() # 계좌 관련 변수 self.account_number = None self.total_buy_money = None self.total_evaluation_money = None self.total_evaluation_profit_and_loss_money = None self.total_yield = None self.account_stock_dict = {} self.not_signed_account_dict = {} self.bunhal_stock_dict = {} self.hoga_stock_dict = {} # 예수금 관련 변수 self.deposit = None self.withdraw_deposit = None self.order_deposit = None # 종목 분석 관련 변수 self.calculator_list = [] # 화면 번호 self.screen_my_account = "1000" self.screen_calculation_stock = "2000" # 초기 작업 print("로그인-초기작업시작") self.create_kiwoom_instance() self.event_collection() # 이벤트와 슬롯을 메모리에 먼저 생성. self.login() print("계좌정보시작") # input() # self.get_account_info() # 계좌 번호만 얻어오기 self.get_account_evaluation_balance() # 계좌평가잔고내역 얻어오기 ###########[스케쥴링]############ ### [self.item_codes 끝에 허수종목을 하나 넣어줘야함. 뭐가 잘못된건지 감 안옴.] ### self.item_codes = "002200","008420","008420" self.buying_split() # 현재가 가격알아보기 print("현재가 가격알아보기", self.bunhal_stock_dict) self.hoga_list() # 매수호가 가격알아보기 print("매수호가 가격알아보기",self.hoga_stock_dict) self.buying_run() # 매수진행 ###########[스케쥴링]############ # self.get_deposit_info() # 예수금 관련된 정보 얻어오기 # self.not_signed_account() # 미체결내역 얻어오기 def hoga_list(self): # 매수할 종목의 매수호가 1~10 담기 self.hoga = list(self.bunhal_stock_dict.keys()) print(self.hoga) for i in range(0, len(self.item_codes)): self.for_hoga_index = i self.item_code = self.item_codes[i] time.sleep(0.3) #print(self.hoga[self.for_hoga_index]) self.trcode_hoga() def buying_split(self): # 종목명과 현재가 담기 for iii in range(0,len(self.item_codes)): self.item_code = self.item_codes[iii] self.for_buying_index = iii time.sleep(0.3) self.trcode_closem() def buying_run(self): self.hoga_x = list(self.hoga_stock_dict.keys()) self.hoga_name=['매수최우선호가','매수2차선호가','매수3차선호가','매수4차선호가','매수5차선호가','매수6우선호가','매수7차선호가','매수8차선호가','매수9차선호가','매수10차선호가'] #for index, keys in enumerate(self.hoga_x): for iiiiii in range(0, len(self.hoga_x)): hoga_temp = self.hoga_stock_dict[self.hoga_x[iiiiii]] delay_time = 0.37 buyprice = 1000000 buytemp = self.bunhal_stock_dict[self.hoga_x[iiiiii]]['현재가'] #종목현재가 buy_temp = int(int(buyprice) / int(buytemp)) buy_ea = [] buy_ea.append(int(buy_temp * 0.04)) # 4 buy_ea.append(int(buy_temp * 0.05)) # 9 buy_ea.append(int(buy_temp * 0.07)) # 16 buy_ea.append(int(buy_temp * 0.09)) # 25 buy_ea.append(int(buy_temp * 0.11)) # 36 buy_ea.append(int(buy_temp * 0.13)) # 49 buy_ea.append(int(buy_temp * 0.15)) # 64 buy_ea.append(int(buy_temp * 0.17)) # 81 buy_ea.append(int(buy_temp * 0.19)) # 90 buy_ea.append(int(buy_temp * 0.10)) # 100 print("총수량:[%s] 분할매수수량:[%s]" % (buy_temp,buy_ea)) hopi=hoga_temp[self.hoga_name[(0)]] if buy_ea[0] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[0], hopi, "00","") print("1호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[0])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(1)]] if buy_ea[1] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[1], hopi, "00","") print("2호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[1])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(2)]] if buy_ea[2] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[2], hopi, "00","") print("3호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[2])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(3)]] if buy_ea[3] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[3], hopi, "00","") print("4호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[3])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(4)]] if buy_ea[4] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[4], hopi, "00","") print("5호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[4])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(5)]] if buy_ea[5] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[5], hopi, "00","") print("6호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[5])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(6)]] if buy_ea[6] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[6], hopi, "00","") print("7호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[6])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(7)]] if buy_ea[7] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[7], hopi, "00","") print("8호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[7])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(8)]] if buy_ea[8] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[8], hopi, "00","") print("9호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[8])) time.sleep(delay_time) hopi=hoga_temp[self.hoga_name[(9)]] if buy_ea[9] != 0: self.send_order("buy", "0101", self.account_number, 1, self.hoga_x[iiiiii], buy_ea[9], hopi, "00","") print("10호가 %s 에 %s개 매수주문 완료." % (hopi,buy_ea[9])) time.sleep(delay_time) def _event_connect(self, err_code): if err_code == 0: print("connected") else: print("disconnected") self.login_event_loop.exit() def _get_repeat_cnt(self, sTrCode, sRQName): ret = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName) return ret ################################################## # COM 오브젝트 생성. def create_kiwoom_instance(self): # 레지스트리에 저장된 키움 openAPI 모듈 불러오기 self.setControl("KHOPENAPI.KHOpenAPICtrl.1") def event_collection(self): self.OnEventConnect.connect(self.login_slot) # 로그인 관련 이벤트 self.OnReceiveTrData.connect(self.tr_slot) # 트랜잭션 요청 관련 이벤트 def login(self): self.dynamicCall("CommConnect()") # 시그널 함수 호출. self.login_event_loop.exec_() def login_slot(self, err_code): if err_code == 0: print("로그인에 성공하였습니다.") else: os.system('cls') print("에러 내용 :", errors(err_code)[1]) sys.exit(0) self.login_event_loop.exit() def get_account_info(self): account_list = self.dynamicCall("GetLoginInfo(QString)", "ACCNO") account_number = account_list.split(';')[0] self.account_number = account_number def menu(self): sel = "" while True: os.system('cls') print("1. 현재 로그인 상태 확인") print("2. 사용자 정보 조회") print("3. 예수금 조회") print("4. 계좌 잔고 조회") print("5. 미체결 내역 조회") print("Q. 프로그램 종료") sel = input("=> ") if sel == "Q" or sel == "q": sys.exit(0) if sel == "1": self.print_login_connect_state() elif sel == "2": self.print_my_info() elif sel == "3": self.print_get_deposit_info() elif sel == "4": self.print_get_account_evaulation_balance_info() elif sel == "5": self.print_not_signed_account() def print_login_connect_state(self): os.system('cls') isLogin = self.dynamicCall("GetConnectState()") if isLogin == 1: print("\n현재 계정은 로그인 상태입니다.") else: print("\n현재 계정은 로그아웃 상태입니다.") input() def print_my_info(self): os.system('cls') user_name = self.dynamicCall("GetLoginInfo(QString)", "USER_NAME") user_id = self.dynamicCall("GetLoginInfo(QString)", "USER_ID") account_count = self.dynamicCall( "GetLoginInfo(QString)", "ACCOUNT_CNT") print(f"\n이름 : {user_name}") print(f"ID : {user_id}") print(f"보유 계좌 수 : {account_count}") print(f"계좌번호 : {self.account_number}") input() def print_get_deposit_info(self): os.system('cls') print(f"\n예수금 : {self.deposit}원") print(f"출금 가능 금액 : {self.withdraw_deposit}원") print(f"주문 가능 금액 : {self.order_deposit}원") input() def print_get_account_evaulation_balance_info(self): os.system('cls') print("\n<싱글 데이터>") print(f"총 매입 금액 : {self.total_buy_money}원") print(f"총 평가 금액 : {self.total_evaluation_money}원") print(f"총 평가 손익 금액 : {self.total_evaluation_profit_and_loss_money}원") print(f"총 수익률 : {self.total_yield}%\n") table = self.make_table("계좌평가잔고내역요청") print("<멀티 데이터>") if len(self.account_stock_dict) == 0: print("보유한 종목이 없습니다!") else: print(f"보유 종목 수 : {len(self.account_stock_dict)}개") print(table) input() def make_table(self, sRQName): table = BeautifulTable() table = BeautifulTable(maxwidth=150) if sRQName == "계좌평가잔고내역요청": for stock_code in self.account_stock_dict: stock = self.account_stock_dict[stock_code] stockList = [] for key in stock: output = None if key == "종목명": output = stock[key] elif key == "수익률(%)": output = str(stock[key]) + "%" elif key == "보유수량" or key == "매매가능수량": output = str(stock[key]) + "개" else: output = str(stock[key]) + "원" stockList.append(output) table.rows.append(stockList) table.columns.header = ["종목명", "평가손익", "수익률", "매입가", "보유수량", "매매가능수량", "현재가"] table.rows.sort('종목명') elif sRQName == "실시간미체결요청": for stock_order_number in self.not_signed_account_dict: stock = self.not_signed_account_dict[stock_order_number] stockList = [stock_order_number] for key in stock: output = None if key == "주문가격" or key == "현재가": output = str(stock[key]) + "원" elif '량' in key: output = str(stock[key]) + "개" elif key == "종목코드": continue else: output = stock[key] stockList.append(output) table.rows.append(stockList) table.columns.header = ["주문번호", "종목명", "주문구분", "주문가격", "주문수량", "미체결수량", "체결량", "현재가", "주문상태"] table.rows.sort('주문번호') return table def print_not_signed_account(self): os.system('cls') print() table = self.make_table("실시간미체결요청") if len(self.not_signed_account_dict) == 0: print("미체결 내역이 없습니다!") else: print(table) input() def get_deposit_info(self, nPrevNext=0): self.dynamicCall("SetInputValue(QString, QString)", "계좌번호", self.account_number) self.dynamicCall("SetInputValue(QString, QString)", "비밀번호", " ") self.dynamicCall("SetInputValue(QString, QString)", "비밀번호입력매체구분", "00") self.dynamicCall("SetInputValue(QString, QString)", "조회구분", "2") self.dynamicCall("CommRqData(QString, QString, int, QString)", "예수금상세현황요청", "opw00001", nPrevNext, self.screen_my_account) self.account_event_loop.exec_() def get_account_evaluation_balance(self, nPrevNext=0): self.dynamicCall("SetInputValue(QString, QString)", "계좌번호", self.account_number) self.dynamicCall("SetInputValue(QString, QString)", "비밀번호", " ") self.dynamicCall("SetInputValue(QString, QString)", "비밀번호입력매체구분", "00") self.dynamicCall("SetInputValue(QString, QString)", "조회구분", "1") self.dynamicCall("CommRqData(QString, QString, int, QString)", "계좌평가잔고내역요청", "opw00018", nPrevNext, self.screen_my_account) if not self.account_event_loop.isRunning(): self.account_event_loop.exec_() def not_signed_account(self, nPrevNext=0): self.dynamicCall("SetInputValue(QString, QString)", "계좌번호", self.account_number) self.dynamicCall("SetInputValue(QString, QString)", "전체종목구분", "0") self.dynamicCall("SetInputValue(QString, QString)", "매매구분", "0") self.dynamicCall("SetInputValue(QString, QString)", "체결구분", "1") self.dynamicCall("CommRqData(QString, QString, int, QString)", "실시간미체결요청", "opt10075", nPrevNext, self.screen_my_account) if not self.account_event_loop.isRunning(): self.account_event_loop.exec_() # 수신 메시지 이벤트 def OnReceiveMsg(self, scrNo, rQName, trCode, msg): print('_OnReceiveMsg()', scrNo, rQName, trCode, msg) def send_order(self, rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no): self.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)", [rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no]) def trcode_buy(self,sPrevNext="0"): ##현재가로 피라미드 0~4까지 매수 self.dynamicCall("SetInputValue(QString, QString)", "종목코드", self.item_num) self.dynamicCall("CommRqData(QString, QString, int, QString)", "buy", "opt10001", sPrevNext, "2000") print("현재가요청 서버 전송 완료") def trcode_buy04(self,sPrevNext="0"): ##현재가로 피라미드 0~4까지 매수 self.dynamicCall("SetInputValue(QString, QString)", "종목코드", self.item_num) self.dynamicCall("CommRqData(QString, QString, int, QString)", "buy04", "opt10001", sPrevNext, "2000") print("현재가요청 서버 전송 완료") def trcode_closem(self,sPrevNext="0"): # 종목현재가 self.dynamicCall("SetInputValue(QString, QString)", "종목코드", self.item_code) self.dynamicCall("CommRqData(QString, QString, int, QString)", "종목현재가", "opt10001", sPrevNext, "2001") # 이부분 활성화시키면 for문을 두번세번네번 계속 반복시킴. self.OnReceiveTrData.connect(self.tr_slot) # 트랜잭션 요청 관련 이벤트 print("현재가요청 서버>>>전송") def trcode_hoga(self,sPrevNext="0"): # 종목호가 print(type(self.item_code),self.item_code) self.dynamicCall("SetInputValue(QString, QString)", "종목코드", self.item_code) self.dynamicCall("CommRqData(QString, QString, int, QString)", "종목호가", "opt10004", sPrevNext, "2001") # 이부분 활성화시키면 for문을 두번세번네번 계속 반복시킴. self.OnReceiveTrData.connect(self.tr_slot) # 트랜잭션 요청 관련 이벤트 print("매수호가요청 서버>>>전송") def tr_slot(self, sScrNo, sRQName, sTrCode, sRecordName, sPrevNext): print("tr_slot 수신코드로 진입했습니다.") if sRQName == "종목현재가": tp = {} stock_cd = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드") stock_nn = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목명") stock_np = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "현재가") stock_tv = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "거래량") stock_cd = stock_cd.strip().replace("+", "").replace("-", "").replace(" ", "") stock_nn = stock_nn.strip().replace("+","").replace("-","").replace(" ","") stock_np = stock_np.strip().replace("+","").replace("-","").replace(" ","") stock_tv = stock_tv.strip().replace("+", "").replace("-", "").replace(" ", "") tp.update({"종목코드":stock_cd,"종목명":stock_nn,"현재가":stock_np,"거래량":stock_tv}) print(tp) self.bunhal_stock_dict.update({stock_cd :tp}) print("[%s][%s][%s]종목의 현재가격은 [%s],거래량은 [%s]입니다." % (self.for_buying_index,stock_nn,stock_cd,stock_np,stock_tv)) elif sRQName == "종목테스트": stock_cd = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드") print(hoga_temp,stock_cd) elif sRQName == "종목호가": tp ={} for ii in range(0,10): if ii == 0 : hoga_name = "매수최우선호가" elif ii == 5: hoga_name = "매수6우선호가" else: hoga_name = "매수"+str(ii+1)+"차선호가" # 최우선호가 이후 1차선호가가 없고 2차선호가부터 시작하여 i+1로 해야 정상사용됨. hoga_temp = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, hoga_name) hoga_temp = hoga_temp.strip().replace("+","").replace("-","").replace(" ","") print("종목코드:",self.item_code,type(hoga_temp),"호가:",hoga_temp) tp.update({hoga_name :hoga_temp}) # 1~10호가 모으기 print("[%s][%s]종목코드,셀프종목코드:%s" % (self.for_hoga_index,list(self.bunhal_stock_dict.keys())[(self.for_hoga_index-1)],self.item_code)) print(len(self.item_codes),self.for_hoga_index) if 34 < self.for_hoga_index: print("끝날때가 됬쥬?") #self.hoga_stock_dict.update({list(self.bunhal_stock_dict.keys())[(self.for_hoga_index-1)] : tp}) # 종목코드가 데이터보다 이전배열코드로 문제가 발생됨. # 종목과 모아둔 호가 넣기 else: self.hoga_stock_dict.update({list(self.bunhal_stock_dict.keys())[( self.for_hoga_index - 1)]: tp}) # 종목코드가 데이터보다 이전배열코드로 문제가 발생됨. # 종목과 모아둔 호가 넣기 print("종목 호가리스트 담기성공") if sRQName == "buy": print("buy 잘 전달했겠죠?") if sRQName == "buy04": print("잘 전달했겠죠?") if sRQName == "sell_auto_Order": #self.OnReceiveMsg() print("sell_auto_Order >>> 잘 전달했겠죠?") ####################[현재가 확인후 피라미드 매수 0~4번] if sRQName == "buy59": print("현재가피라미드매수-buy59 %s", self.item_num) ####################[현재가 확인후 피라미드 매도 0~4번] if sRQName == "sell04": print("현재가피라미드매도-sell04 %s",self.item_num) ####################[현재가 확인후 피라미드 매도 5~9번] if sRQName == "sell59": print("현재가피라미드매도-sell59 시작! %s" % self.item_num) if sRQName == "예수금상세현황요청": deposit = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "예수금") self.deposit = int(deposit) withdraw_deposit = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "출금가능금액") self.withdraw_deposit = int(withdraw_deposit) order_deposit = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "주문가능금액") self.order_deposit = int(order_deposit) self.cancel_screen_number(self.screen_my_account) self.account_event_loop.exit() elif sRQName == "계좌평가잔고내역요청": if (self.total_buy_money == None or self.total_evaluation_money == None or self.total_evaluation_profit_and_loss_money == None or self.total_yield == None): total_buy_money = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총매입금액") self.total_buy_money = int(total_buy_money) total_evaluation_money = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총평가금액") self.total_evaluation_money = int(total_evaluation_money) total_evaluation_profit_and_loss_money = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총평가손익금액") self.total_evaluation_profit_and_loss_money = int( total_evaluation_profit_and_loss_money) total_yield = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "총수익률(%)") self.total_yield = float(total_yield) cnt = self.dynamicCall( "GetRepeatCnt(QString, QString)", sTrCode, sRQName) for i in range(cnt): stock_code = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목번호") stock_code = stock_code.strip()[1:] stock_name = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명") stock_name = stock_name.strip() # 필요 없는 공백 제거. stock_evaluation_profit_and_loss = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "평가손익") stock_evaluation_profit_and_loss = int( stock_evaluation_profit_and_loss) stock_yield = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "수익률(%)") stock_yield = float(stock_yield)/100 stock_buy_money = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매입가") stock_buy_money = int(stock_buy_money) stock_quantity = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "보유수량") stock_quantity = int(stock_quantity) stock_trade_quantity = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매매가능수량") stock_trade_quantity = int(stock_trade_quantity) stock_present_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") stock_present_price = int(stock_present_price) if not stock_code in self.account_stock_dict: self.account_stock_dict[stock_code] = {} self.account_stock_dict[stock_code].update({'종목명': stock_name}) self.account_stock_dict[stock_code].update( {'평가손익': stock_evaluation_profit_and_loss}) self.account_stock_dict[stock_code].update( {'수익률(%)': stock_yield}) self.account_stock_dict[stock_code].update( {'매입가': stock_buy_money}) self.account_stock_dict[stock_code].update( {'보유수량': stock_quantity}) self.account_stock_dict[stock_code].update( {'매매가능수량': stock_trade_quantity}) self.account_stock_dict[stock_code].update( {'현재가': stock_present_price}) if sPrevNext == "2": self.get_account_evaluation_balance(2) else: self.cancel_screen_number(self.screen_my_account) self.account_event_loop.exit() elif sRQName == "실시간미체결요청": cnt = self.dynamicCall( "GetRepeatCnt(QString, QString)", sTrCode, sRQName) for i in range(cnt): stock_code = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목코드") stock_code = stock_code.strip() stock_order_number = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문번호") stock_order_number = int(stock_order_number) stock_name = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명") stock_name = stock_name.strip() stock_order_type = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문구분") stock_order_type = stock_order_type.strip().lstrip('+').lstrip('-') stock_order_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문가격") stock_order_price = int(stock_order_price) stock_order_quantity = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문수량") stock_order_quantity = int(stock_order_quantity) stock_not_signed_quantity = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "미체결수량") stock_not_signed_quantity = int(stock_not_signed_quantity) stock_signed_quantity = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "체결량") stock_signed_quantity = int(stock_signed_quantity) stock_present_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") stock_present_price = int( stock_present_price.strip().lstrip('+').lstrip('-')) stock_order_status = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문상태") stock_order_status = stock_order_status.strip() if not stock_order_number in self.not_signed_account_dict: self.not_signed_account_dict[stock_order_number] = {} self.not_signed_account_dict[stock_order_number].update( {'종목코드': stock_code}) self.not_signed_account_dict[stock_order_number].update( {'종목명': stock_name}) self.not_signed_account_dict[stock_order_number].update( {'주문구분': stock_order_type}) self.not_signed_account_dict[stock_order_number].update( {'주문가격': stock_order_price}) self.not_signed_account_dict[stock_order_number].update( {'주문수량': stock_order_quantity}) self.not_signed_account_dict[stock_order_number].update( {'미체결수량': stock_not_signed_quantity}) self.not_signed_account_dict[stock_order_number].update( {'체결량': stock_signed_quantity}) self.not_signed_account_dict[stock_order_number].update( {'현재가': stock_present_price}) self.not_signed_account_dict[stock_order_number].update( {'주문상태': stock_order_status}) if sPrevNext == "2": self.not_signed_account(2) else: self.cancel_screen_number(sScrNo) self.account_event_loop.exit() elif sRQName == "주식일봉차트조회요청": stock_code = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드") #six_hundred_data = self.dynamicCall("GetCommDataEx(QString, QString)", sTrCode, sRQName) stock_code = stock_code.strip() cnt = self.dynamicCall( "GetRepeatCnt(QString, QString)", sTrCode, sRQName) # 최대 600일 for i in range(cnt): calculator_list = [] current_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가") volume = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래량") trade_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "거래대금") date = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "일자") start_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "시가") high_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "고가") low_price = self.dynamicCall( "GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "저가") calculator_list.append("") calculator_list.append(int(current_price)) calculator_list.append(int(volume)) calculator_list.append(int(trade_price)) calculator_list.append(int(date)) calculator_list.append(int(start_price)) calculator_list.append(int(high_price)) calculator_list.append(int(low_price)) calculator_list.append("") self.calculator_list.append(calculator_list.copy()) if sPrevNext == "2": self.day_kiwoom_db(stock_code, None, 2) else: self.calculator_event_loop.exit() def cancel_screen_number(self, sScrNo): self.dynamicCall("DisconnectRealData(QString)", sScrNo) def get_code_list_by_market(self, market_code): code_list = self.dynamicCall( "GetCodeListByMarket(QString)", market_code) code_list = code_list.split(";")[:-1] return code_list def calculator(self): kosdaq_list = self.get_code_list_by_market("10") for idx, stock_code in enumerate(kosdaq_list): self.dynamicCall("DisconnectRealData(QString)", self.screen_calculation_stock) print( f"{idx + 1} / {len(kosdaq_list)} : KOSDAQ Stock Code : {stock_code} is updating...") self.day_kiwoom_db(stock_code) def day_kiwoom_db(self, stock_code=None, date=None, nPrevNext=0): QTest.qWait(3600) # 3.6초마다 딜레이 self.dynamicCall("SetInputValue(QString, QString)", "종목코드", stock_code) self.dynamicCall("SetInputValue(QString, QString)", "수정주가구분", 1) if date != None: # date가 None일 경우 date는 오늘 날짜 기준 self.dynamicCall("SetInputValue(QString, QString)", "기준일자", date) self.dynamicCall("CommRqData(QString, QString, int, QString)", "주식일봉차트조회요청", "opt10081", nPrevNext, self.screen_calculation_stock) if not self.calculator_event_loop.isRunning(): self.calculator_event_loop.exec_() def errors(err_code): err_dic = {0: ('OP_ERR_NONE', '정상처리'), -10: ('OP_ERR_FAIL', '실패'), -100: ('OP_ERR_LOGIN', '사용자정보교환실패'), -101: ('OP_ERR_CONNECT', '서버접속실패'), -102: ('OP_ERR_VERSION', '버전처리실패'), -103: ('OP_ERR_FIREWALL', '개인방화벽실패'), -104: ('OP_ERR_MEMORY', '메모리보호실패'), -105: ('OP_ERR_INPUT', '함수입력값오류'), -106: ('OP_ERR_SOCKET_CLOSED', '통신연결종료'), -200: ('OP_ERR_SISE_OVERFLOW', '시세조회과부하'), -201: ('OP_ERR_RQ_STRUCT_FAIL', '전문작성초기화실패'), -202: ('OP_ERR_RQ_STRING_FAIL', '전문작성입력값오류'), -203: ('OP_ERR_NO_DATA', '데이터없음'), -204: ('OP_ERR_OVER_MAX_DATA', '조회가능한종목수초과'), -205: ('OP_ERR_DATA_RCV_FAIL', '데이터수신실패'), -206: ('OP_ERR_OVER_MAX_FID', '조회가능한FID수초과'), -207: ('OP_ERR_REAL_CANCEL', '실시간해제오류'), -300: ('OP_ERR_ORD_WRONG_INPUT', '입력값오류'), -301: ('OP_ERR_ORD_WRONG_ACCTNO', '계좌비밀번호없음'), -302: ('OP_ERR_OTHER_ACC_USE', '타인계좌사용오류'), -303: ('OP_ERR_MIS_2BILL_EXC', '주문가격이20억원을초과'), -304: ('OP_ERR_MIS_5BILL_EXC', '주문가격이50억원을초과'), -305: ('OP_ERR_MIS_1PER_EXC', '주문수량이총발행주수의1 % 초과오류'), -306: ('OP_ERR_MIS_3PER_EXC', '주문수량은총발행주수의3 % 초과오류'), -307: ('OP_ERR_SEND_FAIL', '주문전송실패'), -308: ('OP_ERR_ORD_OVERFLOW', '주문전송과부하'), -309: ('OP_ERR_MIS_300CNT_EXC', '주문수량300계약초과'), -310: ('OP_ERR_MIS_500CNT_EXC', '주문수량500계약초과'), -340: ('OP_ERR_ORD_WRONG_ACCTINFO', '계좌정보없음'), -500: ('OP_ERR_ORD_SYMCODE_EMPTY', '종목코드없음') } result = err_dic[err_code] return result class KiwoomProcessingError(Exception): """ 키움에서 처리실패에 관련된 리턴코드를 받았을 경우 발생하는 예외 """ def __init__(self, msg="처리 실패"): # self.msg = msg print(msg) def __str__(self): return self.msg def __repr__(self): return self.msg ######################## 시작 if __name__=="__main__": kiwoom = Kiwoom()