diff --git a/Simulation.py b/Simulation.py index a09f5f6..9788be7 100644 --- a/Simulation.py +++ b/Simulation.py @@ -182,8 +182,11 @@ if __name__ == "__main__": # to check bying stock_codes = { - "252670": ['20220822', '20220823', '20220824', '20220825', '20220826', '20220829'], - "122630": ['20220822', '20220823', '20220824', '20220825', '20220826', '20220829'] + "252670": ['20220801', '20220802', '20220803', '20220804', '20220805', + '20220808', '20220809', '20220810', '20220811', '20220812', + '20220816', '20220817', '20220818', '20220819', + '20220822', '20220823', '20220824', '20220825', '20220826', '20220829'], + #"122630": ['20220822', '20220823', '20220824', '20220825', '20220826', '20220829'] } method = "rule" # "rule", "ml", "answer" diff --git a/hts/BuySellChecker.py b/hts/BuySellChecker.py index 5cdf393..a8dd16b 100644 --- a/hts/BuySellChecker.py +++ b/hts/BuySellChecker.py @@ -23,143 +23,6 @@ class BuySellChecker: return - def getPriceAndWeight1(self, data, i): - buy, weight, sell = -1, -1, -1 - - START_TIME_INDEX = 0 - for c in range(370, len(data.index)): - if data.index[c].strftime("%H:%M:%S") == "09:01:00": - START_TIME_INDEX = c - break - - if i >= START_TIME_INDEX: - ################ - ### sell 분석 ### - ################ - # 1. 볼린져밴드 상단이 최고와 종가 사이 아래에 있는 경우 매도한다. - #if (hts["high"][i] - hts["close"][i]) / 2 + hts["close"][i] > hts["upper"][i]: - # sell = hts["high"][i] - - # 2. slow_k가 90이 넘으면 매도한다. - if data["slow_k"][i] > 90: - sell = data["high"][i] - - #if hts["slow_k"][i] >= 85: - # if hts["slow_d"][i-1] < hts["slow_k"][i-1] and hts["slow_k"][i] < hts["slow_d"][i]: - # sell = hts["high"][i] - - # 3. 2시 이후에는 최고가가 볼린져밴드 상단 위에 있으면 매도한다. - if i > 300 and data["high"][i] > data["upper"][i]: - sell = data["high"][i] - - ########################## - ### buy 분석 ### - ########################## - if data["low"][i] < data["lower"][i] + 5 and data["open"][i] <= data["close"][i]: - if data["slow_k"][i-1] < 30 and data["slow_k"][i] < 30: - if data["slow_k"][i-1] < data["slow_k"][i]: - buy = data["low"][i] - - if data["rsi"][i] < 25: - if data["rsi"][i - 2] < data["rsis"][i - 2] and data["rsi"][i - 1] < data["rsis"][i - 1] and data["rsis"][i] < data["rsi"][i]: - if data["close"][i] < data["avg5"][i]: - buy = data["close"][i] - else: - buy = data["low"][i] - weight = 1 - - ############################# - ### STOCHASTIC weight 분석 ### - ############################# - if data["slow_k"][i] in (0, 1, 2, 3): - weight = 1 - if data["slow_k"][i] in (4, 5, 6, 7, 8): - weight = 1 - elif data["slow_k"][i] in (9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20): - weight = 1 - elif data["slow_k"][i] in (21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35): - weight = 1 - - return buy, weight, sell - - def getPriceAndWeight2(self, data, i): - buy, weight, sell = -1, -1, -1 - - START_TIME_INDEX = 0 - for c in range(370, len(data.index)): - if data.index[c].strftime("%H:%M:%S") == "09:01:00": - START_TIME_INDEX = c - break - - if i >= START_TIME_INDEX: - ################ - ### sell 분석 ### - ################ - # 1. 볼린져밴드 상단이 최고와 종가 사이 아래에 있는 경우 매도한다. - if (data["high"][i] - data["close"][i]) / 2 + data["close"][i] > data["upper"][i]: - sell = data["high"][i] - - if data["slow_k"][i] >= 85: - if data["slow_d"][i - 1] < data["slow_k"][i - 1] and data["slow_k"][i] < data["slow_d"][i]: - sell = data["high"][i] - - # 3. 2시 이후에는 최고가가 볼린져밴드 상단 위에 있으면 매도한다. - if i > 300 and data["high"][i] > data["upper"][i]: - sell = data["high"][i] - - ########################## - ### STOCHASTIC buy 분석 ### - ########################## - if i < 40: - pre_slow = data["slow_k"][i - 1] / data["slow_d"][i - 1] - 1 - now_slow = data["slow_k"][i] / data["slow_d"][i] - 1 - if pre_slow < 0 and 0 < now_slow: - if data["slow_k"][i] <= 35: - if (data["close"][i] - data["lower"][i]) / (data["upper"][i] - data["lower"][i]) < 0.35: - if data["slow_k"][i - 1] < data["slow_d"][i - 1] and data["slow_d"][i] < data["slow_k"][i]: - if data['avg10'][i] < data['avg5'][i]: - if data["open"][i] < data["close"][i]: - buy = data["close"][i] - else: - buy = data["low"][i] - else: - pre_slow = data["slow_k"][i - 1] / data["slow_d"][i - 1] - 1 - now_slow = data["slow_k"][i] / data["slow_d"][i] - 1 - if pre_slow < 0 and pre_slow < now_slow and -0.15 < now_slow: - if data["slow_k"][i] <= 30: - if (data["close"][i] - data["lower"][i]) / (data["upper"][i] - data["lower"][i]) < 0.35: - if data["slow_k"][i - 1] < data["slow_d"][i - 1] and data["slow_d"][i] < data["slow_k"][i]: - if data['avg10'][i] < data['avg5'][i]: - if data["close"][i] < data["avg5"][i]: - buy = data["close"][i] - else: - buy = data["low"][i] - - ############################# - ### STOCHASTIC weight 분석 ### - ############################# - if data["slow_k"][i] in (0, 1, 2, 3): - weight = 1 - if data["slow_k"][i] in (4, 5, 6, 7, 8): - weight = 1 - elif data["slow_k"][i] in (9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20): - weight = 1 - elif data["slow_k"][i] in (21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35): - weight = 1 - - return buy, weight, sell - - def getBuyCheck(self, data, i, buy, weight): - if data['close'][i] 40: - buy, weight, sell = -1, -1, -1 - - return buy, weight - - - def isYangbong(self, data, i): if data['close'][i] > data['open'][i]: @@ -181,11 +44,52 @@ class BuySellChecker: return True return False + # 지난 1시간 30분 동안 12분 선이 20분 선위에 20분 이상 있었는지 체크 + def check_12_over_20_for_30(self, data, i, default=90): + if i - default < 381: + return False + check_12_over_20_for_30 = False + for c in range(i - default, i - 20): + if data['avg20'][c] < data['avg20'][i]: + value = [1 if data['avg20'][d] < data['avg12'][d] else 0 for d in range(c, c + 20)] + if len(value) == 20 and sum(value) == 20: + check_12_over_20_for_30 = True + break + return check_12_over_20_for_30 + + # 지난 1시간 동안 3, 6, 9, 12분 선이 10분 이상 20분 선 아래 있었는지 체크 + def check_under_20_for_10(self, data, i, within=60, during=10): + if i - within < 381: + return False + + check_under_20_for_10 = False + for c in range(i - within, i - during): + value = [1 if max(data['avg3'][d], data['avg6'][d], data['avg9'][d], data['avg12'][d]) < data['avg20'][d] else 0 for d in range(c, c + during)] + if len(value) == during and sum(value) == during: + check_under_20_for_10 = True + break + return check_under_20_for_10 + + def max_min_avg(self, data, i): + return max(data['avg3'][i], data['avg6'][i], data['avg9'][i], data['avg12'][i], data['avg20'][i]) - min(data['avg3'][i], data['avg6'][i], data['avg9'][i], data['avg12'][i], data['avg20'][i]) + + def check_inverse_arrangement_before(self, data, i, within=30, during=5): + if i - within < 381: + return False + + inverse_arrangement = False + for c in range(i-within, i-during): + value = [1 if data['avg3'][d] < data['avg6'][d] < data['avg9'][d] < data['avg12'][d] < data['avg20'][d] else 0 for d in range(c, c + during)] + if len(value) == during and sum(value) == during-1: + inverse_arrangement = True + break + return inverse_arrangement def getBuyPriceAndWeight(self, data, i): - buy, weight = -1, -1 - slow_k = 60 + type = -1 + buy, weight = min(data["open"][i], data["close"][i]), 1 + SLOW_K = 60 START_TIME_INDEX = 0 for c in range(370, len(data.index)): @@ -196,38 +100,80 @@ class BuySellChecker: if i > START_TIME_INDEX: # 매수 분석 + # 이전에 30분 동안 5분내 역배열이 있었던 경우, avg3이 avg20위로 올라온 경우 매수한다. + if data['avg3'][i-1] <= data['avg20'][i-1] and data['avg3'][i] > data['avg20'][i]: + if self.check_inverse_arrangement_before(data, i, 30, 5): + buy = min(data["open"][i], data["close"][i]) + weight = 1 + type = 1 + return buy, weight, type + + # 10시 이후 + if i > START_TIME_INDEX + 60: + if data["macd"][i] < -10 and data["macd"][i - 1] < data["macd"][i]: + if data["slow_k"][i] < 5 and data["slow_k"][i-1] < data["slow_k"][i]: + if data["slow_k"][i] < 5 and data["slow_k"][i - 1] < data["slow_k"][i]: + if data["rsi"][i] < 30 and data["rsi"][i - 1] < data["rsi"][i]: + buy = min(data["open"][i], data["close"][i]) + weight = 1 + type = 1 + return buy, weight, type + + + # avg20이 10분동안 상승하고,현재 avg20이 open/close 사이에 있고, slow_k가 60보다 작으면 매수 valid = True - for c in range(i-10, i+1): + for c in range(i-9, i+1): if data["avg20"][c-1] > data["avg20"][c]: valid = False if valid: - min_value = min(data["open"][i], data["close"][i]) - max_value = max(data["open"][i], data["close"][i]) - if min_value < data["avg20"][i] < max_value: - if data["slow_k"][i] < slow_k: - buy = min_value - weight = 1 + min_value = data["close"][i] + max_value = data["open"][i] + if data["open"][i] < data["close"][i]: + min_value = data["open"][i] + max_value = data["close"][i] - if data["slow_k"][i] < slow_k: + if min_value < data["avg20"][i] < max_value: + if data["slow_k"][i] < SLOW_K: + if not self.check_12_over_20_for_30(data, i): + buy = min_value + weight = 1 + type = 1 + return buy, weight, type + + # 현재 slow_k가 60보다 작고, 최근 5분 동안 avg20이 다른 avg[3,6,9,12]의 최저값보다 큰 적이 없을 때, + if data["slow_k"][i] < SLOW_K: valid = True - for c in range(i - 5, i + 1): - if data["avg20"][c] >= min(data["avg3"][c], data["avg6"][c], data["avg9"][c], data["avg12"][c]): + for c in range(i-4, i+1): + if min(data["avg3"][c], data["avg6"][c], data["avg9"][c], data["avg12"][c]) <= data["avg20"][c]: valid = False break if valid: valid = False - for c in range(i - 20, i + 1): - if data["avg20"][c] > max(data["avg3"][c], data["avg6"][c], data["avg9"][c], data["avg12"][c]): + # 최근 20분 동안 avg20이 다른 avg[3,6,9,12]의 최대값보다 큰 적이 있을 때, + for c in range(i-19, i+1): + if max(data["avg3"][c], data["avg6"][c], data["avg9"][c], data["avg12"][c]) < data["avg20"][c]: valid = True break if valid: - buy = max(int(data["open"][i]+data["close"][i])/2, min(data["open"][i], data["close"][i])) - weight = 1 + if not self.check_12_over_20_for_30(data, i): + buy = min(data["open"][i], data["close"][i]) + weight = 1 + type = 1 + return buy, weight, type - return buy, weight + if (data['macdo'][i] >= 0 or + data['avg3'][i-1] > data['avg3'][i] or + data['avg3'][i] < max(data['avg6'][i], data['avg9'][i], data['avg12'][i], data['avg20'][i])): + buy = -1 + weight = -1 + type = 0 + return buy, weight, type + + + return buy, weight, type def getSellPriceAndWeight(self, data, i): - sell, weight = -1, -1 + sell, weight, type = -1, -1, -1 slow_k = 60 START_TIME_INDEX = 0 @@ -254,7 +200,8 @@ class BuySellChecker: if data["slow_k"][i] > slow_k: sell = int(data["avg3"][i] - data["avg3"][i] % 5) weight = 1 - return sell, weight + type = 1 + return sell, weight, type # 12분선이 5분 이상 20분선 위에 있다가 20분선 아래로 내려옴 if i >= 381 + 5: @@ -268,21 +215,23 @@ class BuySellChecker: if data["slow_k"][i] > slow_k: sell = data["close"][i] weight = 1 - return sell, weight + type = 1 + return sell, weight, type if (not (data["avg20"][i-1] > max(data["avg3"][i-1], data["avg6"][i-1], data["avg9"][i-1], data["avg12"][i-1])) and (data["avg20"][i] > max(data["avg3"][i], data["avg6"][i], data["avg9"][i], data["avg12"][i]))): if data["slow_k"][i] > slow_k: sell = data["close"][i] weight = 1 - return sell, weight + type = 1 + return sell, weight, type - return sell, weight + return sell, weight, type # 곱버스에 해당함 def getBuyPriceAndWeight_252670(self, data, i): - buy, weight = -1, -1 + buy, weight, type = -1, -1, -1 START_TIME_INDEX = 0 for c in range(370, len(data.index)): @@ -315,12 +264,12 @@ class BuySellChecker: buy = int((data["open"][i] + data["close"][i]) / 2) weight = 1 - return buy, weight + return buy, weight, type - return buy, weight + return buy, weight, type def getSellPriceAndWeight_252670(self, data, i): - sell, weight = -1, -1 + sell, weight, type = -1, -1, -1 START_TIME_INDEX = 0 for c in range(370, len(data.index)): @@ -345,7 +294,7 @@ class BuySellChecker: if data["avg3"][i] < data["avg6"][i]: sell = int(data["avg3"][i] - data["avg3"][i] % 5) weight = 1 - return sell, weight + return sell, weight, type # 3분선이 5분 이상 12분선 위에 있다가 12분선 아래로 내려옴 if i >= 381 + 5: @@ -358,12 +307,12 @@ class BuySellChecker: if data["avg3"][i] < data["avg12"][i]: sell = data["close"][i] weight = 1 - return sell, weight + return sell, weight, type - return sell, weight + return sell, weight, type def getBuyPriceAndWeight_122630(self, data, i): - buy, weight = -1, -1 + buy, weight, type = -1, -1, -1 START_TIME_INDEX = 0 for c in range(370, len(data.index)): @@ -400,7 +349,7 @@ class BuySellChecker: buy = int((data["open"][i] + data["close"][i]) / 2) weight = 1 - return buy, weight + return buy, weight, type """ if -30 < data["macd"][i] < -25: @@ -412,7 +361,7 @@ class BuySellChecker: if valid: buy = int((data["open"][i] + data["close"][i]) / 2) weight = 1 - return buy, weight + return buy, weight, type previous_lowest_close = 99999999 for c in range(10, 30): @@ -428,7 +377,7 @@ class BuySellChecker: if valid: buy = int((data["open"][i] + data["close"][i]) / 2) weight = 1 - return buy, weight + return buy, weight, type if (data["avg54"][i-4] < data["avg54"][i-3] < data["avg54"][i-2] < data["avg54"][i-1] < data["avg54"][i] and @@ -438,7 +387,7 @@ class BuySellChecker: ): buy = data["close"][i] weight = 1 - return buy, weight + return buy, weight, type @@ -449,13 +398,13 @@ class BuySellChecker: if data['macd'][i] < -5: buy = data["close"][i] weight = 1 - return buy, weight + return buy, weight, type - return buy, weight + return buy, weight, type def getSellPriceAndWeight_122630(self, data, i): - sell, weight = -1, -1 + sell, weight, type = -1, -1, -1 START_TIME_INDEX = 0 for c in range(370, len(data.index)): @@ -480,7 +429,7 @@ class BuySellChecker: if data["avg3"][i] < data["avg6"][i]: sell = int(data["avg3"][i] - data["avg3"][i]%5) weight = 1 - return sell, weight + return sell, weight, type # 3분선이 5분 이상 12분선 위에 있다가 12분선 아래로 내려옴 if i >= 381 + 5: @@ -493,7 +442,7 @@ class BuySellChecker: if data["avg3"][i] < data["avg12"][i]: sell = data["close"][i] weight = 1 - return sell, weight + return sell, weight, type param = 2 if (data["macd"][i] > 11.4590339 and @@ -526,11 +475,11 @@ class BuySellChecker: data["diff_avg27"][i] > 2.261904762 * param and data["diff_avg54"][i] > 1.18452381 * param ): - buy = int((data["open"][i] + data["close"][i]) / 2) + sell = int((data["open"][i] + data["close"][i]) / 2) weight = 1 - return buy, weight + return sell, weight, type - return sell, weight + return sell, weight, type def analyze(self, result): # 기본 캔들 정보 @@ -1021,20 +970,13 @@ class BuySellChecker: # 어제 오늘 데이터로 분석 bsLine = {} size = len(data["close"]) + if isRealTime: # isRealTime=True, 실시간 적용 last_index = size - 1 - buy, buy_weight = self.getBuyPriceAndWeight(data, last_index) - sell, sell_weight = self.getSellPriceAndWeight(data, last_index) - """ - if stock_code == "252670": - sell, sell_weight = self.getSellPriceAndWeight_252670(data, last_index) - buy, buy_weight = self.getBuyPriceAndWeight_252670(data, last_index) - else: - sell, sell_weight = self.getSellPriceAndWeight_122630(data, last_index) - buy, buy_weight = self.getBuyPriceAndWeight_122630(data, last_index) - """ + buy, buy_weight, buy_type = self.getBuyPriceAndWeight(data, last_index) + sell, sell_weight, sell_type = self.getSellPriceAndWeight(data, last_index) bsLine['buy'] = [buy] bsLine['buy_weight'] = [buy_weight] @@ -1047,19 +989,23 @@ class BuySellChecker: bsLine['sell'] = [-1 for i in range(size)] bsLine['sell_weight'] = [-1 for i in range(size)] + self.buy_type = -1 for i in range(size): - buy, buy_weight = self.getBuyPriceAndWeight(data, i) - sell, sell_weight = self.getSellPriceAndWeight(data, i) - """ - if stock_code == "252670": - sell, sell_weight = self.getSellPriceAndWeight_252670(data, i) - buy, buy_weight = self.getBuyPriceAndWeight_252670(data, i) + buy, buy_weight, buy_type = self.getBuyPriceAndWeight(data, i) + sell, sell_weight, sell_type = self.getSellPriceAndWeight(data, i) + + if buy_type == 1: + self.buy_type = 1 + if buy_type == 0 or sell_type == 1: + self.buy_type = -1 + + if self.buy_type == 1: + bsLine['buy'][i] = buy + bsLine['buy_weight'][i] = buy_weight else: - sell, sell_weight = self.getSellPriceAndWeight_122630(data, i) - buy, buy_weight = self.getBuyPriceAndWeight_122630(data, i) - """ - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = buy_weight + bsLine['buy'][i] = -1 + bsLine['buy_weight'][i] = -1 + bsLine['sell'][i] = sell bsLine['sell_weight'][i] = sell_weight