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
155 lines
5.5 KiB
import sys
|
|
from PyQt5.QtWidgets import *
|
|
import Kiwoom
|
|
import time
|
|
from pandas import DataFrame
|
|
import datetime
|
|
import webreader
|
|
import numpy as np
|
|
|
|
MARKET_KOSPI = 0
|
|
MARKET_KOSDAQ = 10
|
|
|
|
class PyMon:
|
|
def __init__(self):
|
|
self.kiwoom = Kiwoom.Kiwoom()
|
|
self.kiwoom.comm_connect()
|
|
self.get_code_list()
|
|
|
|
def get_code_list(self):
|
|
self.kospi_codes = self.kiwoom.get_code_list_by_market(MARKET_KOSPI)
|
|
self.kosdaq_codes = self.kiwoom.get_code_list_by_market(MARKET_KOSDAQ)
|
|
|
|
#현재 날짜를 기준으로 과거 거래일별로 시가, 고가, 저가, 종가, 거래량을 가져오는 메서드 구현
|
|
def get_ohlcv(self, code, start):
|
|
self.kiwoom.ohlcv = {'date': [], 'open': [], 'high': [], 'low': [], 'close': [], 'volume': []}
|
|
|
|
self.kiwoom.set_input_value("종목코드", code)
|
|
self.kiwoom.set_input_value("기준일자", start)
|
|
self.kiwoom.set_input_value("수정주가구분", 1)
|
|
self.kiwoom.comm_rq_data("opt10081_req", "opt10081", 0, "0101")
|
|
#0.2초의 간격을 두어 TR 요청 -> 더 늘려도 될 듯...?
|
|
time.sleep(0.5)
|
|
|
|
df = DataFrame(self.kiwoom.ohlcv, columns=['open', 'high', 'low', 'close', 'volume'],
|
|
index=self.kiwoom.ohlcv['date'])
|
|
return df
|
|
|
|
#이전 시점의 평균 거래랑을 특정 거래일 이전의 20일 동안의 평균 거래량으로 정의
|
|
#특정 거래일의 거래량이 평균 거래량보다 25% 초과일 때 급등한 것으로 정의
|
|
def check_speedy_rising_volume(self, code):
|
|
today = datetime.datetime.today().strftime("%Y%m%d")
|
|
df = self.get_ohlcv(code, today)
|
|
volumes = df['volume']
|
|
|
|
if len(volumes) < 11:
|
|
return False
|
|
|
|
sum_vol20 = 0
|
|
today_vol = 0
|
|
|
|
for i, vol in enumerate(volumes):
|
|
if i == 0:
|
|
today_vol = vol
|
|
elif 1 <= i <= 10:
|
|
sum_vol20 += vol
|
|
else:
|
|
break
|
|
|
|
avg_vol20 = sum_vol20 / 10
|
|
# 25% 초과인지 알아내는 부분, 초과한다면 True
|
|
if today_vol > avg_vol20 * 10:
|
|
return True
|
|
|
|
#선정된 종목에 대한 정보 파일로 쓰기
|
|
# 매수전이라고 buylist에 적었기 때문에 다음날 코드를 실행하면 pytrader에서 프로그램 실행.
|
|
def update_buy_list(self, buy_list):
|
|
f = open("buy_list.txt", "wt")
|
|
for code in buy_list:
|
|
f.writelines("매수;%s;시장가;10;0;매수전\n" % (code))
|
|
f.close()
|
|
|
|
def run(self):
|
|
buy_list = []
|
|
num = len(self.kosdaq_codes)
|
|
|
|
for i, code in enumerate(self.kosdaq_codes):
|
|
print(i, '/', num)
|
|
if self.check_speedy_rising_volume(code):
|
|
buy_list.append(code)
|
|
|
|
self.update_buy_list(buy_list)
|
|
|
|
def calculate_estimated_dividend_to_treasury(self, code):
|
|
estimated_dividend_yield = webreader.get_estimated_dividend_yield(code)
|
|
print("calculate_estimated_dividend_to_treasury", estimated_dividend_yield)
|
|
if estimated_dividend_yield == 0:
|
|
estimated_dividend_yield = webreader.get_dividend_yield(code)
|
|
|
|
if estimated_dividend_yield == "":
|
|
estimated_dividend_yield = 0
|
|
|
|
current_3year_treasury = webreader.get_current_3year_treasury()
|
|
|
|
estimated_dividend_to_treasury = float(estimated_dividend_yield) / float(current_3year_treasury)
|
|
return estimated_dividend_to_treasury
|
|
|
|
|
|
def get_min_max_dividend_to_treasury(self, code):
|
|
previous_dividend_yield = webreader.get_previous_dividend_yield(code)
|
|
three_years_treasury = webreader.get_3year_treasury()
|
|
|
|
now = datetime.datetime.now()
|
|
cur_year = now.year
|
|
previous_dividend_to_treasury = {}
|
|
|
|
for year in range(cur_year-5, cur_year):
|
|
if year in previous_dividend_yield.keys() and year in three_years_treasury.keys():
|
|
ratio = float(previous_dividend_yield[year]) / float(three_years_treasury[year])
|
|
previous_dividend_to_treasury[year] = ratio
|
|
|
|
#print(previous_dividend_to_treasury)
|
|
if not previous_dividend_yield:
|
|
return (0, 0)
|
|
|
|
min_ratio = min(previous_dividend_to_treasury.values())
|
|
max_ratio = max(previous_dividend_to_treasury.values())
|
|
|
|
return (min_ratio, max_ratio)
|
|
|
|
def buy_check_by_dividend_algorithm(self, code):
|
|
estimated_dividend_to_treasury = self.calculate_estimated_dividend_to_treasury(code)
|
|
(min_ratio, max_ratio) = self.get_min_max_dividend_to_treasury(code)
|
|
|
|
if estimated_dividend_to_treasury >= max_ratio and max_ratio != 0:
|
|
return (1, estimated_dividend_to_treasury)
|
|
else:
|
|
return (0, estimated_dividend_to_treasury)
|
|
|
|
|
|
|
|
def run_dividend(self):
|
|
buy_list = []
|
|
|
|
for code in self.kospi_codes[100:150]:
|
|
time.sleep(0.5)
|
|
ret = self.buy_check_by_dividend_algorithm(code)
|
|
if ret[0] == 1:
|
|
buy_list.append((code, ret[1]))
|
|
|
|
sorted_list = sorted(buy_list, key=lambda t:t[1], reverse=True)
|
|
|
|
buy_list = []
|
|
for i in range(0, 5):
|
|
code = sorted_list[i][0]
|
|
buy_list.append(code)
|
|
|
|
self.update_buy_list(buy_list)
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
pymon = PyMon()
|
|
pymon.run_dividend()
|
|
#print(pymon.calculate_estimated_dividend_to_treasury('058470'))
|
|
#print(pymon.get_min_max_dividend_to_treasury("058470"))
|
|
#print(pymon.buy_check_by_dividend_algorithm("058470"))
|