웹스쿨
파이썬을 이용한 뉴스매매 ver2.0 실시간 뉴스 + 주문설정 페이지 제작완료 본문
반응형
UI 부터가 ver1.0 과 완전히 다르게 개발했습니다.
각각의 정보들을 모두 새창으로 개발했습니다.
Qt Designer 으로 개발하니까 좌표값이랑 크기값을 일일이 세팅하지 않아도 되어서 개발이 너무 편하다.
메인 윈도우 소스공개~
import sys
import requests
import json
import re
import webbrowser
from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog, QGridLayout, QLabel, QMessageBox, QTableWidget, QTableWidgetItem, QPushButton, QLineEdit
from PyQt5 import uic
from PyQt5.QtCore import QTimer
from functools import partial
from collections import OrderedDict
from kiwoom import kiwoom
ui = uic.loadUiType("auto_pay.ui")[0]
order_ui = uic.loadUiType("order_setup.ui")[0]
class MyWindow(QMainWindow, ui):
def __init__(self):
super().__init__()
self.setupUi(self)
self.show()
'''
# 실사모드
self.ki = kiwoom()
self.ki.commConnect()
# 요기서 loop로 멈춤
self.server = self.ki.get_login_info("GetServerGubun")
if len(self.server) == 0 or self.server != "1":
self.serverGubun = "실제운영서버"
else:
self.serverGubun = "모의투자서버"
self.set_logbox(self.serverGubun + " 접속성공")
'''
# 테스트 모드
self.ki = kiwoom()
self.ki.user_id = "키움아이디"
# 실시간 뉴스 버튼
self.notice_btn.clicked.connect(self.notice_btn_proc)
# 주문설정 버튼
self.order_btn.clicked.connect(self.order_btn_proc)
# 공시뉴스 크롤링 타이머
self.current_timer = None
self.current_timer_interval = 1000
self.current_timer_cnt = 0
# 공시뉴스 데이터
self.news_list = None
# 공시뉴스 긁어오기 시작
# self.start_timer()
# 뉴스 크롤링 및 매칭 서버
self.api_url = "나의API 주소는 비밀"
# 종료버튼
self.btn_exit.clicked.connect(self.news_exit)
def news_exit(self):
# myWindow.close()
self.close()
def order_btn_proc(self):
# 주문설정 팝업
self.osdlg = OrderSetupDialog()
self.osdlg.show()
def notice_btn_proc(self):
# 공시뉴스 팝업
self.dlg = NoticeDialog()
# self.dlg.exec_()
self.dlg.show()
def OnCustomWinClosed(self):
print("OnCustomWinClosed 호출됨")
def start_timer(self):
if self.current_timer:
self.current_timer.stop()
self.current_timer.deleteLater()
self.current_timer = QTimer()
self.current_timer.timeout.connect(self.start_news)
self.current_timer.setSingleShot(True)
self.current_timer.start(self.current_timer_interval)
def start_news(self):
self.current_timer_cnt = self.current_timer_cnt + 1
print("뉴스 타이머 (" + str(self.current_timer_cnt) + ")")
self.get_set_news()
self.start_timer()
# API 서버에서 뉴스크롤링 실행시키고, 바로 가져오기
def get_set_news(self):
# print("get_set_news 호출, stock_id = " + self.ki.user_id)
post_data = {"type": "getset", "stock_id": self.ki.user_id}
r = requests.post(self.api_url, data=post_data)
result_json = r.text # {"result":"OK"}
data = json.loads(result_json)
# print("get_set_news = " + dict['result'])
# 매칭된 키워드가 있으면 로그로 보여주기
'''
뉴스 쓰레드 가동(135)
{'111': ['(주)', '결과']}
'''
if data['log_text']:
self.set_logbox(data['log_text'])
'''
buy_code = re.split(',', data['buy_code'])
for row in buy_code:
if row:
self.ki.call_stock(row)
'''
# 뉴스 갱신
# print("data.list = " + data['list'])
self.news_list = data['list']
def set_logbox(self, msg):
content = self.logbox.toPlainText()
self.logbox.setText(msg + "\n" + content)
class NoticeDialog(QDialog):
def __init__(self):
super().__init__()
print("NoticeDialog 오픈됨.")
self.setGeometry(700, 200, 1000, 650)
self.setWindowTitle("실시간 공시뉴스")
self.notice_table = QTableWidget(self)
self.notice_table.setRowCount(20)
self.notice_table.setColumnCount(3)
self.notice_table.setColumnWidth(0, 720)
self.notice_table.setColumnWidth(1, 140)
self.notice_table.setColumnWidth(2, 90)
self.notice_table.setHorizontalHeaderLabels(['제목', '시간', '상세보기'])
self.layout = QGridLayout()
self.layout.addWidget(self.notice_table, 0, 0)
self.setLayout(self.layout)
self.current_news_timer = None
self.current_news_start = "YES"
# 공시뉴스 마지막 제목
self.last_title = None
self.news_timer()
# self.close()
def closeEvent(self, event):
print("closeEvent 호출됨")
event.ignore()
self.hide()
self.current_news_start = "NO"
def news_loading(self):
print("news_list = " + str(myWindow.news_list))
if myWindow.news_list != None:
cnt = 0
for row in myWindow.news_list:
if cnt == 0:
if self.last_title == row['title']:
break
else:
self.last_title = row['title']
# title = row['title'][0:30]
title = row['title']
self.notice_table.setItem(cnt, 0, QTableWidgetItem(title))
self.notice_table.setItem(cnt, 1, QTableWidgetItem(row['time']))
detailbtn = QPushButton("보기")
detailbtn.clicked.connect(partial(self.detailbtn_clicked, row['idx']))
self.notice_table.setCellWidget(cnt, 2, detailbtn)
# 데이터 갱신을 위해 포커스를 주자
self.notice_table.setCurrentCell(cnt, 0)
self.notice_table.setCurrentCell(cnt, 1)
self.notice_table.setCurrentCell(cnt, 2)
cnt = cnt + 1
if self.current_news_start == "YES":
self.news_timer()
# 기사 상세보기 띄우기
def detailbtn_clicked(self, idx):
url = myWindow.api_url + "?type=news_detail&idx=" + idx + "&stock_id=" + myWindow.ki.user_id
webbrowser.open(url)
def news_timer(self):
# print("news_timer 호출, self.current_news_timer = " + str(self.current_news_timer))
if self.current_news_timer:
self.current_news_timer.stop()
self.current_news_timer.deleteLater()
self.current_news_timer = QTimer()
self.current_news_timer.timeout.connect(self.news_loading)
self.current_news_timer.setSingleShot(True)
self.current_news_timer.start(1000)
class OrderSetupDialog(QDialog, order_ui):
def __init__(self):
super().__init__()
# print("OrderSetupDialog 오픈됨." + str(order_ui))
try:
self.setupUi(self)
except Exception as error:
print(error)
self.btn_order_add.clicked.connect(self.order_table_add)
self.btn_order_save.clicked.connect(self.order_save_proc)
self.vars = locals()
post_data = {"type": "order_get", "stock_id": myWindow.ki.user_id}
# print("post_data = " + str(post_data))
return_data = requests.post(myWindow.api_url, data=post_data)
return_data = return_data.text
# print("return_data = " + str(return_data))
r_data = json.loads(return_data)
order_list_number = 0
if r_data['result'] == "OK":
self.order_money.setText(r_data['buy_money'])
for row in r_data['data']:
# print(row['name'])
self.btn_order_add_proc(order_list_number)
self.vars['edit_name_%d' % order_list_number].setText(row['name'])
self.vars['edit_code_%d' % order_list_number].setText(row['code'])
order_list_number = order_list_number + 1
else:
QMessageBox.information(self, "알림", "주문설정 가져오기에 실패했습니다.")
def order_save_proc(self):
cnt = self.order_table.rowCount()
all_json = OrderedDict()
all_json_cnt = 0
for i in range(cnt):
row_json = OrderedDict()
row_json['name'] = self.vars['edit_name_%d' % i].text()
row_json['code'] = self.vars['edit_code_%d' % i].text()
all_json[str(all_json_cnt)] = row_json
all_json_cnt = all_json_cnt + 1
# print("all_json = " + str(all_json))
data = json.dumps(all_json)
buy_money = self.order_money.text()
post_data = {"type": "order_save", "stock_id": myWindow.ki.user_id, "data": data, "buy_money": buy_money}
# print("post_data = " + str(post_data))
return_data = requests.post(myWindow.api_url, data=post_data)
return_data = return_data.text
#print("return_data = " + str(return_data))
r_data = json.loads(return_data)
#print(r_data['result'])
if r_data['result'] == "OK":
QMessageBox.information(self, "알림", "저장성공")
elif r_data['result'] == "NO":
QMessageBox.information(self, "알림", r_data['msg'])
def order_table_add(self):
cnt = self.order_table.rowCount()
self.btn_order_add_proc(cnt)
def btn_order_add_proc(self, rowCnt):
# print("btn_order_add_proc 호출됨")
self.order_table.insertRow(rowCnt)
self.vars['edit_name_%d' % rowCnt] = QLineEdit()
self.order_table.setCellWidget(rowCnt, 0, self.vars['edit_name_%d' % rowCnt])
self.vars['edit_code_%d' % rowCnt] = QLineEdit()
self.order_table.setCellWidget(rowCnt, 1, self.vars['edit_code_%d' % rowCnt])
self.vars['btn_remove_%d' % rowCnt] = QPushButton("삭제" + str(rowCnt))
self.vars['btn_remove_%d' % rowCnt].clicked.connect(partial(self.btn_remove_clicked, rowCnt))
self.order_table.setCellWidget(rowCnt, 2, self.vars['btn_remove_%d' % rowCnt])
def btn_remove_clicked(self, index):
# print("btn_remove_clicked 호출, index = " + str(index))
rowCnt = self.order_table.rowCount()
for i in range(rowCnt):
if index > i:
continue
elif index == i:
self.order_table.removeRow(index)
else:
edit_name_value = self.vars['edit_name_%d' % i].text()
edit_code_value = self.vars['edit_code_%d' % i].text()
upper_number = i - 1
self.btn_order_add_proc(upper_number)
self.vars['edit_name_%d' % upper_number].setText(edit_name_value)
self.vars['edit_code_%d' % upper_number].setText(edit_code_value)
self.order_table.removeRow(i)
if __name__ == "__main__":
app = QApplication(sys.argv)
myWindow = MyWindow()
sys.exit(app.exec_())
이 게시글은
https://webschool.kr/?v=board_view&board_key=30&idx=467
에서 작성한 글입니다. 소스코드의 경우 해당 블로그에서 이뿌게 노출이 되지 않을 수 있사오니, 위 링크로 들어오셔서 보시길 바랍니다.
https://webschool.kr/?v=board_view&board_key=30&idx=467
에서 작성한 글입니다. 소스코드의 경우 해당 블로그에서 이뿌게 노출이 되지 않을 수 있사오니, 위 링크로 들어오셔서 보시길 바랍니다.
반응형
'개인 프로젝트 > 파이썬 뉴스매매' 카테고리의 다른 글
실시간 뉴스, 종목 키워드, 주문 설정, 매수 패턴 적용완료 (0) | 2023.03.30 |
---|---|
종목코드 데이터베이스에 저장 (0) | 2023.03.29 |
키움 API를 이용한 뉴스매매 ver2.0 개발시작 (0) | 2023.03.29 |
최종 완성본 이라기보다는 일단 프로토타입 완성 (0) | 2023.03.29 |
매수성공 (0) | 2023.03.29 |