diff --git a/Bithumb_minute.py b/Bithumb_minute.py deleted file mode 100644 index 488a09a..0000000 --- a/Bithumb_minute.py +++ /dev/null @@ -1,778 +0,0 @@ -import os -import time -import requests -import json -import ccxt -import pybithumb -import pandas as pd -from math import nan -import plotly.io as po -from plotly import subplots -import plotly.graph_objects as go -from datetime import datetime, timedelta -from sklearn.linear_model import LinearRegression -from sklearn.preprocessing import StandardScaler, MinMaxScaler - -from stock.analysis.AnalyzerSqlite import AnalyzerSqlite -from hts.BuySellChecker import BuySellChecker -from hts.HTS import HTS -from stock.util.SlackBot import SlackBot - - -class Bithumb_minute(HTS): - RESOURCE_PATH = None - buySellChecker = None - analyzerSqlite = None - bithumb = None - binance = None - TODAY = None - slackBot = None - stock_code = None - - def __init__(self, RESOURCE_PATH, today): - super().__init__(RESOURCE_PATH) - self.slackBot = SlackBot() - self.stock_code = {"XRP": "리플"} - - self.RESOURCE_PATH = RESOURCE_PATH - - con_key = "946dd0b0e6f8ad411144cd33f09518d3" # 본인의 Connect Key를 입력한다. - sec_key = "56b2a3cdd9fe3a82aa3f38c97c161125" # 본인의 Secret Key를 입력한다. - - self.buySellChecker = BuySellChecker() - self.analyzerSqlite = AnalyzerSqlite() - - # bithumb api에 연결한 클라스 객체를 선언한다. - self.bithumb = pybithumb.Bithumb(con_key, sec_key) - self.binance = ccxt.binance() - self.TODAY = today - - return - - def bull_market(self, df, ticker): - m5 = df['close'].rolling(5).mean() - last_m5 = m5[-2] - - price = pybithumb.get_current_price(ticker) - - if price > last_m5: - return True - - return False - - def append(self, df, stock): - for i in range(len(df)): - stock['PRICE'].append( - { - "ymd": df.index[i], - "close": df['close'][i], - "diff": 0, - "open": df['open'][i], - "high": df['high'][i], - "low": df['low'][i], - "volume": df['volume'][i], - "avg3": -1, - "avg4": -1, - "avg5": -1, - "avg6": -1, - "avg10": -1, - "avg12": -1, - "avg20": -1, - "avg36": -1, - "avg40": -1, - "avg48": -1, - "avg60": -1, - "avg120": -1, - "avg200": -1, - "avg240": -1, - "avg300": -1, - "disparity_avg5": -1, - "disparity_avg10": -1, - "disparity_avg20": -1, - "disparity_avg60": -1, - "disparity_avg120": -1, - "bolingerband_upper": -1, - "bolingerband_lower": -1, - "bolingerband_middle": -1, - "envelope_upper": -1, - "envelope_lower": -1, - "envelope_middle": -1, - "ichimokucloud_changeLine": -1, - "ichimokucloud_baseLine": -1, - "ichimokucloud_leadingSpan1": -1, - "ichimokucloud_leadingSpan2": -1, - "stochastic_fast_k": -1, - "stochastic_slow_k": -1, - "stochastic_slow_d": -1, - "rsi": -1, - "rsis": -1, - "macd": -1, - "macds": -1, - "macdo": -1, - }) - return - - def analyze(self, stock, days=120): - stock["PRICE"] = sorted(stock["PRICE"], key=lambda x: x['ymd']) - self.analyzerSqlite.get_moving_average(stock["PRICE"]) - - # 이동 평균을 이용한 이격도 계산 - self.analyzerSqlite.get_disparity(stock["PRICE"]) - - self.analyzerSqlite.ichimokuCloud.analyze(stock) - self.analyzerSqlite.stochastic.analyze(stock) - self.analyzerSqlite.bolingerBand.analyze(stock) - self.analyzerSqlite.envelope.analyze(stock) - self.analyzerSqlite.rsi.analyze(stock) - self.analyzerSqlite.macd.analyze(stock) - - result = { - "ymd": [], - "open": [], - "close": [], - "high": [], - "low": [], - "avg3": [], - "avg4": [], - "avg5": [], - "avg6": [], - "avg10": [], - "avg12": [], - "avg20": [], - "avg36": [], - "avg40": [], - "avg48": [], - "avg60": [], - "avg120": [], - "avg200": [], - "avg240": [], - "avg300": [], - "disparity_avg5": [], - "disparity_avg20": [], - "disparity_avg60": [], - "disparity_avg120": [], - "disparity": [], - "disparity_type": [], - "envelope_upper": [], - "envelope_lower": [], - "envelope_middle": [], - "rsi": [], - "rsis": [], - "macd": [], - "macds": [], - "slow_k": [], - "slow_d": [], - "buy": [], - "sell": [], - } - for item in stock['PRICE']: - result["ymd"].append(item['ymd']) - result["open"].append(item['open']) - result["close"].append(item['close']) - result["high"].append(item['high']) - result["low"].append(item['low']) - result["avg3"].append(item['avg3']) - result["avg4"].append(item['avg4']) - result["avg5"].append(item['avg5']) - result["avg6"].append(item['avg6']) - result["avg10"].append(item['avg10']) - result["avg12"].append(item['avg12']) - result["avg20"].append(item['avg20']) - result["avg36"].append(item['avg36']) - result["avg40"].append(item['avg40']) - result["avg48"].append(item['avg48']) - result["avg60"].append(item['avg60']) - result["avg120"].append(item['avg120']) - result["avg200"].append(item['avg200']) - result["avg240"].append(item['avg240']) - result["avg300"].append(item['avg300']) - result["disparity_avg5"].append(item['disparity_avg5']) - result["disparity_avg20"].append(item['disparity_avg20']) - result["disparity_avg60"].append(item['disparity_avg60']) - result["disparity_avg120"].append(item['disparity_avg120']) - result['disparity'].append( - max(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60']) - min( - item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60'])) - if item['disparity_avg60'] < item['disparity_avg20'] < item['disparity_avg5']: - result['disparity_type'].append(1) - elif item['disparity_avg5'] < item['disparity_avg20'] < item['disparity_avg60']: - result['disparity_type'].append(-1) - else: - result['disparity_type'].append(0) - result["envelope_upper"].append(item['envelope_upper']) - result["envelope_lower"].append(item['envelope_lower']) - result["envelope_middle"].append(item['envelope_middle']) - result["rsi"].append(item['rsi']) - result["rsis"].append(item['rsis']) - result["macd"].append(item['macd']) - result["macds"].append(item['macds']) - result["slow_k"].append(item['stochastic_slow_k']) - result["slow_d"].append(item['stochastic_slow_d']) - result["buy"].append(-1) - result["sell"].append(-1) - - data = pd.DataFrame(result) - df_final_time = pd.DatetimeIndex(result['ymd']) - data.index = df_final_time - - data = data.astype( - { - 'open': 'float', - 'high': 'float', - 'low': 'float', - 'close': 'float', - 'avg3': 'float', - 'avg4': 'float', - 'avg5': 'float', - 'avg6': 'float', - 'avg10': 'float', - 'avg12': 'float', - 'avg20': 'float', - 'avg36': 'float', - 'avg40': 'float', - 'avg48': 'float', - 'avg60': 'float', - 'avg120': 'float', - 'avg200': 'float', - 'avg240': 'float', - 'avg300': 'float', - 'disparity_avg5': 'float', - 'disparity_avg20': 'float', - 'disparity_avg60': 'float', - 'disparity_avg120': 'float', - 'buy': 'float', - 'sell': 'float', - 'slow_k': 'float', - 'slow_d': 'float', - 'macd': 'float', - 'macds': 'float', - 'envelope_upper': 'float', - 'envelope_lower': 'float', - 'envelope_middle': 'float', - 'rsi': 'float', - 'rsis': 'float' - } - ) - - scaler = StandardScaler() - low_df = pd.DataFrame(data['low']) - low_df.index = [c for c in range(len(low_df))] - low_std = scaler.fit_transform(data['low'].values.reshape(-1, 1)) - low_std = pd.DataFrame(low_std, columns=['low_std']) - - min_df = pd.DataFrame({'open': data['open'].to_list(), 'close': data['close'].to_list()}) - min_df['min_std'] = min_df.min(axis=1) - min_df.index = [c for c in range(len(min_df))] - min_std = scaler.fit_transform(min_df['min_std'].values.reshape(-1, 1)) - min_std = pd.DataFrame(min_std, columns=['min_std']) - - line_fitter = LinearRegression() - size = len(data["close"]) - gradients_low = [] - gradients_avg5 = [] - gradients_avg20 = [] - gradients_avg60 = [] - - for i in range(size): - coef_low = -999 - coef_avg5 = -999 - coef_avg20 = -999 - coef_avg60 = -999 - - if i > 0: - l = days if i >= days else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(low_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_low = line_fitter.coef_[0][0] - - l = 5 if i >= 5 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg5 = line_fitter.coef_[0][0] - - l = 20 if i >= 20 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg20 = line_fitter.coef_[0][0] - - l = 60 if i >= 60 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg60 = line_fitter.coef_[0][0] - - gradients_low.append(coef_low) - gradients_avg5.append(coef_avg5) - gradients_avg20.append(coef_avg20) - gradients_avg60.append(coef_avg60) - - gradients_low_df = pd.DataFrame(gradients_low, columns=['gradients_low']) - gradients_avg5_df = pd.DataFrame(gradients_avg5, columns=['gradients_avg5']) - gradients_avg20_df = pd.DataFrame(gradients_avg20, columns=['gradients_avg20']) - gradients_avg60_df = pd.DataFrame(gradients_avg60, columns=['gradients_avg60']) - - gradients_low_df.index = df_final_time - gradients_avg5_df.index = df_final_time - gradients_avg20_df.index = df_final_time - gradients_avg60_df.index = df_final_time - - data = data.merge(gradients_low_df, left_index=True, right_index=True) - data = data.merge(gradients_avg5_df, left_index=True, right_index=True) - data = data.merge(gradients_avg20_df, left_index=True, right_index=True) - data = data.merge(gradients_avg60_df, left_index=True, right_index=True) - - return data - - def writeFile(self, dirName, ticker, data, bsLine, type=None): - if bsLine is None: - return - - # 어제 데이터는 지운다. - buy_line = bsLine['buy'] - buy_weight_line = bsLine['buy_weight'] - sell_line = bsLine['sell'] - - buy_size = [] - buy_colors = [] - for i in range(len(buy_line)): - if buy_line[i] < 0: - buy_colors.append("#ffffff") - buy_line[i] = nan - buy_size.append(0) - else: - buy_colors.append("#B2028C") - buy_size.append(10 + (0.1 * buy_weight_line[i])) - - sell_colors = [] - for i in range(len(sell_line)): - if sell_line[i] < 0: - sell_colors.append("#ffffff") - sell_line[i] = nan - else: - sell_colors.append("#00ced1") - - # 그래프를 설정한다. - buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) - sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) - avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') - avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') - avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') - candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) - - macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') - macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') - - # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') - slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') - slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') - - rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') - rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') - - disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') - disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') - disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') - - candle_data = [candle_stick, avg5, avg20, avg60, buy_check, sell_check] - disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] - macd_data = [macd_line, macd_s_line] - stochastic_data = [slow_k_line, slow_d_line] - rsi_data = [rsi_line, rsis_line] - - # 그래프를 그린다. - """ - fig = go.Figure(data=candle_data) - fig.update_layout(title=stock_code + "_" + given_day) - fig.show() - """ - - fig = subplots.make_subplots( - rows=5, cols=1, - subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), - # specs=[[{}], [{}], [{}], [{}], [{}], [{}]], - shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, - row_heights=[200, 200, 200, 200, 750] - ) - for trace in macd_data: - fig.append_trace(trace, 1, 1) - for trace in rsi_data: - fig.append_trace(trace, 2, 1) - for trace in stochastic_data: - fig.append_trace(trace, 3, 1) - for trace in disparity_data: - fig.append_trace(trace, 4, 1) - for trace in candle_data: - fig.append_trace(trace, 5, 1) - - df = pd.DataFrame(bsLine) - df = df.fillna(-1) - buy_count = len(df.loc[df["buy"] > 0]) - sell_count = len(df.loc[df["sell"] > 0]) - - fig.update_layout(height=1700, title="_" + str(buy_count) + "," + str(sell_count)) - fig['layout'].update() - - if type is None: - fileName = "%s/%s_%s.html" % (dirName, ticker, self.TODAY) - po.write_html(fig, file=fileName, auto_open=False) - else: - fileName = "%s/%s_%s_%s.html" % (dirName, type, ticker, self.TODAY) - po.write_html(fig, file=fileName, auto_open=False) - - return - - def notBuy(self, data, i): - if i > 5: - check = True - for l in range(i - 4, i + 1): - if ( - data['gradients_avg60'][l - 1] > data['gradients_avg60'][l] or - data['gradients_avg20'][l - 1] > data['gradients_avg20'][l] or - data['gradients_low'][l - 1] > data['gradients_low'][l] - ): - check = False - break - if not check: - return False - return True - - def checkWithEnvelope(self, data1, data2=None, isRealTime=False): - - bsLine = {} - size = len(data1["close"]) - - bsLine['buy'] = [-1.0 for i in range(size)] - bsLine['buy_weight'] = [-1.0 for i in range(size)] - bsLine['sell'] = [-1.0 for i in range(size)] - bsLine['sell_weight'] = [-1.0 for i in range(size)] - - for i in range(size): - if isRealTime: - if i < size - 1: - continue - - if i > 10: - - if data1['slow_k'][i] < 20: - if data1['slow_k'][i - 1] < data1['slow_d'][i - 1] and data1['slow_d'][i] < data1['slow_k'][i]: - buy = data1['low'][i] - data1['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 0.3 - - if data2['slow_k'][i] < 30 and data1['slow_k'][i] < 30: - if data1['slow_k'][i-1] < data1['slow_d'][i-1] and data1['slow_d'][i] < data2['slow_k'][i]: - buy = data1['close'][i] - data1['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 0.3 - - - if data2['slow_k'][i] < 30: - if data1['slow_k'][i] < 30: - if data1['avg5'][i] < data1['close'][i]: - buy = data1['close'][i] - data1['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 0.2 - - if data1['slow_k'][i-1] < data1['slow_d'][i-1] and data1['slow_d'][i] < data2['slow_k'][i]: - buy = data1['close'][i] - data1['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 0.3 - - if data2['slow_k'][i] > 90: - if (data1['slow_d'][i-1] < data1['slow_k'][i-1] and data1['slow_k'][i] < data1['slow_d'][i]): - sell = data1['close'][i] - data1['sell'][i] = sell - bsLine['sell'][i] = sell - bsLine['sell_weight'][i] = 100 - - if data1['slow_k'][i] > 95 and data1['slow_k'][i] < data1['slow_d'][i]: - sell = data1['close'][i] - data1['sell'][i] = sell - bsLine['sell'][i] = sell - bsLine['sell_weight'][i] = 100 - - if data2['slow_k'][i] > 98 and data1['slow_k'][i] > 98: - sell = data1['close'][i] - data1['sell'][i] = sell - bsLine['sell'][i] = sell - bsLine['sell_weight'][i] = 100 - - return bsLine - - def get_ohlcv(self, ticker, minute=5): - url = "https://api.upbit.com/v1/candles/minutes/"+str(minute) - querystring = {"market": "KRW-"+ticker, "count": "300"} - response = requests.request("GET", url, params=querystring) - json_response = json.loads(response.text) - - btc_ohlcv = [] - for json_data in json_response: - btc_ohlcv.append({'datetime': datetime.strptime(json_data['candle_date_time_kst'], '%Y-%m-%dT%H:%M:%S'), 'open': json_data['opening_price'], 'high': json_data['high_price'], 'low': json_data['low_price'], 'close': json_data['trade_price'], 'volume': json_data['candle_acc_trade_volume']}) - btc_ohlcv = sorted(btc_ohlcv, key=lambda item: (item['datetime'])) - - df = pd.DataFrame(btc_ohlcv, columns=['datetime', 'open', 'high', 'low', 'close', 'volume']) - df['datetime'] = pd.to_datetime(df['datetime'], unit='ms') - df.set_index('datetime', inplace=True) - df.insert(1, "datetime", df.index) - return df - - def cancel_order(self, log_df, log_filename, min=5): - - now = datetime.now() - timedelta(minutes=min) - # min 분 이상 된 시간인 내용을 가지고 옴 - df = log_df.loc[(log_df.index <= now) ] - # 취소가 되지 않은 것만 가지고 옴 (0: 취소 되지 않음, 1: 취소함) - df = df.loc[(log_df["canceled"] == 0)] - - if df is not None: - for i in range(len(df)): - order = (df['order0'][i], df['order1'][i], df['order2'][i], df['order3'][i]) - cancel = self.bithumb.cancel_order(order) - # slackbot에 메시지를 보냄 - #self.slackBot.post_to_slack(ticker, self.stock_code[ticker], "CANCEL", -1, -1) - - for i in range(len(df)): - log_df.loc[(log_df.index == df.index[i]), 'canceled'] = 1 - - log_df.to_csv(log_filename, index=False) - - return log_df - - def check_buy_history(self, log_df, min=10): - # min 분 이상 된 시간인 내용을 가지고 옴 - now = datetime.now() - timedelta(minutes=min) - # 취소가 되지 않은 것만 가지고 옴 (0: 취소 되지 않음, 1: 취소함) - log_df = log_df.loc[(now < log_df.index)] - - if len(log_df) == 0: - return False - - return True - - def getStock(self, ticker, analyzed_day, minute=5, day=None): - stock = {"CODE": ticker, "NAME": ticker, "PRICE": []} - - if day is None: - df = self.get_ohlcv(ticker, minute) - else: - df = pybithumb.get_ohlcv(ticker) - df["datetime"] = df.index - close = pybithumb.get_current_price(ticker) - if df is None or close is None: - return - - size = len(df) - df['close'][size - 1] = close - if close < df['low'][size - 1]: - df['low'][size - 1] = close - if df['high'][size - 1] < close: - df['high'][size - 1] = close - self.append(df, stock) - - data = self.analyze(stock, analyzed_day) - # 분석일 데이터만 활용한다 (이전 데이터는 제거) - data.drop(data.index[:len(data) - analyzed_day], inplace=True) - - return data - - def getXRPCount(self, price): - MAX_BUY_PRICE = 1000 - if 870 < price: MAX_BUY_PRICE = 1000 - elif 840 <= price < 870: MAX_BUY_PRICE = 2000 - elif 810 <= price < 840: MAX_BUY_PRICE = 3000 - elif 780 <= price < 810: MAX_BUY_PRICE = 4000 - elif 750 <= price < 780: MAX_BUY_PRICE = 5000 - elif 720 <= price < 750: MAX_BUY_PRICE = 6000 - elif 690 <= price < 720: MAX_BUY_PRICE = 7000 - elif 660 <= price < 690: MAX_BUY_PRICE = 8000 - elif 630 <= price < 660: MAX_BUY_PRICE = 9000 - elif 600 <= price < 630: MAX_BUY_PRICE = 10000 - elif 570 <= price < 600: MAX_BUY_PRICE = 20000 - elif 540 <= price < 570: MAX_BUY_PRICE = 30000 - elif 510 <= price < 540: MAX_BUY_PRICE = 40000 - elif 450 <= price < 480: MAX_BUY_PRICE = 50000 - elif 420 <= price < 450: MAX_BUY_PRICE = 60000 - elif 390 <= price < 420: MAX_BUY_PRICE = 70000 - elif 360 <= price < 390: MAX_BUY_PRICE = 80000 - elif 330 <= price < 360: MAX_BUY_PRICE = 90000 - elif 300 <= price < 330: MAX_BUY_PRICE = 100000 - elif 270 <= price < 300: MAX_BUY_PRICE = 110000 - elif 240 <= price < 270: MAX_BUY_PRICE = 120000 - elif 210 <= price < 240: MAX_BUY_PRICE = 130000 - elif 180 <= price < 210: MAX_BUY_PRICE = 140000 - elif 150 <= price < 180: MAX_BUY_PRICE = 150000 - elif 120 <= price < 150: MAX_BUY_PRICE = 160000 - elif 90 <= price < 120: MAX_BUY_PRICE = 170000 - elif 60 <= price < 90: MAX_BUY_PRICE = 180000 - elif 30 <= price < 60: MAX_BUY_PRICE = 190000 - elif price < 30: MAX_BUY_PRICE = 200000 - else: MAX_BUY_PRICE = 1000 - - count = int(MAX_BUY_PRICE / price) - return count - - def buyRealTime(self, ticker, analyzed_day=120, isRealTime=False): - - """ - # binance - btc_ohlcv = self.binance.fetch_ohlcv(ticker + "/BKRW") - df = pd.DataFrame(btc_ohlcv, columns=['datetime', 'open', 'high', 'low', 'close', 'volume']) - df['datetime'] = pd.to_datetime(df['datetime'], unit='ms') - df.set_index('datetime', inplace=True) - """ - - """ - # bithumb - df_ = pybithumb.get_ohlcv(ticker) - """ - - stock1 = self.getStock(ticker, analyzed_day, minute=5) - stock2 = self.getStock(ticker, analyzed_day, minute=30) - - # 매수 매도 체크 - bsLine = self.checkWithEnvelope(stock1, stock2, isRealTime=isRealTime) - print(ticker, "/", datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "/", stock1['close'][len(stock1['close'])-1], "/", "{:.2f}".format(stock2['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock1['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock2['macd'][len(stock2['macd']) - 1]), "/", "{:.2f}".format(stock1['macd'][len(stock1['macd']) - 1])) - - # 그래프를 그린다. - if len(stock1.index) > 10: - # 매수 요청 n분 이상된 주문은 취소하기 위함 - order_log_filename = os.path.join(RESOURCE_PATH, 'order', "bithumb"+"_"+self.TODAY + '.log') - if os.path.exists(order_log_filename): - order_log_df = pd.read_csv(order_log_filename) - order_log_df.columns = ["type", "datetime", "order0", "order1", "order2", "order3", "canceled", "slow_k_30", "slow_k_5", "price", "count"] - order_log_df["datetime"] = pd.to_datetime(order_log_df["datetime"], format='%Y-%m-%d %H:%M:%S') - else: - order_log_df = pd.DataFrame(columns=["type", "datetime", "order0", "order1", "order2", "order3", "canceled", "slow_k_30", "slow_k_5", "price", "count"]) - order_log_df['datetime'] = pd.to_datetime(order_log_df['datetime'], unit='s') - order_log_df.set_index('datetime', inplace=True) - order_log_df.insert(1, "datetime", order_log_df.index) - - # 10분이 지난 미체결은 취소한다. - order_log_df = self.cancel_order(order_log_df, order_log_filename, min=10) - # 한번 매수 후 n분 이후 매수하기 위함 - check_buy_history = self.check_buy_history(order_log_df, min=60) - - if isRealTime and not check_buy_history: - # 매수 조건 - if max(bsLine['buy'][len(bsLine['buy']) - 2:]) > 100: - - #stock = self.getStock(ticker, analyzed_day, day=30) - #if stock["slow_k"][len(stock['close'])-1] > 40: - # print (datetime.now().strftime('%Y-%m-%d %H:%M:%S'), ",", round(stock["slow_k"][len(stock['close'])-3],2), ",", round(stock["slow_k"][len(stock['close'])-2],2), ",", round(stock["slow_k"][len(stock['close'])-1], )) - # return - - # [잔고 확인하기] - # - 비트코인의 총 잔고 - # - 거래 중인 비트코인의 수량 - # - 보유 중인 총원화 - # - 주문에 사용된 원화 - # (4.978e-05, 0.0, 3438133.120299, 0) - tmp = self.bithumb.get_balance(ticker) - balance = tmp[2] - count = self.getXRPCount(bsLine['buy'][len(bsLine['buy']) - 1]) - - # 매수를 요청한다. - order = self.bithumb.buy_limit_order(ticker, bsLine['buy'][len(bsLine['buy']) - 1], count) - # slackbot에 메시지를 보냄 - self.slackBot.post_to_slack(ticker, self.stock_code[ticker], "BUY", bsLine['buy'][len(bsLine['buy']) - 1], count) - - # order: ('bid', 'BTC', 'C0101000000322993432', 'KRW') - if len(stock1['close']) > 0: - print(ticker, "/", datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "/", stock1['close'][len(stock1['close'])-1], "/", "{:.2f}".format(stock2['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock1['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock2['macd'][len(stock2['macd']) - 1]), "/", "{:.2f}".format(stock1['macd'][len(stock1['macd']) - 1]), "/", bsLine['buy'][len(bsLine['buy']) - 1], "/", count) - datetime_value = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - value = {"type": "BUY", "datetime": datetime_value, "order0": order[0], "order1": order[1], "order2": order[2], "order3": order[3], "canceled": 0, "slow_k_30": stock2['slow_k'][len(stock2['slow_k']) - 1], "slow_k_5": stock1['slow_k'][len(stock1['slow_k']) - 1], "price": bsLine['buy'][len(bsLine['buy']) - 1], "count": count} - value_df = pd.DataFrame(value, index=[datetime_value]) - value_df["datetime"] = pd.to_datetime(value_df["datetime"], format='%Y-%m-%d %H:%M:%S') - indexes1 = order_log_df.index.tolist() - indexes1.append(datetime_value) - - order_log_df = order_log_df.append(value_df, ignore_index = True) - order_log_df.index = indexes1 - order_log_df['datetime'] = order_log_df.index - order_log_df.to_csv(order_log_filename, index=False) - - # 파일에 매수 시점 그래프 - #dirName = os.path.join(RESOURCE_PATH, 'analysis', 'bithumb') - #self.writeFile(dirName, ticker, stock1, bsLine, 'buy') - - """ - if max(bsLine['sell'][len(bsLine['sell']) - 2:]) > 100: - # [잔고 확인하기] - # - 비트코인의 총 잔고 - # - 거래 중인 비트코인의 수량 - # - 보유 중인 총원화 - # - 주문에 사용된 원화 - # (4.978e-05, 0.0, 3438133.120299, 0) - tmp = self.bithumb.get_balance(ticker) - if tmp is None: - return - count = tmp[0] - tmp[1] - - # 매도를 요청한다. - order = self.bithumb.sell_limit_order(ticker, bsLine['sell'][len(bsLine['sell'])-1], count) - # slackbot에 메시지를 보냄 - self.slackBot.post_to_slack(ticker, self.stock_code[ticker], "SELL", bsLine['sell'][len(bsLine['sell']) - 1], count) - - if len(order) > 2 and len(stock1['close']) > 0: - print(ticker, "/", datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "/", stock1['close'][len(stock1['close'])-1], "/", "{:.2f}".format(stock2['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock1['slow_k'][len(stock1['slow_k'])-1]), "/", "{:.2f}".format(stock2['macd'][len(stock2['macd']) - 1]), "/", "{:.2f}".format(stock1['macd'][len(stock1['macd']) - 1]), "/", bsLine['sell'][len(bsLine['sell']) - 1], "/", count) - value = {"type": "SELL","order0": order[0], "order1": order[1], "order2": order[2], "order3": order[3], "canceled": 0, "slow_k_30": stock2['slow_k'][len(stock2['slow_k']) - 1], "slow_k_5": stock1['slow_k'][len(stock1['slow_k']) - 1], "price": bsLine['sell'][len(bsLine['sell']) - 1], "count": count} - datetime_value = datetime.now().strftime('%Y-%m-%d %H:%M:%S') - value_df = pd.DataFrame(value, index=[datetime_value]) - - indexes = order_log_df.index.tolist() - indexes.append(datetime_value) - - order_log_df = order_log_df.append(value_df, ignore_index=True) - order_log_df.index = indexes - order_log_df['datetime'] = order_log_df.index - order_log_df.to_csv(order_log_filename, index=False) - - dirName = os.path.join(RESOURCE_PATH, 'analysis', 'bithumb') - self.writeFile(dirName, ticker, stock1, bsLine, 'sell') - """ - #else: - # dirName = os.path.join(RESOURCE_PATH, 'analysis', 'bithumb') - # self.writeFile(dirName, ticker, stock1, bsLine) - - return - - -if __name__ == "__main__": - - PROJECT_HOME = os.getcwd() - RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") - - if not os.path.exists(os.path.join(RESOURCE_PATH, 'analysis', 'bithumb')): - os.mkdir(os.path.join(RESOURCE_PATH, 'analysis', 'bithumb')) - dirName = os.path.join(RESOURCE_PATH, 'analysis', 'bithumb') - if not os.path.exists(dirName): - os.mkdir(dirName) - - # bithumb_daily = Bithumb_daily(RESOURCE_PATH) - today = datetime.today().strftime('%Y%m%d') - bithumb = Bithumb_minute(RESOURCE_PATH, today) - - tickers = ['XRP'] - analyzed_day = 120 - isRealTime = True - if isRealTime: - while True: - for ticker in tickers: - #data_daily = bithumb_daily.buyRealTime(ticker, analyzed_day) - #size = len(data_daily) - #if data_daily['slow_k'] < 30: - try: - time.sleep(30) - bithumb.buyRealTime(ticker, analyzed_day, isRealTime) - except: - continue - else: - for ticker in tickers: - bithumb.buyRealTime(ticker, analyzed_day, isRealTime) diff --git a/Simulation_Stock.py b/Simulation.py similarity index 100% rename from Simulation_Stock.py rename to Simulation.py diff --git a/bithumb/Bithumb_Example.py b/bithumb/Bithumb_Example.py deleted file mode 100644 index c844ddd..0000000 --- a/bithumb/Bithumb_Example.py +++ /dev/null @@ -1,87 +0,0 @@ -import pybithumb - -con_key = "946dd0b0e6f8ad411144cd33f09518d3" # 본인의 Connect Key를 입력한다. -sec_key = "56b2a3cdd9fe3a82aa3f38c97c161125" # 본인의 Secret Key를 입력한다. - -# bithumb api에 연결한 클라스 객체를 선언한다. -bithumb = pybithumb.Bithumb(con_key, sec_key) - -def bull_market(ticker): - df = pybithumb.get_ohlcv(ticker) - m5 = df['close'].rolling(5).mean() - last_m5 = m5[-2] - - price = pybithumb.get_current_price(ticker) - - if price > last_m5: - return True - else: - return False - - -# 상장된 코인 Tickers 확인하기 -#print (bithumb.get_tickers()) - -tickers = ['XRP'] - - -for ticker in tickers: - # 과거 시세 얻기 - result = pybithumb.get_ohlcv(ticker) - print(result) - - is_bull = bull_market(ticker) - if is_bull: - print(ticker, "상승장") - else: - print(ticker, "하락장") - - # [잔고 확인하기] - # - 비트코인의 총 잔고 - # - 거래 중인 비트코인의 수량 - # - 보유 중인 총원화 - # - 주문에 사용된 원화 - # (4.978e-05, 0.0, 3438133.120299, 0) - print (bithumb.get_balance(ticker)) - - # [매수] - # buy_limit_order() 메서드의 파라미터로 구매하고자 하는 가상화폐의 - # 티커, 지정가, 매수 수량을 순서대로 입력합니다 - # order = ('bid', 'BTC', 'C0101000000322993432', 'KRW') - order = bithumb.buy_limit_order(ticker, 300, 1) - print(order) - - # 미체결 주문 확인 - # get_balance를 통해 지정가 주문이 들어간 금액만큼 매수에 사용된 원화의 값이 확인된다. 39098.5에 해당된다. - # (0.04588863, 0.0, 3438133.120299, 39098.5) - # - 총 보유 수량 - # - 현재 매도 거래에 사용 중인 코인 수량 - # - 현재 보유하고 있는 원화 보유량. 즉 현금 보유액 - # - 현재 매수 거래에 사용 중인 원화 보유량 - print (bithumb.get_balance(ticker)) - - # 주문 취소 하기 - cancel = bithumb.cancel_order(order) - print(cancel) # True - - # 호가창 Order Book 살펴보기 - orderbook = pybithumb.get_orderbook('BTC') - print (orderbook) - # bids의 최상단 66883000.0원이 매수 최상단 금액 (매수자가 기꺼이 지불하려고 하는 최대 금액) - # asks의 최상단 66919000.0원이 매도 최하단 금액 (판매자가 판매하고자 하는 최소 금액) - """ - {'timestamp': '1616913007272', - 'payment_currency': 'KRW', - 'order_currency': 'BTC', - 'bids': [{'price': 66883000.0, 'quantity': 0.0951}, - {'price': 66881000.0, 'quantity': 0.0607}, - {'price': 66880000.0, 'quantity': 0.503}, - {'price': 66878000.0, 'quantity': 0.0415}, - {'price': 66868000.0, 'quantity': 0.0293}], - 'asks': [{'price': 66919000.0, 'quantity': 0.9946}, - {'price': 66927000.0, 'quantity': 0.002}, - {'price': 66936000.0, 'quantity': 0.0382}, - {'price': 66937000.0, 'quantity': 0.1541}, - {'price': 66939000.0, 'quantity': 0.188}]} - """ - diff --git a/bithumb/Bithumb_daily.py b/bithumb/Bithumb_daily.py deleted file mode 100644 index 62f9696..0000000 --- a/bithumb/Bithumb_daily.py +++ /dev/null @@ -1,680 +0,0 @@ -import csv -import os -import time -import pybithumb -import pandas as pd -from math import nan -import plotly.io as po -from plotly import subplots -import plotly.graph_objects as go -from datetime import datetime -from sklearn.linear_model import LinearRegression -from sklearn.preprocessing import StandardScaler, MinMaxScaler - -from stock.analysis.AnalyzerSqlite import AnalyzerSqlite -from hts.BuySellChecker import BuySellChecker -from hts.HTS import HTS - -class Bithumb_daily(HTS): - - RESOURCE_PATH = None - buySellChecker = None - analyzerSqlite = None - - def __init__(self, RESOURCE_PATH): - super().__init__(RESOURCE_PATH) - self.RESOURCE_PATH = RESOURCE_PATH - - con_key = "946dd0b0e6f8ad411144cd33f09518d3" # 본인의 Connect Key를 입력한다. - sec_key = "56b2a3cdd9fe3a82aa3f38c97c161125" # 본인의 Secret Key를 입력한다. - - # bithumb api에 연결한 클라스 객체를 선언한다. - self.bithumb = pybithumb.Bithumb(con_key, sec_key) - - self.buySellChecker = BuySellChecker() - self.analyzerSqlite = AnalyzerSqlite() - - return - - def bull_market(self, df, ticker): - m5 = df['close'].rolling(5).mean() - last_m5 = m5[-2] - - price = pybithumb.get_current_price(ticker) - - if price > last_m5: - return True - - return False - - def append(self, df, stock): - for i in range(len(df)): - stock['PRICE'].append( - { - "ymd": df.index[i].strftime('%Y.%m.%d'), - "close": df['close'][i], - "diff": 0, - "open": df['open'][i], - "high": df['high'][i], - "low": df['low'][i], - "volume": df['volume'][i], - "avg3": -1, - "avg4": -1, - "avg5": -1, - "avg6": -1, - "avg10": -1, - "avg12": -1, - "avg20": -1, - "avg36": -1, - "avg40": -1, - "avg48": -1, - "avg60": -1, - "avg120": -1, - "avg200": -1, - "avg240": -1, - "avg300": -1, - "disparity_avg5": -1, - "disparity_avg10": -1, - "disparity_avg20": -1, - "disparity_avg60": -1, - "disparity_avg120": -1, - "bolingerband_upper": -1, - "bolingerband_lower": -1, - "bolingerband_middle": -1, - "envelope_upper": -1, - "envelope_lower": -1, - "envelope_middle": -1, - "ichimokucloud_changeLine": -1, - "ichimokucloud_baseLine": -1, - "ichimokucloud_leadingSpan1": -1, - "ichimokucloud_leadingSpan2": -1, - "stochastic_fast_k": -1, - "stochastic_slow_k": -1, - "stochastic_slow_d": -1, - "rsi": -1, - "rsis": -1, - "macd": -1, - "macds": -1, - "macdo": -1, - }) - return - - def analyze (self, stock, days=120): - stock["PRICE"] = sorted(stock["PRICE"], key=lambda x: x['ymd']) - self.analyzerSqlite.get_moving_average(stock["PRICE"]) - - # 이동 평균을 이용한 이격도 계산 - self.analyzerSqlite.get_disparity(stock["PRICE"]) - - self.analyzerSqlite.ichimokuCloud.analyze(stock) - self.analyzerSqlite.stochastic.analyze(stock) - self.analyzerSqlite.bolingerBand.analyze(stock) - self.analyzerSqlite.envelope.analyze(stock) - self.analyzerSqlite.rsi.analyze(stock) - self.analyzerSqlite.macd.analyze(stock) - - result = { - "ymd": [], - "open": [], - "close": [], - "high": [], - "low": [], - "avg3": [], - "avg4": [], - "avg5": [], - "avg6": [], - "avg10": [], - "avg12": [], - "avg20": [], - "avg36": [], - "avg40": [], - "avg48": [], - "avg60": [], - "avg120": [], - "avg200": [], - "avg240": [], - "avg300": [], - "disparity_avg5": [], - "disparity_avg20": [], - "disparity_avg60": [], - "disparity_avg120": [], - "disparity": [], - "disparity_type": [], - "envelope_upper": [], - "envelope_lower": [], - "envelope_middle": [], - "rsi": [], - "rsis": [], - "macd": [], - "macds": [], - "slow_k": [], - "slow_d": [], - "buy": [], - "sell": [], - } - for item in stock['PRICE']: - result["ymd"].append(item['ymd']) - result["open"].append(item['open']) - result["close"].append(item['close']) - result["high"].append(item['high']) - result["low"].append(item['low']) - result["avg3"].append(item['avg3']) - result["avg4"].append(item['avg4']) - result["avg5"].append(item['avg5']) - result["avg6"].append(item['avg6']) - result["avg10"].append(item['avg10']) - result["avg12"].append(item['avg12']) - result["avg20"].append(item['avg20']) - result["avg36"].append(item['avg36']) - result["avg40"].append(item['avg40']) - result["avg48"].append(item['avg48']) - result["avg60"].append(item['avg60']) - result["avg120"].append(item['avg120']) - result["avg200"].append(item['avg200']) - result["avg240"].append(item['avg240']) - result["avg300"].append(item['avg300']) - result["disparity_avg5"].append(item['disparity_avg5']) - result["disparity_avg20"].append(item['disparity_avg20']) - result["disparity_avg60"].append(item['disparity_avg60']) - result["disparity_avg120"].append(item['disparity_avg120']) - result['disparity'].append(max(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60']) - min(item['disparity_avg5'], item['disparity_avg20'], item['disparity_avg60'])) - if item['disparity_avg60'] < item['disparity_avg20'] < item['disparity_avg5']: - result['disparity_type'].append(1) - elif item['disparity_avg5'] < item['disparity_avg20'] < item['disparity_avg60']: - result['disparity_type'].append(-1) - else: - result['disparity_type'].append(0) - result["envelope_upper"].append(item['envelope_upper']) - result["envelope_lower"].append(item['envelope_lower']) - result["envelope_middle"].append(item['envelope_middle']) - result["rsi"].append(item['rsi']) - result["rsis"].append(item['rsis']) - result["macd"].append(item['macd']) - result["macds"].append(item['macds']) - result["slow_k"].append(item['stochastic_slow_k']) - result["slow_d"].append(item['stochastic_slow_d']) - result["buy"].append(-1) - result["sell"].append(-1) - - data = pd.DataFrame(result) - df_final_time = pd.DatetimeIndex(result['ymd']) - data.index = df_final_time - - data = data.astype( - { - 'open': 'int', - 'high': 'int', - 'low': 'int', - 'close': 'int', - 'avg3': 'float', - 'avg4': 'float', - 'avg5': 'float', - 'avg6': 'float', - 'avg10': 'float', - 'avg12': 'float', - 'avg20': 'float', - 'avg36': 'float', - 'avg40': 'float', - 'avg48': 'float', - 'avg60': 'float', - 'avg120': 'float', - 'avg200': 'float', - 'avg240': 'float', - 'avg300': 'float', - 'disparity_avg5': 'float', - 'disparity_avg20': 'float', - 'disparity_avg60': 'float', - 'disparity_avg120': 'float', - 'buy': 'int', - 'sell': 'int', - 'slow_k': 'float', - 'slow_d': 'float', - 'macd': 'float', - 'macds': 'float', - 'envelope_upper': 'float', - 'envelope_lower': 'float', - 'envelope_middle': 'float', - 'rsi': 'float', - 'rsis': 'float' - } - ) - - scaler = StandardScaler() - low_df = pd.DataFrame(data['low']) - low_df.index = [c for c in range(len(low_df))] - low_std = scaler.fit_transform(data['low'].values.reshape(-1, 1)) - low_std = pd.DataFrame(low_std, columns=['low_std']) - - min_df = pd.DataFrame({'open': data['open'].to_list(), 'close': data['close'].to_list()}) - min_df['min_std'] = min_df.min(axis=1) - min_df.index = [c for c in range(len(min_df))] - min_std = scaler.fit_transform(min_df['min_std'].values.reshape(-1, 1)) - min_std = pd.DataFrame(min_std, columns=['min_std']) - - line_fitter = LinearRegression() - size = len(data["close"]) - gradients_low = [] - gradients_avg5 = [] - gradients_avg20 = [] - gradients_avg60 = [] - - for i in range(size): - coef_low = -999 - coef_avg5 = -999 - coef_avg20 = -999 - coef_avg60 = -999 - - if i > 0: - l = days if i >= days else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(low_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_low = line_fitter.coef_[0][0] - - l = 5 if i >= 5 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg5 = line_fitter.coef_[0][0] - - l = 20 if i >= 20 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg20 = line_fitter.coef_[0][0] - - l = 60 if i >= 60 else i - x = pd.DataFrame([c for c in range(i - l, i + 1)]) - y = pd.DataFrame(min_std.values.tolist()[i - l:i + 1]) - line_fitter.fit(x.values.reshape(-1, 1), y) - coef_avg60 = line_fitter.coef_[0][0] - - gradients_low.append(coef_low) - gradients_avg5.append(coef_avg5) - gradients_avg20.append(coef_avg20) - gradients_avg60.append(coef_avg60) - - gradients_low_df = pd.DataFrame(gradients_low, columns=['gradients_low']) - gradients_avg5_df = pd.DataFrame(gradients_avg5, columns=['gradients_avg5']) - gradients_avg20_df = pd.DataFrame(gradients_avg20, columns=['gradients_avg20']) - gradients_avg60_df = pd.DataFrame(gradients_avg60, columns=['gradients_avg60']) - - gradients_low_df.index = df_final_time - gradients_avg5_df.index = df_final_time - gradients_avg20_df.index = df_final_time - gradients_avg60_df.index = df_final_time - - data = data.merge(gradients_low_df, left_index=True, right_index=True) - data = data.merge(gradients_avg5_df, left_index=True, right_index=True) - data = data.merge(gradients_avg20_df, left_index=True, right_index=True) - data = data.merge(gradients_avg60_df, left_index=True, right_index=True) - - return data - - def writeFile(self, dirName, ticker, data, bsLine, today): - if bsLine is None: - return - - # 어제 데이터는 지운다. - buy_line = bsLine['buy'] - buy_weight_line = bsLine['buy_weight'] - sell_line = bsLine['sell'] - - buy_size = [] - buy_colors = [] - for i in range(len(buy_line)): - if buy_line[i] < 0: - buy_colors.append("#ffffff") - buy_line[i] = nan - buy_size.append(0) - else: - buy_colors.append("#B2028C") - buy_size.append(10 + (0.1 * buy_weight_line[i])) - - sell_colors = [] - for i in range(len(sell_line)): - if sell_line[i] < 0: - sell_colors.append("#ffffff") - sell_line[i] = nan - else: - sell_colors.append("#00ced1") - - # 그래프를 설정한다. - buy_check = go.Scatter(x=data['ymd'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0)) - sell_check = go.Scatter(x=data['ymd'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0)) - envelope_upper = go.Scatter(x=data['ymd'], y=data["envelope_upper"], name="upper", line_color='#000000') - envelope_middle = go.Scatter(x=data['ymd'], y=data["envelope_middle"], name="middle", line_color='#927786') - envelope_lower = go.Scatter(x=data['ymd'], y=data["envelope_lower"], name="lower", line_color='#000000') - - avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#6C2507') - avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#f84c43') - avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#f89543') - candle_stick = go.Candlestick(x=data['ymd'], open=data['open'], high=data['high'], low=data['low'], close=data['close'], increasing_line_color='red', decreasing_line_color='blue', showlegend=False) - - macd_line = go.Scatter(x=data['ymd'], y=data["macd"], line=dict(color='red', width=2), name='macd') - macd_s_line = go.Scatter(x=data['ymd'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds') - - # fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k') - slow_k_line = go.Scatter(x=data['ymd'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k') - slow_d_line = go.Scatter(x=data['ymd'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d') - - rsi_line = go.Scatter(x=data['ymd'], y=data["rsi"], line=dict(color='red', width=2), name='rsi') - rsis_line = go.Scatter(x=data['ymd'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis') - - disparity_avg5 = go.Scatter(x=data['ymd'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#8F8203') - disparity_avg20 = go.Scatter(x=data['ymd'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#ff00ff') - disparity_avg60 = go.Scatter(x=data['ymd'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#1469F4') - - candle_data = [candle_stick, avg5, avg20, avg60, envelope_upper, envelope_middle, envelope_lower, buy_check, sell_check] - disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60] - macd_data = [macd_line, macd_s_line] - stochastic_data = [slow_k_line, slow_d_line] - rsi_data = [rsi_line, rsis_line] - - # 그래프를 그린다. - """ - fig = go.Figure(data=candle_data) - fig.update_layout(title=stock_code + "_" + given_day) - fig.show() - """ - - fig = subplots.make_subplots( - rows=5, cols=1, - subplot_titles=("MACD", "RSI", "스토캐스틱", '이격도', '캔들'), - #specs=[[{}], [{}], [{}], [{}], [{}], [{}]], - shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01, - row_heights=[200, 200, 200, 200, 750] - ) - for trace in macd_data: - fig.append_trace(trace, 1, 1) - for trace in rsi_data: - fig.append_trace(trace, 2, 1) - for trace in stochastic_data: - fig.append_trace(trace, 3, 1) - for trace in disparity_data: - fig.append_trace(trace, 4, 1) - for trace in candle_data: - fig.append_trace(trace, 5, 1) - - df = pd.DataFrame(bsLine) - df = df.fillna(-1) - buy_count = len(df.loc[df["buy"] > 0]) - sell_count = len(df.loc[df["sell"] > 0]) - - fig.update_layout(height=1700, title="_" + str(buy_count)+","+str(sell_count)) - fig['layout'].update() - - fileName = "%s/%s_%s.html" % (dirName, ticker, today) - po.write_html(fig, file=fileName, auto_open=False) - - return - - def getBalance(self, ticker): - tmp = self.bithumb.get_balance(ticker) - return tmp[2] - - def exist_buy(self, ticker, log_filename): - if os.path.exists(log_filename): - log_file = open(log_filename, 'r', ) - reader = csv.reader(log_file) - for line in reader: - if line[2] == ticker: - log_file.close() - return True - log_file.close() - return False - - def notBuy(self, data, i): - if i > 5: - check = True - for l in range(i-4, i+1): - if ( - data['gradients_avg60'][l - 1] > data['gradients_avg60'][l] or - data['gradients_avg20'][l - 1] > data['gradients_avg20'][l] or - data['gradients_low'][l - 1] > data['gradients_low'][l] - ): - check = False - break - if not check: - return False - return True - - def checkWithEnvelope(self, data, analyzed_day=120, isRealTime=False): - - bsLine = {} - size = len(data["close"]) - - bsLine['buy'] = [-1 for i in range(size)] - bsLine['buy_weight'] = [-1 for i in range(size)] - bsLine['sell'] = [-1 for i in range(size)] - bsLine['sell_weight'] = [-1 for i in range(size)] - - gap_interval = analyzed_day - gap_state = False - for i in range(size): - if isRealTime: - if i < size - 1: - continue - - if i > 10: - # 만약 전일 저가와 오늘 종의 차이가 1만원이 넘으면 향후 60일은 분석하지 않는다. - if data['high'][i] < int(data['low'][i - 1] * 0.7): - gap_state = True - gap_interval -= 1 - continue - if gap_state: - if gap_interval <= 0: - gap_state = False - gap_interval = 60 - else: - gap_interval -= 1 - continue - - if data['disparity'][i] < 2: - check = True - for l in range(i - 3, i): - if ( - data['gradients_avg60'][l - 1] > data['gradients_avg60'][l] or - data['gradients_avg20'][l - 1] > data['gradients_avg20'][l] or - data['gradients_low'][l - 1] > data['gradients_low'][l] or - data['disparity_avg5'][l - 1] > data['disparity_avg5'][l] or - data['disparity'][l - 1] < data['disparity'][l] - ): - check = False - break - if check and 99 < sum(data['disparity_avg5'][i - 4:i + 1]) / 5 < 100 and 99 < sum( - data['disparity_avg60'][i - 4:i + 1]) / 5 < 100: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - check = True - for l in range(i - 2, i): - if ( - data['gradients_avg60'][l - 1] > data['gradients_avg60'][l] or - data['gradients_low'][l - 1] > data['gradients_low'][l] - ): - check = False - break - if ( - check and - -0.0011 < data['gradients_low'][i] < 0 and -0.007 < data['gradients_avg5'][i] < 0.001 and - -0.0012 < data['gradients_avg60'][i] < 0 and - 98.90 < data['disparity_avg5'][i] < 101 - ): - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - check = True - for l in range(i - 6, i): - if ( - data['gradients_avg60'][l - 1] < data['gradients_avg60'][l] or - data['gradients_avg20'][l - 1] < data['gradients_avg20'][l] or - data['gradients_low'][l - 1] < data['gradients_low'][l] or - -0.039 < data['gradients_low'][l - 1] < -0.35 or - -0.05 < data['gradients_avg20'][l - 1] < -0.30 or - -0.40 < data['gradients_avg60'][l - 1] < -0.30 - ): - check = False - break - if check and 99 < min(data['disparity_avg5'][i - 6:i]) < max(data['disparity_avg5'][i - 6:i]) < 101: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - check = True - for l in range(i - 3, i): - if ( - data['gradients_low'][l - 1] < data['gradients_low'][l] or - data['gradients_avg60'][l - 1] < data['gradients_avg60'][l] or - data['gradients_avg20'][l - 1] < data['gradients_avg20'][l] or - 0.01 < data['gradients_low'][l - 1] < 0.21 or - -0.09 < data['gradients_avg20'][l - 1] < -0.002 or - 0.01 < data['gradients_avg60'][l - 1] < 0.021 - ): - check = False - break - if check: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - if (data['disparity'][i] < 5 and 99.0 < data['disparity_avg60'][i] < 99.1 and - -0.009 < data['gradients_avg60'][i] < -0.008 and 0.015 < data['gradients_avg20'][i] < 0.016 and - -0.006 < data['gradients_avg5'][i] < -0.005 and -0.009 < data['gradients_low'][i] < -0.008): - check = True - for l in range(i - 5, i): - if ( - data['gradients_avg60'][l - 1] > data['gradients_avg60'][l] or - data['gradients_low'][l - 1] > data['gradients_low'][l] or - data['disparity'][l - 1] < data['disparity'][l] - ): - check = False - break - if check: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - if data['macd'][i] < -4000: - if data['macd'][i - 1] < data['macd'][i]: - if not self.notBuy(data, i) and data['slow_k'][i] < 30: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - # macd 이전에 없던 바닥인 경우 상승할 찰나 매수 - if data['macds'][i - 1] < min(data['macds'][:i - 1]): - if data['macds'][i - 1] < data['macds'][i]: - if not self.notBuy(data, i) and data['slow_k'][i] < 30: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 10 - - if ( - 98 < data['disparity_avg5'][i] < 100 and data['disparity_avg20'][i] < 93.5 and - data['disparity_avg60'][i] < 89 and - -0.014 < data['gradients_avg60'][i] < -0.013 and -0.03 < data['gradients_avg20'][ - i] < -0.02 and -0.014 < data['gradients_low'][i] < -0.013 and - data['slow_k'][i] < 11 - ): - if not self.notBuy(data, i): - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 15 - - if data['slow_k'][i] < 20 and data['slow_k'][i - 1] < data['slow_d'][i - 1] and data['slow_d'][i] < data['slow_k'][i]: - buy = data['low'][i] - data['buy'][i] = buy - bsLine['buy'][i] = buy - bsLine['buy_weight'][i] = 15 - - return bsLine, data - - def buyRealTime(self, ticker, analyzed_day=120, isRealTime=False): - - stock = {"CODE": ticker, "NAME": ticker, "PRICE": []} - df = pybithumb.get_ohlcv(ticker) - if df is None: - return - - close = pybithumb.get_current_price(ticker) - - size = len(df) - df['close'][size - 1] = close - if close < df['low'][size - 1]: - df['low'][size - 1] = close - if df['high'][size - 1] < close: - df['high'][size - 1] = close - self.append(df, stock) - - data = self.analyze(stock, analyzed_day) - - # 분석일 데이터만 활용한다 (이전 데이터는 제거) - data.drop(data.index[:len(data) - analyzed_day], inplace=True) - - bsLine, data = self.checkWithEnvelope(data, analyzed_day, isRealTime=isRealTime) - print(ticker, "/", datetime.now().strftime('%Y-%m-%d %H:%M:%S'), "/", data['close'][len(data['close'])-1], "/", data['slow_k'][len(data['slow_k'])-1]) - - # 그래프를 그린다. - if len(data.index) > 10: - today = datetime.today().strftime('%Y%m%d') - log_filename = os.path.join(RESOURCE_PATH, 'analysis', '', today + '.log') - - # realtime이고, 5분이내 매수 기록이 없다면 - if isRealTime and not self.exist_buy(ticker, log_filename): - if max(bsLine['buy'][len(bsLine['buy']) - 2:]) > 100: - balance = self.getBalance(ticker) - count = round((balance * (bsLine['buy_weight'][len(bsLine['buy_weight'])-1]/100)) / bsLine['buy'][len(bsLine['buy'])-1], 2) - order = self.bithumb.buy_limit_order(ticker, bsLine['buy'][len(bsLine['buy'])-1], count) - # order: ('bid', 'BTC', 'C0101000000322993432', 'KRW') - - with open(log_filename, 'a', newline='', encoding='utf-8') as log_file: - wr = csv.writer(log_file) - wr.writerow([datetime.now().strftime('%Y-%m-%d %H:%M:%S'), order[0], order[1], order[2], order[3]]) - - dirName = os.path.join(RESOURCE_PATH, 'analysis', '') - self.writeFile(dirName, ticker, data, bsLine, datetime.now().strftime('%Y%m%d %H%M%S'), 'buy') - else: - dirName = os.path.join(RESOURCE_PATH, 'analysis', '') - self.writeFile(dirName, ticker, data, bsLine, datetime.now().strftime('%Y%m%d %H%M%S')) - - return bsLine, data - -if __name__ == "__main__": - - PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__)))) - RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources") - - if not os.path.exists(os.path.join(RESOURCE_PATH, 'analysis', '')): - os.mkdir(os.path.join(RESOURCE_PATH, 'analysis', '')) - dirName = os.path.join(RESOURCE_PATH, 'analysis', '') - if not os.path.exists(dirName): - os.mkdir(dirName) - - bithumb = Bithumb_daily(RESOURCE_PATH) - - tickers = ['XRP', 'BTC', 'SOL'] - analyzed_day = 120 - isRealTime = False - if isRealTime: - while True: - try: - for ticker in tickers: - bithumb.buyRealTime(ticker, analyzed_day, isRealTime) - except: - time.sleep(30) - continue - time.sleep(10) - else: - for ticker in tickers: - bithumb.buyRealTime(ticker, analyzed_day, isRealTime)