import os from dtw import dtw import json import sqlite3 import numpy as np from datetime import datetime, timedelta class BuySellChecker(): PATTERNS = None RESOURCE_PATH = None def __init__(self, RESOURCE_PATH): self.RESOURCE_PATH = RESOURCE_PATH return def nearDisparity(self, data, i): if (0.998 < data['disparity_avg5'][i] < 1.002 and 0.998 < data['disparity_avg5'][i] < 1.002 and 0.998 < data['disparity_avg5'][i] < 1.002 and 0.998 < data['disparity_avg5'][i] < 1.002 and 0.998 < data['disparity_avg5'][i] < 1.002): return True return False def cosine_similarity(self, x, y): return np.dot(x, y) / (np.sqrt(np.dot(x, x)) * np.sqrt(np.dot(y, y))) """ def findBuyPoint(self, data, data_signal, i): # 코사인 유사도(cosine similarity)로 과거 주가의 유사 패턴을 찾아 미래 예측하기 # https://teddylee777.github.io/pandas/cos-sim-stock/ buy_target = data['close'].iloc[i-179:i+1] window_size = len(buy_target) if window_size == 180: buy_target = (buy_target - buy_target.min()) / (buy_target.max() - buy_target.min()) for pattern in self.PATTERNS: cos_similarity = self.cosine_similarity(pattern, buy_target) if 0.995 < cos_similarity: return True return False """ def findBuyPoint(self, data, i): # DTW (Dynamic Time Warping) # 시계열 유사도: https://m.blog.naver.com/happyrachy/221693939341 if i < 24: return False for p in range(len(self.PATTERNS['min_max'])): size = len(self.PATTERNS['stndardization'][p]) if i - size + 1 < 0: continue close = data['close'].iloc[i-size+1:i+1] #min_max = np.array(self.PATTERNS['min_max'][p]).reshape(-1, 1) stndardization = np.array(self.PATTERNS['stndardization'][p]).reshape(-1, 1) #min_max_y = np.array((close - close.min()) / (close.max() - close.min())).reshape(-1, 1) stndardization_y = np.array((close - close.mean()) / close.std()).reshape(-1, 1) #manhattan_distance = lambda min_max, min_max_y: np.abs(min_max - min_max_y) #min_max_d, cost_matrix, acc_cost_matrix, path = dtw(min_max, min_max_y, dist=manhattan_distance) manhattan_distance = lambda stndardization, stndardization_y: np.abs(stndardization - stndardization_y) stndardization_d, cost_matrix, acc_cost_matrix, path = dtw(stndardization, stndardization_y, dist=manhattan_distance) if stndardization_d < 2: #print(i, data['ymd'].iloc[i], stndardization_d) return True return False def getMacd(self, ticker_code, day, mins=1): table = 'minutely_max_macd_' + str(mins) conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, 'coins.db')) cursor = conn.cursor() day1 = (datetime.strptime(day, '%Y%m%d') - timedelta(1)).strftime('%Y%m%d') cursor.execute('SELECT ymd, hms, macd, close FROM '+table+' WHERE (CODE=? or CODE=?) and (ymd=? or ymd=?) order by macd desc', (ticker_code, ticker_code.replace('KRW-', ''), day, day1, )) db_result1 = cursor.fetchall() cursor.close() conn.close() macd_limit = [(datetime.strptime(rows[0]+" "+rows[1], '%Y%m%d %H%M%S'), rows[2], rows[3]) for rows in db_result1] macd_dup = list(set(macd_limit)) return macd_dup def is_Support(self, df, i, observation_time=300): # c1 = df.Low[i] < df.Low[i - 1] < df.Low[i - 2] < df.Low[i - 3] # c2 = df.Low[i] < df.Low[i + 1] < df.Low[i + 2] < df.Low[i + 3] # return c1 & c2 #if df['low'][i] == np.min(df['low'][i - self.observation_time:i + self.observation_time + 1]): if df['low'][i] == np.min(df['low'][i - observation_time:i+1]): return True else: return False def is_Resistance(self, df, i, observation_time = 300): # c1 = df.High[i] > df.High[i - 1] > df.High[i - 2] > df.High[i - 3] # c2 = df.High[i] > df.High[i + 1] > df.High[i + 2] > df.High[i + 3] # return c1 & c2 #if df['high'][i] == np.max(df['high'][i - self.observation_time:i + self.observation_time + 1]): if df['high'][i] == np.max(df['high'][i - observation_time:i+1]): return True else: return False def getBuyPriceAndWeight1(self, ticker, MAX_BUY_PRICE, i, data, data_signal, BUY_LIST, isRealTime=True): buy_ymd, buy_price, buy_count, buy_cut, buy_type = None, -1, -1, -1, '' df_tmp = data_signal['ymd'] <= data['ymd'][i] df_signal = data_signal.loc[df_tmp] si = len(df_signal) - 1 i = i - 5 check = False duration = 5 + 60 if duration < i: if np.average(data['trend_avg'][i - duration:i]) < data['trend_avg'][i] and data['avg1500'][i] < \ data['trend_avg'][i]: if np.average(data['avg480'][i - duration:i]) < data['avg480'][i]: if data['avg480'][i] < data['trend_avg'][i]: if data['avg20'][i] < data['avg480'][i] and data['avg20'][i - 1] < data['avg20'][i]: if len(BUY_LIST['buy_list']) == 0: check = True else: if BUY_LIST['buy_list'][-1]['buy_price'] < data['close'][i]: check = True if 2800 < len(data['close'][i - 2880:i]) and np.max(data['close'][i - 2880:i]) < data['close'][i]: if np.max(data['rsi'][i - 30:i]) < data['rsi'][i]: if data['disparity_avg1500'][i] < 1.1: if data['close'][i] < data['trend_avg'][i]: buy_type = 'upward' check = True max_value = np.max(data['close'][i - 3000:i]) min_value = np.min(data['close'][i - 3000:i]) if 0.1 < (max_value - min_value) / max_value: if data['close'][i - 1] < data['trend_avg'][i - 1] and data['trend_avg'][i] < data['close'][i]: buy_type = 'trend_close' check = True if data['disparity_avg20'][i] < BUY_LIST['disparity']['limit_bottom_5']['avg20']: buy_type = 'disparity_avg' check = True if data['disparity_avg60'][i] < BUY_LIST['disparity']['limit_bottom_5']['avg60']: buy_type = 'disparity_avg' check = True if data['disparity_avg480'][i] < BUY_LIST['disparity']['limit_bottom_10']['avg480']: buy_type = 'disparity_avg' check = True if data['disparity_avg1500'][i] < BUY_LIST['disparity']['limit_bottom_20']['avg1500']: buy_type = 'disparity_avg' check = True if check: buy_price = data['close'][i] buy_ymd = data['ymd'][i] if data['slow_k'][si] < 30: buy_count = MAX_BUY_PRICE * 2 / (data['close'][i]) elif data['slow_k'][si] < 50: buy_count = MAX_BUY_PRICE * 1.5 / (data['close'][i]) else: buy_count = MAX_BUY_PRICE * 1 / (data['close'][i]) return buy_ymd, buy_price, buy_count, buy_cut, buy_type return buy_ymd, buy_price, buy_count, buy_cut, buy_type def getSellPriceAndWeight1(self, ticker, i, data, data_signal, BUY_LIST=None): sell_price, sell_count, sell_type = -1, -1, '' check = False sell_count_disparity_avg = 0 sell_count_trend_close = 0 if 0 < len(BUY_LIST['buy_list']): if data['avg480'][i - 1] <= data['avg420'][i] and data['avg420'][i] < data['avg480'][i]: sell_count_trend_close = sum( [price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'trend_close']) if 0 < sell_count_trend_close: check = True # 매수한지 12시간 이내라면 if data['ymd'][i] - timedelta(hours=12) < BUY_LIST['buy_list'][-1]['buy_ymd']: if BUY_LIST['disparity']['limit_top_3']['avg20'] < data['disparity_avg20'][i]: sell_count_disparity_avg = sum( [price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_3']['avg60'] < data['disparity_avg60'][i]: sell_count_disparity_avg = sum( [price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_5']['avg480'] < data['disparity_avg480'][i]: sell_count_disparity_avg = sum( [price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_10']['avg1500'] < data['disparity_avg1500'][i]: sell_count_disparity_avg = sum( [price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True else: # 매수한지 12시간 이후라면 if BUY_LIST['buy_list'][-1]['buy_price'] * 1.004 < data['close'][i]: if BUY_LIST['disparity']['limit_top_99']['avg20'] < data['disparity_avg20'][i]: sell_count_disparity_avg = sum([price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_99']['avg60'] < data['disparity_avg60'][i]: sell_count_disparity_avg = sum([price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_99']['avg480'] < data['disparity_avg480'][i]: sell_count_disparity_avg = sum([price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if BUY_LIST['disparity']['limit_top_99']['avg1500'] < data['disparity_avg1500'][i]: sell_count_disparity_avg = sum([price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'disparity_avg']) check = True if check: sell_price = data['close'][i] sell_count = sell_count_disparity_avg + sell_count_trend_close return sell_price, sell_count, sell_type def checkTransaction1(self, ticker, MAX_BUY_PRICE, data, data_signal, BUY_LIST=None, isRealTime=True): # 어제 오늘 데이터로 분석 bsLine = {} if data is not None and 'close' in data.columns: size = len(data["close"]) if isRealTime: # isRealTime=True, 실시간 적용 last_index = size - 1 sell_price, sell_count, sell_type = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST) bsLine['sell_price'] = [sell_price] bsLine['sell_count'] = [sell_count] bsLine['sell_type'] = [sell_type] if 0 < sell_price: BUY_LIST['buy_limit'] = 0 BUY_LIST['buy_list'].clear() else: buy_ymd, buy_price, buy_count, buy_cut, buy_type = self.getBuyPriceAndWeight1(ticker, MAX_BUY_PRICE, last_index, data, data_signal, BUY_LIST, isRealTime) bsLine['buy_ymd'] = [buy_ymd] bsLine['buy_price'] = [buy_price] bsLine['buy_count'] = [buy_count] bsLine['buy_cut'] = [buy_cut] bsLine['buy_type'] = [buy_type] if 0 < buy_price: BUY_LIST['buy_list'].append( {'buy_ymd': buy_ymd, 'buy_price': buy_price, 'buy_count': buy_count, 'buy_cut': buy_cut, 'buy_type': buy_type}) else: # Type=False, 시뮬레이션 적용 bsLine['buy_ymd'] = [-1 for i in range(size)] bsLine['buy_price'] = [-1 for i in range(size)] bsLine['buy_count'] = [-1 for i in range(size)] bsLine['buy_cut'] = [-1 for i in range(size)] bsLine['buy_type'] = ['' for i in range(size)] bsLine['sell_price'] = [-1 for i in range(size)] bsLine['sell_count'] = [-1 for i in range(size)] bsLine['sell_type'] = ['' for i in range(size)] for last_index in range(size): sell_price, sell_count, sell_type = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST) bsLine['sell_price'][last_index] = sell_price bsLine['sell_count'][last_index] = sell_count bsLine['sell_type'][last_index] = sell_type if 0 < sell_price: BUY_LIST['buy_limit'] = 0 BUY_LIST['buy_list'].clear() else: buy_ymd, buy_price, buy_count, buy_cut, buy_type = self.getBuyPriceAndWeight1(ticker, MAX_BUY_PRICE, last_index, data, data_signal, BUY_LIST, isRealTime) bsLine['buy_price'][last_index] = buy_price bsLine['buy_count'][last_index] = buy_count bsLine['buy_cut'][last_index] = buy_cut bsLine['buy_type'][last_index] = buy_type if 0 < buy_price: BUY_LIST['buy_list'].append( {'buy_ymd': buy_ymd, 'buy_price': buy_price, 'buy_count': buy_count, 'buy_cut': buy_cut, 'buy_type': buy_type}) else: bsLine['buy_price'] = [-1] bsLine['buy_count'] = [-1] bsLine['buy_cut'] = [-1] bsLine['buy_type'] = [''] bsLine['sell_price'] = [-1] bsLine['sell_count'] = [-1] return bsLine