아직... 한참남았는데, 생각보다 분량이 많다 ㅠ
얼른 가보자...!
def get_account_info(self):
self.account_list = self.dynamicCall("GetLoginInfo(String)","ACCNO")
self.account_num = self.account_list.split(';')[0]
print("계좌 번호 : %s" % self.account_num)
def detail_account_info(self):
print("예수금을 요청하는 부분")
self.dynamicCall("SetInputValue(String, String)","계좌번호",self.account_num)
self.dynamicCall("SetInputValue(String, String)","비밀번호","0000")
self.dynamicCall("SetInputValue(String, String)","비밀번호입력매체구분","00")
self.dynamicCall("SetInputValue(String, String)","조회구분","2")
self.dynamicCall("CommRqData(String, String, int, String)","예수금상세현황요청","opw00001","0",self.screen_my_info)
# event loop : 명령을 처리하는 동안 다른 작업을 가능하게 하는 것, 병렬화
self.detail_account_info_event_loop = QEventLoop() # 아랫줄과 함께, 2set는 명령마다 대기를 위해서 들어가야함
self.detail_account_info_event_loop.exec_() #_exec()랑은 최신버전 차이
def detail_account_mystock(self, sPrevNext="0"):
print("계좌평가 잔고내역 요청")
self.dynamicCall("SetInputValue(String, String)","계좌번호",self.account_num)
self.dynamicCall("SetInputValue(String, String)","비밀번호","0000")
self.dynamicCall("SetInputValue(String, String)","비밀번호입력매체구분","00")
self.dynamicCall("SetInputValue(String, String)","조회구분","2")
self.dynamicCall("CommRqData(String, String, int, String)","계좌평가잔고내역요청","opw00018",sPrevNext,self.screen_my_info)
# self.detail_account_info_event_loop_2=QEventLoop()
self.detail_account_info_event_loop.exec_()
def not_concluded_account(self, sPrevNext="0"):
print("미체결요청")
self.dynamicCall("SetInputValue(QString, QString)","계좌번호",self.account_num)
self.dynamicCall("SetInputValue(QString, QString)","체결구분","1")
self.dynamicCall("SetInputValue(QString, QString)", "매매구분", "0")
self.dynamicCall("CommRqData(String, String, int, String)","실시간미체결요청","opt10075",sPrevNext,self.screen_my_info)
self.detail_account_info_event_loop.exec_()
Account 관련 함수들은 한번에 모아봤다.
get_account_info(self) 함수는 계좌번호를 가져온다.
계좌번호를 받아오고, 초기에 생성한 self.account_num 변수에 반환해주는 역할을 한다.
detail_account_info(self) 함수에서는 예수금을 가져온다.
CommRqData를 통해 data를 요청하는데, 이 data 수신을 대기하기위해 뒤에 event loop를 걸어준다.
detail_account_mystock(self, sPrevNext="0")함수는 계좌평가 잔고내력을 불러온다.
이 때, 함수의 인자인 PrevNext는 연속 조회 여부를 결정한다. (2이면 연속조회)
not_concluded_account(self, sPrevNext="0") 함수는 미체결 요청 내역을 가져온다.
체결되지 않은 매매내력을 확인하는 함수이다.
사실 이런 자질구레한 함수 나열은 크게 중요하지 않다.
Tr data를 불러오는 여기부터는 좀 어려운 내용이었고, 실제로 많이 중요했는데 천천히 복기해봐야겠다.
def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName,sPrevNext):
'''
tr 요청을 받는 구역. Slot임!
:param sScrNo: 스크린번호
:param sRQName: 내가 요청했을 때 지은 이름
:param sTrCode: 요청 id, tr코드
:param sRecordName: 사용안함
:param sPrevNext: 다음 페이지가 있는지
:return:
'''
if sRQName == "예수금상세현황요청":
deposit=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "예수금")
print("예수금 %s" % deposit)
print("예수금 형변환%s" % int(deposit))
self.use_money=int(deposit)*self.use_money_percent #일부분만 사용하는 코드
self.use_money=self.use_money/4
ok_deposit=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "출금가능금액")
print("출금가능금액 %s" % ok_deposit)
print("출금가능금액 형변환 %s" % int(ok_deposit))
self.detail_account_info_event_loop.exit() # 도중에 빠짐
elif sRQName == "계좌평가잔고내역요청":
print("1")
total_buy_money=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총매입금액")
total_buy_money_result = int(total_buy_money)
print("총매입금액 %s" % total_buy_money_result)
total_profit_loss_rate = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총수익률(%)")
total_profit_loss_rate_result=float(total_profit_loss_rate)
print("총수익률(%%) %s" % total_profit_loss_rate_result)
rows=self.dynamicCall("GetRepeatCnt(QString, QString)",sTrCode, sRQName) #GetRepeatCnt : 멀티데이터 조회 용도
cnt=0
for i in range(rows):
code=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목번호")
code=code.strip()[1:]
code_name=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명")
stock_quantity=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "보유수량")
buy_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매입가")
learn_rate = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "수익률(%)")
current_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가")
total_chegual_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매입금액")
possible_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매매가능수량")
if code in self.account_stock_dict:
pass
else:
self.account_stock_dict.update({code:{}})
code_name=code_name.strip()
stock_quantity=int(stock_quantity.strip())
buy_price = int(buy_price.strip())
learn_rate = float(learn_rate.strip())
current_price = int(current_price.strip())
total_chegual_price = int(total_chegual_price.strip())
possible_quantity = int(possible_quantity.strip())
self.account_stock_dict[code].update({"종목명":code_name})
self.account_stock_dict[code].update({"보유수량":stock_quantity})
self.account_stock_dict[code].update({"매입가":buy_price})
self.account_stock_dict[code].update({"수익률(%)":learn_rate})
self.account_stock_dict[code].update({"현재가":current_price})
self.account_stock_dict[code].update({"매입금액":total_chegual_price})
self.account_stock_dict[code].update({"매매가능수량":possible_quantity})
cnt += 1
print("계좌에 가지고 있는 종목 %s"% self.account_stock_dict)
print("계좌 보유종목 카운트 %s"%cnt)
if sPrevNext=="2":
self.detail_account_mystock(sPrevNext="2")
else:
self.detail_account_info_event_loop.exit()
elif sRQName == "실시간미체결요청":
rows = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName) # GetRepeatCnt : 멀티데이터 조회 용도
for i in range(rows):
code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목코드")
code_name=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명")
order_no=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문번호")
order_status=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문상태")
order_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문수량")
order_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문가격")
order_gubun = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "주문구분")
not_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "미체결수량")
ok_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "체결량")
code=code.strip()
code_name=code_name.strip()
order_no=int(order_no.strip())
order_status=int(order_status.strip())
order_quantity = int(order_quantity.strip())
order_price = float(order_price.strip())
order_gubun = order_gubun.strip().lstrip('+').lstrip('-')
not_quantity = int(not_quantity.strip())
ok_quantity = int(ok_quantity.strip())
if order_no in self.not_account_stock_dict:
pass
else:
self.not_account_stock_dict[order_no]={}
self.not_account_stock_dict[order_no].update({"종목코드":code})
self.not_account_stock_dict[order_no].update({"종목명":code_name})
self.not_account_stock_dict[order_no].update({"주문번호":order_no})
self.not_account_stock_dict[order_no].update({"주문상태":order_status})
self.not_account_stock_dict[order_no].update({"주문수량":order_quantity})
self.not_account_stock_dict[order_no].update({"주문가격":order_price})
self.not_account_stock_dict[order_no].update({"주문구분":order_gubun})
self.not_account_stock_dict[order_no].update({"미체결수량":not_quantity})
self.not_account_stock_dict[order_no].update({"체결량":ok_quantity})
print("미체결 종목 :%s"%self.not_account_stock_dict[order_no])
self.detail_account_info_event_loop.exit()
elif sRQName=="주식일봉차트조회":
#print("일봉데이터 요청")
code=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드")
code = code.strip()
print("%s 일봉데이터 요청" % code)
cnt=self.dynamicCall("GetRepeatCnt(QString, QString)",sTrCode,sRQName)
print("데이터 일수 %s" % cnt)
#data=self.dynamicCall("GetCommDataEx(QString, QString)", sTrCode,sRQName)
#[['','현재가','거래량','거래대금','날짜','시가','고가','저가,''],['','현재가','거래량','거래대금','날짜','시가','고가','저가,''],...]]
#600일치 데이터인 것 확인
for i in range(cnt):
data=[]
current_price=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가")
value = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i,"거래량")
trading_value = 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,"저가")
data.append("")
data.append(current_price.strip())
data.append(value.strip())
data.append(trading_value.strip())
data.append(date.strip())
data.append(start_price.strip())
data.append(high_price.strip())
data.append(low_price.strip())
data.append("")
self.calcul_data.append(data.copy()) #위에 만들어줘야 하는 list
if sPrevNext =="2":
print(sPrevNext)
# self.day_kiwoom_db(code=code, sPrevNext=sPrevNext) #재귀함수에서 오류나는것같음
else:
print("총 일 수%s" %len(self.calcul_data))
#self.logging.logger.debug("총 일수 %s"% len(self.calcul_data))
#120이평선을 그릴 만큼의 data가 있는지 check 필요
pass_success = False
if self.calcul_data == None or len(self.calcul_data)<120:
pass_success=False
print("check1")
else:
#120일 이상이면
total_price=0
for value in self.calcul_data[:120]: #[D,D-1,...,D-120]
total_price += int(value[1])
moving_average_price=total_price/120
#오늘 주가 120일 이평선에 걸쳐있는지 확인
bottom_stock_price=False
check_price=None
if int(self.calcul_data[0][7]) <= moving_average_price and moving_average_price <= int(self.calcul_data[0][6]): #[0] : 오늘 [7] : 저가
print("오늘 주가 120이평선에 걸쳐있는 것 확인")
bottom_stock_price=True
check_price=int(self.calcul_data[0][6])
#과거의 일봉들이 120일 이평선보다 밑에 있는지 확인,
#그렇게 확인을 하다가 일봉이 120일 이평선보다 위에 있으면 계산 진행
prev_price=None #과거의 일봉 저가
if bottom_stock_price == True:
moving_average_price_prev=0
price_top_moving=False
idx=1
while True:
if len(self.calcul_data[idx:])<120:#최근부터 하루씩 거슬러올라가며 120일치 계속 있는지 확인
print("120일치 없음")
break
total_price=0
for value in self.calcul_data[idx:120+idx]:
total_price+=int(value[1])
moving_average_price_prev=total_price/120
if moving_average_price_prev <= int(self.calcul_data[idx][6]) and idx <= 20: # 20일정도는 아래여야되지않겠냐? 강의자가 만든거라함
print("20일동안 주가가 120일 이평선과 같거나 위에 있으면 조건 통과 못 함")
price_top_moving=False
break
elif int(self.calcul_data[idx][7]) > moving_average_price_prev and idx >20:
print("120일 이평선 위에 있는 일봉 확인 됨")
price_top_moving=True
prev_price=int(self.calcul_data[idx][7])
break
idx += 1
#해당부분 이평선이 가장 최근 일자의 이평선 가격보다 낮은지 확인
if price_top_moving == True:
if moving_average_price > moving_average_price_prev and check_price > prev_price:
print("포착된 이평선의 가격이 오늘자(최근일자) 이평선 가격보다 낮은 것 확인됨")
print("포착된 부분의 일봉 저가가 오늘자 일봉의 고가보다 낮은지 확인됨")
pass_success=True
pass_success=True #삭제해야됨
if pass_success==True:
print("조건부 통과됨")
code_nm = self.dynamicCall("GetMasterCodeName(QString)", code)
f=open("files/condition_stock.txt","a",encoding="utf8")
f.write("%s\t%s\t%s\n"%(code, code_nm, self.calcul_data[0][1]))
f.close()
elif pass_success == False:
print("조건부 통과 못함")
self.calcul_data.clear() #함수 초기화
self.calculator_event_loop.exit()
#print("cc")
#rows=self.dynamicCall("GetCommData(QString,QString,int,QString)",sTrCode,sRQName)
#print(rows) #None 오류 이것
if sPrevNext=="2":
self.day_kiwoom_db(code=code,sPrevNext=sPrevNext)
else:
self.calculator_event_loop.exit()
...양이 너무많다.
보기좋게 좀 줄여서 보자.
def trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName,sPrevNext):
if sRQName == "예수금상세현황요청":
deposit=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "예수금")
self.use_money=int(deposit)*self.use_money_percent #일부분만 사용하는 코드
self.use_money=self.use_money/4
ok_deposit=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "출금가능금액")
self.detail_account_info_event_loop.exit() # 도중에 빠짐
elif sRQName == "계좌평가잔고내역요청":
total_buy_money=self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총매입금액")
total_buy_money_result = int(total_buy_money)
total_profit_loss_rate = self.dynamicCall("GetCommData(String, String, int, String)", sTrCode, sRQName, 0, "총수익률(%)")
total_profit_loss_rate_result=float(total_profit_loss_rate)
rows=self.dynamicCall("GetRepeatCnt(QString, QString)",sTrCode, sRQName) #GetRepeatCnt : 멀티데이터 조회 용도
cnt=0
for i in range(rows):
code=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목번호")
code=code.strip()[1:]
code_name=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목명")
...
possible_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "매매가능수량")
if code in self.account_stock_dict:
pass
else:
self.account_stock_dict.update({code:{}})
code_name=code_name.strip()
stock_quantity=int(stock_quantity.strip())
...
possible_quantity = int(possible_quantity.strip())
self.account_stock_dict[code].update({"종목명":code_name})
...
self.account_stock_dict[code].update({"매매가능수량":possible_quantity})
cnt += 1
if sPrevNext=="2":
self.detail_account_mystock(sPrevNext="2")
else:
self.detail_account_info_event_loop.exit()
elif sRQName == "실시간미체결요청":
rows = self.dynamicCall("GetRepeatCnt(QString, QString)", sTrCode, sRQName) # GetRepeatCnt : 멀티데이터 조회 용도
for i in range(rows):
code = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "종목코드")
...
ok_quantity = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "체결량")
code=code.strip()
...
ok_quantity = int(ok_quantity.strip())
if order_no in self.not_account_stock_dict:
pass
else:
self.not_account_stock_dict[order_no]={}
self.not_account_stock_dict[order_no].update({"종목코드":code})
...
self.not_account_stock_dict[order_no].update({"체결량":ok_quantity})
self.detail_account_info_event_loop.exit()
elif sRQName=="주식일봉차트조회":
code=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, 0, "종목코드")
code = code.strip()
cnt=self.dynamicCall("GetRepeatCnt(QString, QString)",sTrCode,sRQName)
for i in range(cnt):
data=[]
current_price=self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i, "현재가")
...
low_price = self.dynamicCall("GetCommData(QString, QString, int, QString)", sTrCode, sRQName, i,"저가")
data.append("")
...
data.append("")
self.calcul_data.append(data.copy())
if sPrevNext =="2":
print(sPrevNext)
# self.day_kiwoom_db(code=code, sPrevNext=sPrevNext)
else:
pass_success = False
if self.calcul_data == None or len(self.calcul_data)<120:
pass_success=False
print("check1")
else:
total_price=0
for value in self.calcul_data[:120]: #[D,D-1,...,D-120]
total_price += int(value[1])
moving_average_price=total_price/120
bottom_stock_price=False
check_price=None
[조건부]
if pass_success==True:
print("조건부 통과됨")
code_nm = self.dynamicCall("GetMasterCodeName(QString)", code)
f=open("files/condition_stock.txt","a",encoding="utf8")
f.write("%s\t%s\t%s\n"%(code, code_nm, self.calcul_data[0][1]))
f.close()
elif pass_success == False:
print("조건부 통과 못함")
self.calcul_data.clear() #함수 초기화
self.calculator_event_loop.exit()
if sPrevNext=="2":
self.day_kiwoom_db(code=code,sPrevNext=sPrevNext)
else:
self.calculator_event_loop.exit()
위의 trdata_slot(self, sScrNo, sRQName, sTrCode, sRecordName,sPrevNext) 는 결국 우리가 요청하는 Request에 따라 요청을 받아오는 Slot이다.
sRQName의 인자로 예수금상세현황요청 / 계좌평가잔고내역요청 / 실시간미체결요청 / 주식일봉차트조회 등의 요청명을 받아서, 그 요청대로 호출하고 응답을 기다리는 slot이다.
호출한 뒤의 행동이 있기에 호출할때 사용된 event loop를 종료하는 event_loop.exit()로 각 명령이 마무리되며,
가장 중요한부분은... 주식일봉차트조회를 호출받아 실행하는 전략 구동부다.
해당 부분의 전략을 수정해가면서 코드를 사용할 수 있는것이다!
'글 > 코딩' 카테고리의 다른 글
(교육정리) Pandas와 Data 통계 - 1 (0) | 2023.07.25 |
---|---|
백준 알고리즘 문제 풀이 1764 : 듣보잡 (0) | 2023.07.05 |
[python][자동매매] 강의가 끝나고, 머릿속 정리 2. Login (0) | 2023.05.31 |
[python][자동매매] 강의가 끝나고, 머릿속 정리 1. init (1) | 2023.05.31 |
[Python][자동매매] Process finished with exit code -1073740791 (0xC0000409) 오류문 해결과정 (0) | 2023.05.29 |