You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

219 lines
8.2 KiB

5 years ago
  1. import sys
  2. from PyQt5.QtWidgets import *
  3. from PyQt5.QAxContainer import *
  4. from PyQt5.QtCore import *
  5. import time
  6. import pandas as pd
  7. import sqlite3
  8. TR_REQ_TIME_INTERVAL = 0.05
  9. class Kiwoom(QAxWidget):
  10. def __init__(self):
  11. super().__init__()
  12. self._create_kiwoom_instance()
  13. self._set_signal_slots()
  14. def _create_kiwoom_instance(self):
  15. self.setControl("KHOPENAPI.KHOpenAPICtrl.1")
  16. def _set_signal_slots(self):
  17. self.OnEventConnect.connect(self._event_connect)
  18. self.OnReceiveTrData.connect(self._receive_tr_data)
  19. self.OnReceiveChejanData.connect(self._receive_chejan_data)
  20. def comm_connect(self):
  21. self.dynamicCall("CommConnect()")
  22. self.login_event_loop = QEventLoop()
  23. self.login_event_loop.exec_()
  24. def _event_connect(self, err_code):
  25. if err_code == 0:
  26. print("connected")
  27. else:
  28. print("disconnected")
  29. self.login_event_loop.exit()
  30. def get_code_list_by_market(self, market):
  31. code_list = self.dynamicCall("GetCodeListByMarket(QString)", market)
  32. code_list = code_list.split(';')
  33. return code_list[:-1]
  34. def get_master_code_name(self, code):
  35. code_name = self.dynamicCall("GetMasterCodeName(QString)", code)
  36. return code_name
  37. def get_connect_state(self):
  38. ret = self.dynamicCall("GetConnectState()")
  39. return ret
  40. def get_login_info(self, tag):
  41. ret = self.dynamicCall("GetLoginInfo(QString)", tag)
  42. return ret
  43. def set_input_value(self, id, value):
  44. self.dynamicCall("SetInputValue(QString, QString)", id, value)
  45. def comm_rq_data(self, rqname, trcode, next, screen_no):
  46. self.dynamicCall("CommRqData(QString, QString, int, QString)", rqname, trcode, next, screen_no)
  47. self.tr_event_loop = QEventLoop()
  48. self.tr_event_loop.exec_()
  49. def _comm_get_data(self, code, real_type, field_name, index, item_name):
  50. ret = self.dynamicCall("CommGetData(QString, QString, QString, int, QString)", code,
  51. real_type, field_name, index, item_name)
  52. return ret.strip()
  53. def _get_repeat_cnt(self, trcode, rqname):
  54. ret = self.dynamicCall("GetRepeatCnt(QString, QString)", trcode, rqname)
  55. return ret
  56. def send_order(self, rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no):
  57. self.dynamicCall("SendOrder(QString, QString, QString, int, QString, int, int, QString, QString)",
  58. [rqname, screen_no, acc_no, order_type, code, quantity, price, hoga, order_no])
  59. def get_chejan_data(self, fid):
  60. ret = self.dynamicCall("GetChejanData(int)", fid)
  61. return ret
  62. def get_server_gubun(self):
  63. ret = self.dynamicCall("KOA_Functions(QString, QString)", "GetServerGubun", "")
  64. return ret
  65. def _receive_chejan_data(self, gubun, item_cnt, fid_list):
  66. print(gubun)
  67. print(self.get_chejan_data(9203))
  68. print(self.get_chejan_data(302))
  69. print(self.get_chejan_data(900))
  70. print(self.get_chejan_data(901))
  71. def _receive_tr_data(self, screen_no, rqname, trcode, record_name, next, unused1, unused2, unused3, unused4):
  72. if next == '2':
  73. self.remained_data = True
  74. else:
  75. self.remained_data = False
  76. if rqname == "opt10081_req":
  77. self._opt10081(rqname, trcode)
  78. elif rqname == "opw00001_req":
  79. self._opw00001(rqname, trcode)
  80. elif rqname == "opw00018_req":
  81. self._opw00018(rqname, trcode)
  82. try:
  83. self.tr_event_loop.exit()
  84. except AttributeError:
  85. pass
  86. @staticmethod
  87. def change_format(data):
  88. strip_data = data.lstrip('-0')
  89. if strip_data == '' or strip_data == '.00':
  90. strip_data = '0'
  91. try:
  92. format_data = format(int(strip_data), ',d')
  93. except:
  94. format_data = format(float(strip_data))
  95. if data.startswith('-'):
  96. format_data = '-' + format_data
  97. return format_data
  98. @staticmethod
  99. def change_format2(data):
  100. strip_data = data.lstrip('-0')
  101. if strip_data == '':
  102. strip_data = '0'
  103. if strip_data.startswith('.'):
  104. strip_data = '0' + strip_data
  105. if data.startswith('-'):
  106. strip_data = '-' + strip_data
  107. return strip_data
  108. def _opw00001(self, rqname, trcode):
  109. d2_deposit = self._comm_get_data(trcode, "", rqname, 0, "d+2추정예수금")
  110. self.d2_deposit = Kiwoom.change_format(d2_deposit)
  111. def _opt10081(self, rqname, trcode):
  112. data_cnt = self._get_repeat_cnt(trcode, rqname)
  113. for i in range(data_cnt):
  114. date = self._comm_get_data(trcode, "", rqname, i, "일자")
  115. open = self._comm_get_data(trcode, "", rqname, i, "시가")
  116. high = self._comm_get_data(trcode, "", rqname, i, "고가")
  117. low = self._comm_get_data(trcode, "", rqname, i, "저가")
  118. close = self._comm_get_data(trcode, "", rqname, i, "현재가")
  119. volume = self._comm_get_data(trcode, "", rqname, i, "거래량")
  120. self.ohlcv['date'].append(date)
  121. self.ohlcv['open'].append(int(open))
  122. self.ohlcv['high'].append(int(high))
  123. self.ohlcv['low'].append(int(low))
  124. self.ohlcv['close'].append(int(close))
  125. self.ohlcv['volume'].append(int(volume))
  126. def reset_opw00018_output(self):
  127. self.opw00018_output = {'single': [], 'multi': []}
  128. def _opw00018(self, rqname, trcode):
  129. # single data
  130. total_purchase_price = self._comm_get_data(trcode, "", rqname, 0, "총매입금액")
  131. total_eval_price = self._comm_get_data(trcode, "", rqname, 0, "총평가금액")
  132. total_eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, 0, "총평가손익금액")
  133. total_earning_rate = self._comm_get_data(trcode, "", rqname, 0, "총수익률(%)")
  134. estimated_deposit = self._comm_get_data(trcode, "", rqname, 0, "추정예탁자산")
  135. self.opw00018_output['single'].append(Kiwoom.change_format(total_purchase_price))
  136. self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_price))
  137. self.opw00018_output['single'].append(Kiwoom.change_format(total_eval_profit_loss_price))
  138. total_earning_rate = Kiwoom.change_format(total_earning_rate)
  139. if self.get_server_gubun():
  140. total_earning_rate = float(total_earning_rate) / 100
  141. total_earning_rate = str(total_earning_rate)
  142. self.opw00018_output['single'].append(total_earning_rate)
  143. self.opw00018_output['single'].append(Kiwoom.change_format(estimated_deposit))
  144. # multi data
  145. rows = self._get_repeat_cnt(trcode, rqname)
  146. for i in range(rows):
  147. name = self._comm_get_data(trcode, "", rqname, i, "종목명")
  148. quantity = self._comm_get_data(trcode, "", rqname, i, "보유수량")
  149. purchase_price = self._comm_get_data(trcode, "", rqname, i, "매입가")
  150. current_price = self._comm_get_data(trcode, "", rqname, i, "현재가")
  151. eval_profit_loss_price = self._comm_get_data(trcode, "", rqname, i, "평가손익")
  152. earning_rate = self._comm_get_data(trcode, "", rqname, i, "수익률(%)")
  153. quantity = Kiwoom.change_format(quantity)
  154. purchase_price = Kiwoom.change_format(purchase_price)
  155. current_price = Kiwoom.change_format(current_price)
  156. eval_profit_loss_price = Kiwoom.change_format(eval_profit_loss_price)
  157. earning_rate = Kiwoom.change_format2(earning_rate)
  158. self.opw00018_output['multi'].append([name, quantity, purchase_price, current_price, eval_profit_loss_price,
  159. earning_rate])
  160. if __name__ == "__main__":
  161. app = QApplication(sys.argv)
  162. kiwoom = Kiwoom()
  163. kiwoom.comm_connect()
  164. kiwoom.reset_opw00018_output()
  165. account_number = kiwoom.get_login_info("ACCNO")
  166. account_number = account_number.split(';')[0]
  167. kiwoom.set_input_value("계좌번호", account_number)
  168. kiwoom.comm_rq_data("opw00018_req", "opw00018", 0, "2000")
  169. print(kiwoom.opw00018_output['single'])
  170. print(kiwoom.opw00018_output['multi'])