50강에서는 실시간 체결 정보를 받아왔습니다. 받아온 데이터를 어딘가에는 저장 및 전시를 해야겠죠? 이번 강의에서는 싱글턴 스크립트 및 GUI에 관련 정보를 저장/전시하는 코딩을 해보겠습니다.
[유튜브 강의, 링크]와 같이 보시면 많은 도움이 되실 겁니다.
1. 실시간 체결 정보 저장
아래 그림과 같이 메타클레스 싱글턴 스크립트에 self.not_account_stock_dict라는 딕셔너리를 만들어 실시간 체결 정보를 저장할 방을 만듭니다.
방을 만들었으면, QThread_3 스크립트로 넘어오셔서 50강에 이어 아래 그림과 같은 코드를 작성합니다.
우선 self.not_account_stock_dict에 키 값으로 order_number를 저장합니다. 이전 self.portfolio_stock_dict에서는 키 값으로 종목 코드를 넣어 구분하였는데 체결 정보 구분 값으로는 order_number가 됩니다. 체결될 때마다 order_number가 넘어오니 우선 아래와 같이 self.not_account_stock_dict에 관련 값을 넣도록 합니다.
- if order_number not in self.k.not_account_stock_dict.keys() : not_account_stock_dict에 order_number라는 키값이 없으면 키 값을 아래와 같이 만들어 줍니다.
- self.k.not_account_stock_dict.update({order_number: {}}) : not_account_stock_dict에 order_number라는 키값 아래 {}라는 딕셔너리를 생성합니다. 앞으로 이 {} 딕셔너리에 원하는 값을 넣도록 하겠습니다.
KOA Studio를 기반으로 체결정보는 50강에서 설명드렸듯이 종목코드부터 (최우선) 매도호가까지 가져올 수 있습니다. 자 그러면 저희가 받아온 정보를 하나하나 다 not_account_stock_dict에 저장해야 겠죠?
- self.k.not_account_stock_dict[order_number].update({"종목코드": sCode}) : not_account_stock_dict에 저장된 order_number에 종목코드를 업데이트합니다.
위와 동일하게 (최우선)매도호가까지 다 저장하도록 합시다. 앞으로 어디서든 현재 미체결 잔고를 확인하기 위해서는 not_account_stock_dict를 살펴보면 됩니다. 여기까지는 개발자의 시각이고, 이제 누구든 미체결 잔고 내역을 확인할 수 있어야겠죠? 그러기 위해서는 앞서 많이 설명드린 TableWidget을 만들어 넣어 볼까요?
2. GUI 생성 및 관련 정보 저장
우선 저번에 만들어 놓은 stocklistTableWidget_2 자리에 Tab Widget을 만들어 2개의 탭을 구성합니다. 그리고 currentTabText에 자신이 구분할 수 있는 이름을 적습니다. 저는 계좌 내역과 미체결 잔고라 구분했습니다. 그러면 계좌 내역 안에는 stocklistTableWidget_2을 집어넣고 미체결 잔고에는 새로운 QTableWidget을 집어넣도록 하겠습니다.
그리고 아래와 같이 QTableWidget을 삽입합니다. objectName은 not_account라 하였습니다.
다시 QThread_3로 넘어와 관련 정보들을 QTableWidget에 넣는 코딩을 해 줍니다. 이 부분은 너무 많이 진행하였으니 링크를 걸어 드리겠습니다. 22강 멀티 데이터 QTableWidget에 삽입하기 링크를 확인하세요.
그래도 설명은 간략하게 드리겠습니다.
- colum_head : 열의 개수를 정하며, 관련 데이터의 뜻을 이해하기 위해 반드시 넣으셔야 됩니다. 대략 6개만 샘플로 넣도록 하겠습니다. 본인이 원하는 값을 넣을 수 있으니 바꾸셔도 전혀 무방합니다.
- colCount : 열의 개수이니 colum_head의 길이를 구하시면 되겠죠?
- rowCount : 행의 개수이니 not_account_stock_dict에 들어 있는 종목의 수를 구하시면 되겠죠?
- setColumCount(colCount) : 열의 개수를 세팅 합니다.
- setRowCount(rowCount) : 행의 개수를 세팅합니다.
- setHorizontalHeaderLabels(colum_head) : colum_head를 세팅합니다.
- for index in range(rowCount) : 행의(종목의) 개수만큼 하나씩 index에 들어갑니다.
- self.parent.not_account.setItem(index, 0, QTableWidgetItem(str(sCode))) : 우리가 만든 not_account TableWidget에 저장된 값을 삽입니다. index행에 0열, 1열, 2열... 6열까지 원하는 값을 QTableWidgetItem함수를 사용해서 넣도록 합니다.
3. 요약 및 코드 공개
이번 강의는 미체결 잔고 내역에 대한 다양한 정보를 싱글턴 기반 스크립트의 not_account_stock_dict에 저장하거나 GUI를 생성하여 관련 값을 삽입하는 것을 배워 보았습니다. 다음 강의에서는 미체결에서 체결되었을 때 관련 정보를 가져와 보겠습니다. 대략 4강 정도만 더하면 기본 편은 끝날 것 같습니다. 이것만 끝나면 여러분들은 날개를 다시고 무엇이든 만드실 수 있을 것입니다. 감사합니다.
import os # 현재 디렉토리 확인 기능
from PyQt5.QtCore import * # 쓰레드 함수를 불러온다.
from kiwoom import Kiwoom # 로그인을 위한 클래스
from kiwoomType import *
from PyQt5.QtWidgets import * #PyQt import
class Thread3(QThread):
def __init__(self, parent): # 부모의 윈도우 창을 가져올 수 있다.
super().__init__(parent) # 부모의 윈도우 창을 초기화 한다.
self.parent = parent # 부모의 윈도우를 사용하기 위한 조건
################## 키움서버 함수를 사용하기 위해서 kiwoom의 능력을 상속 받는다.
self.k = Kiwoom()
##################
################## 사용되는 변수
account = self.parent.accComboBox.currentText() # 콤보박스 안에서 가져오는 부분
self.account_num = account
# 계좌번호 가져오는 부분은 Qthread_3 분리 시 로그인 후 계좌번호를 가져오는 함수로 교체된다. Lecture_0529.py
################# 매수관련 변수
self.Load_code() # 매수 종목/금액/수량 가져오기
self.orderitmelist_1 = [] # 중복 매수 금지
self.orderitmelist_2 = [] # 중복 익절 금지
self.orderitmelist_3 = [] # 중복 손절 금지
self.orderitmelist_4 = [] # 중복 재매수 금지
self.cancel_the_order = []
####### 주문 전송 시 필요한 FID 번호
self.realType = RealType() # 실시간 FID 번호를 모아두는 곳
######################################################################
###### 등록된 계좌 전체 해제하기(작동 정지 되었을 때 등록 정보를 다 끊어야 한다.)
self.k.kiwoom.dynamicCall("SetRealRemove(QString, QString)", ["ALL", "ALL"])
######################################################################
######################################################################
###### 선정된 종목 등록하기 : 키움서버에 리얼 데이터 등록하기
self.screen_num = 5000
for code in self.k.portfolio_stock_dict.keys(): # 포트폴리오에 저장된 코드들을 실시간 등록
fids = self.realType.REALTYPE['주식체결']['체결시간'] # 주식체결에 대한 모든 데이터를 로드할 수 있다.
self.k.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", self.screen_num, code, fids, "1") # 실시간 데이터를 받아오기 위해 각 코드들을 서버에 등록(틱 변화가 있으면 데이터 송신)
self.screen_num += 1
# print("실시간 등록 : %s, 스크린번호 : %s, FID 번호 : %s" % (code, screen_num, fids))
print("종목등록 완료")
print(self.k.portfolio_stock_dict.keys())
######################################################################
###### 현재 장 상태 알아보기 (장 시작 / 장 마감 등)
self.screen_start_stop_real = "300" # 장시 시작 전/후 상태 확인용 스크린 번호
self.k.kiwoom.dynamicCall("SetRealReg(QString, QString, QString, QString)", self.screen_start_stop_real, '', self.realType.REALTYPE['장시작시간']['장운영구분'], "0") # 장의 시작인지, 장 외인지등에 대한 정보 수신
###### 실시간 슬롯 (데이터를 받아오는 슬롯을 설정한다)
self.k.kiwoom.OnReceiveRealData.connect(self.realdata_slot) # 실시간 데이터를 받아오는 곳
self.k.kiwoom.OnReceiveChejanData.connect(self.chejan_slot) # (주문접수, 체결통보)=0, (잔고변경) = 1 데이터 전송
def Load_code(self):
if os.path.exists("dist/Selected_code.txt"):
f = open("dist/Selected_code.txt", "r", encoding="utf8")
lines = f.readlines() # 여러 종목이 저장되어 있다면 모든 항목을 가져온다.
screen = 4000
for line in lines:
if line != "": # 만약에 line이 비어 있지 않다면
ls = line.split("\t") # \t(tap)로 구분을 지어 놓는다.
t_code = ls[0]
t_name = ls[1]
curren_price = ls[2]
dept = ls[3]
mesu = ls[4]
n_o_stock = ls[5]
profit = ls[6]
loss = ls[7].split("\n")[0]
self.k.portfolio_stock_dict.update({t_code: {"종목명": t_name}})
self.k.portfolio_stock_dict[t_code].update({"현재가": int(curren_price)})
self.k.portfolio_stock_dict[t_code].update({"신용비율": dept})
self.k.portfolio_stock_dict[t_code].update({"매수가": int(mesu)})
self.k.portfolio_stock_dict[t_code].update({"매수수량": int(n_o_stock)})
self.k.portfolio_stock_dict[t_code].update({"익절가": int(profit)})
self.k.portfolio_stock_dict[t_code].update({"손절가": int(loss)})
self.k.portfolio_stock_dict[t_code].update({"주문용스크린번호": screen}) # 아래 내용을 업데이트
screen += 1
f.close()
def realdata_slot(self, sCode, sRealType, sRealData): # 실시간으로 서버에서 데이터들이 날라온다.
if sRealType == "장시작시간":
fid = self.realType.REALTYPE[sRealType]['장운영구분']
# 실시간시세 데이터 수신 이벤트인 OnReceiveRealData() 가 발생될때 실시간데이터를 얻어오는 함수
value = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid)
if value == '0':
print("장 시작 전")
elif value == '3':
print("장 시작")
elif value == '2':
print("장 종료, 동시호가로 넘어감감")
elif value == '4':
print("장 마감했습니다.")
elif sRealType == "주식체결" and sCode in self.k.portfolio_stock_dict:
fid1 = self.realType.REALTYPE[sRealType]['체결시간'] # 체결시간은 string으로 나온다. HHMMSS
a = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid1)
fid2 = self.realType.REALTYPE[sRealType]['현재가'] # 현재가는 +/-로 나온다.
b = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid2)
b = abs(int(b))
fid3 = self.realType.REALTYPE[sRealType]['전일대비'] # 전달 대비 오르거나/내린 가격
c = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid3)
c = abs(int(c))
fid4 = self.realType.REALTYPE[sRealType]['등락율'] # 전달 대비 오르거나/내린 퍼센테이지
d = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid4)
d = float(d)
fid5 = self.realType.REALTYPE[sRealType]['(최우선)매도호가'] # 매도쪽에 첫번재 부분(시장가)
e = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid5)
e = abs(int(e))
fid6 = self.realType.REALTYPE[sRealType]['(최우선)매수호가'] # 매수쪽에 첫번재 부분(시장가)
f = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid6)
f = abs(int(f))
fid7 = self.realType.REALTYPE[sRealType]['거래량'] # 틱봉의 현재 거래량 (아주 작으 단위)
g = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid7)
g = abs(int(g))
fid8 = self.realType.REALTYPE[sRealType]['누적거래량']
h = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid8)
h = abs(int(h))
fid9 = self.realType.REALTYPE[sRealType]['고가'] # 오늘자 재일 높은 가격
i = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid9)
i = abs(int(i))
fid10 = self.realType.REALTYPE[sRealType]['시가'] # 시가
j = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid10)
j = abs(int(j))
fid11 = self.realType.REALTYPE[sRealType]['저가'] # 전체 재일 낮은 가격
k = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid11)
k = abs(int(k))
fid12 = self.realType.REALTYPE[sRealType]['거래회전율'] # 누적 거래회전율
l = self.k.kiwoom.dynamicCall("GetCommRealData(QString, int)", sCode, fid12)
l = abs(float(l))
if sCode not in self.k.portfolio_stock_dict: # 만약 서버에 등록된 코드가 포트폴리오에 없다면 코드를 등록
self.k.portfolio_stock_dict.update({sCode: {}})
# 포트폴리오 종목코드마다 아래 실시간 데이터를 입력
self.k.portfolio_stock_dict[sCode].update({"채결시간": a}) # 아래 내용을 업데이트
self.k.portfolio_stock_dict[sCode].update({"현재가": b})
self.k.portfolio_stock_dict[sCode].update({"전일대비": c})
self.k.portfolio_stock_dict[sCode].update({"등락율": d})
self.k.portfolio_stock_dict[sCode].update({"(최우선)매도호가": e})
self.k.portfolio_stock_dict[sCode].update({"(최우선)매수호가": f})
self.k.portfolio_stock_dict[sCode].update({"거래량": g})
self.k.portfolio_stock_dict[sCode].update({"누적거래량": h})
self.k.portfolio_stock_dict[sCode].update({"고가": i})
self.k.portfolio_stock_dict[sCode].update({"시가": j})
self.k.portfolio_stock_dict[sCode].update({"저가": k})
self.k.portfolio_stock_dict[sCode].update({"거래회전율": l})
###############################################################
############# 실시간을 위한 조건문 구성하기 ########################
###############################################################
#1. 매수 알고리즘 가동
#1차#############################################################################################
if self.k.portfolio_stock_dict[sCode]["현재가"] <= self.k.portfolio_stock_dict[sCode]["매수가"]:
if sCode not in self.orderitmelist_1:
wa = []
wa.append(sCode)
if len(wa) > 1:
wa.clear()
pass
else:
print("매수 시작 %s" % sCode)
self.orderitmelist_1.append(sCode) # 이 기법을 더이상 사용하지 못하게 하기
order_success1 = self.k.kiwoom.dynamicCall("SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["신규매수", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 1, sCode,
self.k.portfolio_stock_dict[sCode]["매수수량"], self.k.portfolio_stock_dict[sCode]["현재가"],
self.realType.SENDTYPE['거래구분']['지정가'], ""])
wf2 = open("dist/mesu_database.txt", "a", encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("1매수정보", self.k.portfolio_stock_dict[sCode]["종목명"], b, self.k.portfolio_stock_dict[sCode]["채결시간"])) # t는 tap을 의미한다.
wf2.close()
if order_success1 == 0:
print("최우선매수호가로 주문 전달 성공")
else:
print("최우선매수호가로 주문 전달 실패")
#2. 매도 알고리즘 가동
#1차 익절 #############################################################################################
if self.k.portfolio_stock_dict[sCode]["현재가"] >= self.k.portfolio_stock_dict[sCode]["익절가"]:
if sCode not in self.orderitmelist_2:
wa = []
wa.append(sCode)
if len(wa) > 1:
wa.clear()
pass
else:
print("익절 시작 %s" % sCode)
self.orderitmelist_2.append(sCode) # 이 기법을 더이상 사용하지 못하게 하기
order_success2 = self.k.kiwoom.dynamicCall("SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["신규익절", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 2, sCode,
self.k.portfolio_stock_dict[sCode]["매수수량"], self.k.portfolio_stock_dict[sCode]["현재가"],
self.realType.SENDTYPE['거래구분']['지정가'], ""])
wf2 = open("dist/mesu_database.txt", "a", encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("1익절정보", self.k.portfolio_stock_dict[sCode]["종목명"], b, self.k.portfolio_stock_dict[sCode]["채결시간"])) # t는 tap을 의미한다.
wf2.close()
if order_success2 == 0:
print("익절가로 주문 전달 성공")
else:
print("익절가로 주문 전달 실패")
#1차 손절 #############################################################################################
if self.k.portfolio_stock_dict[sCode]["현재가"] <= self.k.portfolio_stock_dict[sCode]["손절가"]:
if sCode not in self.orderitmelist_3:
wa = []
wa.append(sCode)
if len(wa) > 1:
wa.clear()
pass
else:
print("손절 시작 %s" % sCode)
self.orderitmelist_3.append(sCode) # 이 기법을 더이상 사용하지 못하게 하기
order_success3 = self.k.kiwoom.dynamicCall("SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["신규손절", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 2, sCode,
self.k.portfolio_stock_dict[sCode]["매수수량"], self.k.portfolio_stock_dict[sCode]["현재가"],
self.realType.SENDTYPE['거래구분']['지정가'], ""])
wf2 = open("dist/mesu_database.txt", "a", encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("1손절정보", self.k.portfolio_stock_dict[sCode]["종목명"], b, self.k.portfolio_stock_dict[sCode]["채결시간"])) # t는 tap을 의미한다.
wf2.close()
if order_success3 == 0:
print("손절가로 주문 전달 성공")
else:
print("손절가로 주문 전달 실패")
not_meme_list = list(self.k.not_account_stock_dict) # 체결하지 않은 종목들을 실제 미체결 잔고에서 받아온다.
#미체결 잔고 매수/매도 취소 #############################################################################################
if len(self.k.not_account_stock_dict) > 0:
for order_num in not_meme_list: # not_meme_listnot_meme_list에는 주문번호가 들어가 있다.
code = self.k.not_account_stock_dict[order_num]["종목코드"]
meme_price = self.k.not_account_stock_dict[order_num]['주문가격']
not_quantity = self.k.not_account_stock_dict[order_num]['미체결수량']
order_gubun = self.k.not_account_stock_dict[order_num]['주문구분']
##### 매수에 대한 취소 주문 : 주문가격이 최우선 매수호가보다 작을 경우
if order_gubun == "매수" and not_quantity > 0 and meme_price < self.k.portfolio_stock_dict[sCode]["현재가"]:
order_success = self.k.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["매수취소", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 3, code, 0, 0,
self.realType.SENDTYPE['거래구분']['지정가'], order_num]) # order_num 은 어떤 주문을 취소할 것인가.
if order_success == 0:
print("%s 매수취소 전달 성공" % code) # 체결잔고에서 del을 했기 때문에 여기서 하지 않는다.
self.cancel_the_order.append(code) # 차 후 재매수를 위해 필요함
else:
print("%s 매수취소 전달 실패" % code)
wf2 = open("dist/chiso_database.txt", "a", encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("매수취소", self.k.portfolio_stock_dict[sCode]["종목명"], not_quantity, self.k.portfolio_stock_dict[sCode]["채결시간"])) # t는 tap을 의미한다.
wf2.close()
elif not_quantity == 0:
del self.k.not_account_stock_dict[order_num]
##### 매도에 대한 취소 주문 : 주문가격이 최우선매도호가보다 클결우
elif order_gubun == "매도" and not_quantity > 0 and self.k.portfolio_stock_dict[sCode]["현재가"] < meme_price:
order_success = self.k.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["매도취소", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 4, code, 0, 0,
self.realType.SENDTYPE['거래구분']['지정가'], order_num]) # order_num 은 어떤 주문을 취소할 것인가.
wf2 = open("dist/chiso_database.txt", "a",
encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("매도취소", self.k.portfolio_stock_dict[sCode]["종목명"], not_quantity,
self.k.portfolio_stock_dict[sCode]["채결시간"])) # t는 tap을 의미한다.
wf2.close()
if order_success == 0:
print("%s 매도취소 전달 성공" % code) # 체결잔고에서 del을 했기 때문에 여기서 하지 않는다.
self.cancel_the_order.append(code) # 차 후 재매수를 위해 필요함
else:
print("%s 매도취소 전달 실패" % code)
elif not_quantity == 0:
del self.k.not_account_stock_dict[order_num]
########################
# 5. 재 매수 알고리즘 : 현재가가 매수 되지 못하였을 경우를 대비하여 재 매수 알고리즘 가동
########################
elif sCode in self.cancel_the_order:
# 재매수#############################################################################################
if self.k.portfolio_stock_dict[sCode]["현재가"] <= self.k.portfolio_stock_dict[sCode]["매수가"]:
if sCode not in self.orderitmelist_4:
wa = []
wa.append(sCode)
if len(wa) > 1:
wa.clear()
pass
else:
print("재매수 시작 %s" % sCode)
self.orderitmelist_4.append(sCode) # 이 기법을 더이상 사용하지 못하게 하기
order_success3 = self.k.kiwoom.dynamicCall(
"SendOrder(QString, QString, QString ,int, QString, int, int, QString, QString)",
["신규매수", self.k.portfolio_stock_dict[sCode]['주문용스크린번호'], self.account_num, 1, sCode,
self.k.portfolio_stock_dict[sCode]["매수수량"], self.k.portfolio_stock_dict[sCode]["현재가"],
self.realType.SENDTYPE['거래구분']['지정가'], ""])
wf2 = open("dist/mesu_database.txt", "a",
encoding="utf8") # "a" 달아 쓴다. "w" 덮어 쓴다. files라느 파이썬 페키지 볼더를 만든다.
wf2.write("%s\t%s\t%s\t%s\n" % ("재매수정보", self.k.portfolio_stock_dict[sCode]["종목명"], b,
self.k.portfolio_stock_dict[sCode][
"채결시간"])) # t는 tap을 의미한다.
wf2.close()
if order_success3 == 0:
print("재매수 주문 전달 성공")
else:
print("재매수 주문 전달 실패")
def chejan_slot(self, sGubun, nItemCnt, sFIdList): # 주문전송 후 주문접수, 체결통보, 잔고통보를 수신
if sGubun == "0":
print("매수/매도 중입니다. 미체결 잔고 업데이트")
else:
print("미체결잔고 해결로 실제 잔고 업데이트")
if int(sGubun) == 0: # 주문전송 후 미체결 되었을 때 아래와 같은 연산을 해 준다.
account_num = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['계좌번호'])
sCode = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['종목코드'])[1:] # [A203042]
stock_name = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['종목명'])
stock_name = stock_name.strip() # 혹시라도 공백이 있을 까봐
origin_order_number = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['원주문번호']) # 원주문번호가 없으면 0000000이다
order_number = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문번호'])
order_status = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문상태']) # 접수/확인/체결 정보
order_quan = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문수량'])
order_quan = int(order_quan)
order_price = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문가격'])
order_price = int(order_price)
not_chegual_quan = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['미체결수량'])
not_chegual_quan = int(not_chegual_quan)
order_gubun = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문구분']) # 정정 등, 부호가 나오기 때문에 잡아줘야 된다.
order_gubun = order_gubun.lstrip('+').lstrip('-')
order_gubun = order_gubun.strip()
chegual_time_str = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['주문/체결시간']) # '151028'
chegual_price = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['체결가'])
if chegual_price == '':
chegual_price = 0 # 숫자로 할당
else:
chegual_price = int(chegual_price)
chegual_quantity = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['체결량'])
if chegual_quantity == '':
chegual_quantity = 0
else:
chegual_quantity = int(chegual_quantity)
current_price = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['현재가'])
current_price = abs(int(current_price))
first_sell_price = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['(최우선)매도호가'])
first_sell_price = abs(int(first_sell_price))
first_buy_price = self.k.kiwoom.dynamicCall("GetChejanData(int)", self.realType.REALTYPE['주문체결']['(최우선)매수호가'])
first_buy_price = abs(int(first_buy_price))
# 새로운 주문의 미체결 주문번호(order_number)가 미체결잔고에 없을 경우 아래와 같이 미체결 잔고를 업데이트 한다.
if order_number not in self.k.not_account_stock_dict.keys():
self.k.not_account_stock_dict.update({order_number: {}})
self.k.not_account_stock_dict[order_number].update({"종목코드": sCode})
self.k.not_account_stock_dict[order_number].update({"종목명": stock_name})
self.k.not_account_stock_dict[order_number].update({"주문번호": order_number})
self.k.not_account_stock_dict[order_number].update({"주문상태": order_status})
self.k.not_account_stock_dict[order_number].update({"주문수량": order_quan})
self.k.not_account_stock_dict[order_number].update({"주문가격": order_price})
self.k.not_account_stock_dict[order_number].update({"주문구분": order_gubun})
self.k.not_account_stock_dict[order_number].update({"미체결수량": not_chegual_quan})
self.k.not_account_stock_dict[order_number].update({"체결량": chegual_quantity})
self.k.not_account_stock_dict[order_number].update({"원주문번호": origin_order_number})
self.k.not_account_stock_dict[order_number].update({"주문/체결시간": chegual_time_str})
self.k.not_account_stock_dict[order_number].update({"체결가": chegual_price})
self.k.not_account_stock_dict[order_number].update({"현재가": current_price})
self.k.not_account_stock_dict[order_number].update({"(최우선)매도호가": first_sell_price})
self.k.not_account_stock_dict[order_number].update({"(최우선)매수호가": first_buy_price})
column_head = ["종목코드", "종목명", "주문번호", "주문상태", "주문수량", "주문가격", "미체결수량"]
colCount = len(column_head)
rowCount = (len(self.k.not_account_stock_dict))
self.parent.not_account.setColumnCount(colCount) # 행 갯수
self.parent.not_account.setRowCount(rowCount) # 열 갯수 (종목 수)
self.parent.not_account.setHorizontalHeaderLabels(column_head) # 행의 이름 삽입
for index in range(rowCount):
self.parent.not_account.setItem(index, 0, QTableWidgetItem(str(sCode)))
self.parent.not_account.setItem(index, 1, QTableWidgetItem(str(stock_name)))
self.parent.not_account.setItem(index, 2, QTableWidgetItem(str(format(order_number))))
self.parent.not_account.setItem(index, 3, QTableWidgetItem(str(format(order_status))))
self.parent.not_account.setItem(index, 4, QTableWidgetItem(str(format(order_quan, ","))))
self.parent.not_account.setItem(index, 5, QTableWidgetItem(str(format(order_price, ","))))
self.parent.not_account.setItem(index, 6, QTableWidgetItem(str(format(not_chegual_quan, ","))))
print("미체결잔고 종목 추가 %s 수량 %s" % (self.k.not_account_stock_dict[order_number]["종목명"], self.k.not_account_stock_dict[order_number]["미체결수량"]))
'주식 자동매매 강의 > 기초반(모든 코딩의 뿌리)' 카테고리의 다른 글
주식자동매매 53강. 실시간 자동매매 구현(13), 미체결 잔고 체결 시 관련 데이터 저장 및 업데이트 (0) | 2022.06.19 |
---|---|
주식자동매매 52강. 실시간 자동매매 구현(12), 미체결 잔고 취소 주문 보내기 (2) | 2022.06.18 |
주식자동매매 50강. 실시간 자동매매 구현(10), 실시간 체결 정보 받아오기 (6) | 2022.06.17 |
주식자동매매 49강. 실시간 자동매매 구현(9), 관심 종목 실시간 매도(익절/손절) 주문 요청 하기 (8) | 2022.06.16 |
주식자동매매 48강. 실시간 자동매매 구현(8), 실시간 종목 원하는 가격에 매수하기 (12) | 2022.06.15 |