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.

155 lines
5.5 KiB

5 years ago
  1. import sys
  2. from PyQt5.QtWidgets import *
  3. import Kiwoom
  4. import time
  5. from pandas import DataFrame
  6. import datetime
  7. import webreader
  8. import numpy as np
  9. MARKET_KOSPI = 0
  10. MARKET_KOSDAQ = 10
  11. class PyMon:
  12. def __init__(self):
  13. self.kiwoom = Kiwoom.Kiwoom()
  14. self.kiwoom.comm_connect()
  15. self.get_code_list()
  16. def get_code_list(self):
  17. self.kospi_codes = self.kiwoom.get_code_list_by_market(MARKET_KOSPI)
  18. self.kosdaq_codes = self.kiwoom.get_code_list_by_market(MARKET_KOSDAQ)
  19. #현재 날짜를 기준으로 과거 거래일별로 시가, 고가, 저가, 종가, 거래량을 가져오는 메서드 구현
  20. def get_ohlcv(self, code, start):
  21. self.kiwoom.ohlcv = {'date': [], 'open': [], 'high': [], 'low': [], 'close': [], 'volume': []}
  22. self.kiwoom.set_input_value("종목코드", code)
  23. self.kiwoom.set_input_value("기준일자", start)
  24. self.kiwoom.set_input_value("수정주가구분", 1)
  25. self.kiwoom.comm_rq_data("opt10081_req", "opt10081", 0, "0101")
  26. #0.2초의 간격을 두어 TR 요청 -> 더 늘려도 될 듯...?
  27. time.sleep(0.5)
  28. df = DataFrame(self.kiwoom.ohlcv, columns=['open', 'high', 'low', 'close', 'volume'],
  29. index=self.kiwoom.ohlcv['date'])
  30. return df
  31. #이전 시점의 평균 거래랑을 특정 거래일 이전의 20일 동안의 평균 거래량으로 정의
  32. #특정 거래일의 거래량이 평균 거래량보다 25% 초과일 때 급등한 것으로 정의
  33. def check_speedy_rising_volume(self, code):
  34. today = datetime.datetime.today().strftime("%Y%m%d")
  35. df = self.get_ohlcv(code, today)
  36. volumes = df['volume']
  37. if len(volumes) < 11:
  38. return False
  39. sum_vol20 = 0
  40. today_vol = 0
  41. for i, vol in enumerate(volumes):
  42. if i == 0:
  43. today_vol = vol
  44. elif 1 <= i <= 10:
  45. sum_vol20 += vol
  46. else:
  47. break
  48. avg_vol20 = sum_vol20 / 10
  49. # 25% 초과인지 알아내는 부분, 초과한다면 True
  50. if today_vol > avg_vol20 * 10:
  51. return True
  52. #선정된 종목에 대한 정보 파일로 쓰기
  53. # 매수전이라고 buylist에 적었기 때문에 다음날 코드를 실행하면 pytrader에서 프로그램 실행.
  54. def update_buy_list(self, buy_list):
  55. f = open("buy_list.txt", "wt")
  56. for code in buy_list:
  57. f.writelines("매수;%s;시장가;10;0;매수전\n" % (code))
  58. f.close()
  59. def run(self):
  60. buy_list = []
  61. num = len(self.kosdaq_codes)
  62. for i, code in enumerate(self.kosdaq_codes):
  63. print(i, '/', num)
  64. if self.check_speedy_rising_volume(code):
  65. buy_list.append(code)
  66. self.update_buy_list(buy_list)
  67. def calculate_estimated_dividend_to_treasury(self, code):
  68. estimated_dividend_yield = webreader.get_estimated_dividend_yield(code)
  69. print("calculate_estimated_dividend_to_treasury", estimated_dividend_yield)
  70. if estimated_dividend_yield == 0:
  71. estimated_dividend_yield = webreader.get_dividend_yield(code)
  72. if estimated_dividend_yield == "":
  73. estimated_dividend_yield = 0
  74. current_3year_treasury = webreader.get_current_3year_treasury()
  75. estimated_dividend_to_treasury = float(estimated_dividend_yield) / float(current_3year_treasury)
  76. return estimated_dividend_to_treasury
  77. def get_min_max_dividend_to_treasury(self, code):
  78. previous_dividend_yield = webreader.get_previous_dividend_yield(code)
  79. three_years_treasury = webreader.get_3year_treasury()
  80. now = datetime.datetime.now()
  81. cur_year = now.year
  82. previous_dividend_to_treasury = {}
  83. for year in range(cur_year-5, cur_year):
  84. if year in previous_dividend_yield.keys() and year in three_years_treasury.keys():
  85. ratio = float(previous_dividend_yield[year]) / float(three_years_treasury[year])
  86. previous_dividend_to_treasury[year] = ratio
  87. #print(previous_dividend_to_treasury)
  88. if not previous_dividend_yield:
  89. return (0, 0)
  90. min_ratio = min(previous_dividend_to_treasury.values())
  91. max_ratio = max(previous_dividend_to_treasury.values())
  92. return (min_ratio, max_ratio)
  93. def buy_check_by_dividend_algorithm(self, code):
  94. estimated_dividend_to_treasury = self.calculate_estimated_dividend_to_treasury(code)
  95. (min_ratio, max_ratio) = self.get_min_max_dividend_to_treasury(code)
  96. if estimated_dividend_to_treasury >= max_ratio and max_ratio != 0:
  97. return (1, estimated_dividend_to_treasury)
  98. else:
  99. return (0, estimated_dividend_to_treasury)
  100. def run_dividend(self):
  101. buy_list = []
  102. for code in self.kospi_codes[100:150]:
  103. time.sleep(0.5)
  104. ret = self.buy_check_by_dividend_algorithm(code)
  105. if ret[0] == 1:
  106. buy_list.append((code, ret[1]))
  107. sorted_list = sorted(buy_list, key=lambda t:t[1], reverse=True)
  108. buy_list = []
  109. for i in range(0, 5):
  110. code = sorted_list[i][0]
  111. buy_list.append(code)
  112. self.update_buy_list(buy_list)
  113. if __name__ == "__main__":
  114. app = QApplication(sys.argv)
  115. pymon = PyMon()
  116. pymon.run_dividend()
  117. #print(pymon.calculate_estimated_dividend_to_treasury('058470'))
  118. #print(pymon.get_min_max_dividend_to_treasury("058470"))
  119. #print(pymon.buy_check_by_dividend_algorithm("058470"))