This commit is contained in:
dsyoon
2023-12-12 00:15:38 +09:00
parent 6b22132b43
commit fbfab6d236
7 changed files with 550 additions and 359 deletions

View File

@@ -1,6 +1,5 @@
import time import time
import os import pandas as pd
import sqlite3
from datetime import datetime from datetime import datetime
from hts.HTS import HTS from hts.HTS import HTS
@@ -11,11 +10,14 @@ from stock.util.LabelChecker import LabelChecker
from stock.util.TelegramBot import TelegramBot from stock.util.TelegramBot import TelegramBot
from stock.analysis.StockStatus import StockStatus from stock.analysis.StockStatus import StockStatus
from hts.BuySellChecker_122630 import BuySellChecker_122630 from stock.analysis.Common import Common
from hts.BuySellChecker_233740 import BuySellChecker_233740 from stock.analysis.Stochastic import Stochastic
from hts.BuySellChecker_251340 import BuySellChecker_251340 from stock.analysis.RSI import RSI
from hts.BuySellChecker_252670 import BuySellChecker_252670 from stock.analysis.MACD import MACD
from stock.analysis.IchimokuCloud import IchimokuCloud
from statsmodels.tsa.seasonal import seasonal_decompose
from hts.BuySellChecker import BuySellChecker
class HTS_etf(HTS): class HTS_etf(HTS):
RESOURCE_PATH = None RESOURCE_PATH = None
@@ -25,10 +27,16 @@ class HTS_etf(HTS):
buy_count = None buy_count = None
orderChecker = None orderChecker = None
buySellChecker = None buySellChecker = None
labelChecker = None
bot = None bot = None
stockStatus = None stockStatus = None
common = None
stochastic = None
rsi = None
macd = None
ichimokuCloud = None
def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP): def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP):
super().__init__(RESOURCE_PATH) super().__init__(RESOURCE_PATH)
@@ -42,19 +50,19 @@ class HTS_etf(HTS):
self.bot = TelegramBot() self.bot = TelegramBot()
self.stockStatus = StockStatus(RESOURCE_PATH) self.stockStatus = StockStatus(RESOURCE_PATH)
self.buySellChecker = None self.common = Common()
if stock_code == '122630': self.stochastic = Stochastic()
self.buySellChecker = BuySellChecker_122630() self.rsi = RSI()
elif stock_code == '233740': self.macd = MACD()
self.buySellChecker = BuySellChecker_233740() self.ichimokuCloud = IchimokuCloud()
elif stock_code == '251340':
self.buySellChecker = BuySellChecker_251340()
elif stock_code == '252670':
self.buySellChecker = BuySellChecker_252670()
self.buySellChecker = BuySellChecker()
return return
def getBallance(self):
return
def sellStocks(self, stock_code=None, bs_sell_price=None): def sellStocks(self, stock_code=None, bs_sell_price=None):
check = False check = False
jangoDic = self.requstJango() jangoDic = self.requstJango()
@@ -64,19 +72,19 @@ class HTS_etf(HTS):
if code == "A" + stock_code: if code == "A" + stock_code:
if bs_sell_price is not None: if bs_sell_price is not None:
if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: if jangoDic[code]['평가손익'] < -1.0 or 2 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도 # 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price) self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price)
check = True check = True
else: else:
if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: if jangoDic[code]['평가손익'] < -1.0 or 2 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도 # 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
check = True check = True
else: else:
if jangoDic[code]['매도가능'] > 0: if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']: if jangoDic[code]['평가손익'] < -1.0 or 2 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도 # 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가']) self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
check = True check = True
@@ -105,6 +113,188 @@ class HTS_etf(HTS):
return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price
return orderNum, None, None, None return orderNum, None, None, None
def analyze(self, result):
# 기본 캔들 정보
open = result["open"]
close = result["close"]
high = result["high"]
low = result["low"]
volume = result["vol"]
if "volume_down" in result:
volume_down = result["volume_down"]
if "volume_up" in result:
volume_up = result["volume_up"]
if "volume_updown_diff" in result:
volume_updown_diff = result["volume_updown_diff"]
# 이동 평균
close_df = pd.DataFrame(close)
avg5_list = close_df.rolling(window=5).mean().fillna(close[0]).values.tolist()
avg5 = [item[0] for item in avg5_list]
avg20_list = close_df.rolling(window=20).mean().fillna(close[0]).values.tolist()
avg20 = [item[0] for item in avg20_list]
avg30_list = close_df.rolling(window=30).mean().fillna(close[0]).values.tolist()
avg30 = [item[0] for item in avg30_list]
avg60_list = close_df.rolling(window=60).mean().fillna(close[0]).values.tolist()
avg60 = [item[0] for item in avg60_list]
avg120_list = close_df.rolling(window=120).mean().fillna(close[0]).values.tolist()
avg120 = [item[0] for item in avg120_list]
avg240_list = close_df.rolling(window=240).mean().fillna(close[0]).values.tolist()
avg240 = [item[0] for item in avg240_list]
avg480_list = close_df.rolling(window=480).mean().fillna(close[0]).values.tolist()
avg480 = [item[0] for item in avg480_list]
avg1500_list = close_df.rolling(window=1500).mean().fillna(close[0]).values.tolist()
avg1500 = [item[0] for item in avg1500_list]
size = int(len(close) / 8)
pos = round(size / 2)
close_temp = close + [close[-1]] * pos
decomposition_results = seasonal_decompose(close_temp, model='multiplicative', period=size)
trend = decomposition_results.trend[:-pos]
trend_df = pd.DataFrame(trend).fillna(close[0])
trend_avg_list = trend_df.rolling(window=20).mean().values.tolist()
trend_avg = [item[0] for item in trend_avg_list]
open_df = pd.DataFrame(close)
disparity_avg5_list = (open_df / close_df.rolling(window=5).mean()).values.tolist()
disparity_avg5 = [item[0] for item in disparity_avg5_list]
disparity_avg20_list = (open_df / close_df.rolling(window=20).mean()).values.tolist()
disparity_avg20 = [item[0] for item in disparity_avg20_list]
disparity_avg30_list = (open_df / close_df.rolling(window=30).mean()).values.tolist()
disparity_avg30 = [item[0] for item in disparity_avg30_list]
disparity_avg60_list = (open_df / close_df.rolling(window=60).mean()).values.tolist()
disparity_avg60 = [item[0] for item in disparity_avg60_list]
disparity_avg120_list = (open_df / close_df.rolling(window=120).mean()).values.tolist()
disparity_avg120 = [item[0] for item in disparity_avg120_list]
disparity_avg240_list = (open_df / close_df.rolling(window=240).mean()).values.tolist()
disparity_avg240 = [item[0] for item in disparity_avg240_list]
disparity_avg480_list = (open_df / close_df.rolling(window=480).mean()).values.tolist()
disparity_avg480 = [item[0] for item in disparity_avg480_list]
disparity_avg1500_list = (open_df / close_df.rolling(window=1500).mean()).values.tolist()
disparity_avg1500 = [item[0] for item in disparity_avg1500_list]
# 볼린져 밴드
df = pd.DataFrame(close)
max20 = df.rolling(window=20).mean()
stddev20 = df.rolling(window=20).std()
upper_df = max20 + (stddev20 * 2) # 상단 볼린저 밴드
lower_df = max20 - (stddev20 * 2) # 하단 볼린저 밴드
middle_df = (upper_df + lower_df) / 2
upper_limit_df = upper_df - (upper_df - lower_df) * 0.1
lower_limit_df = (upper_df - lower_df) * 0.15 + lower_df
upper, lower, middle, upper_limit, lower_limit = [], [], [], [], []
for i in range(len(upper_df)):
if i < 10:
upper.append(upper_df.values[0][0])
lower.append(lower_df.values[0][0])
middle.append(middle_df.values[0][0])
upper_limit.append(upper_limit_df.values[0][0])
lower_limit.append(lower_limit_df.values[0][0])
else:
upper.append(upper_df.values[i][0])
lower.append(lower_df.values[i][0])
middle.append(middle_df.values[i][0])
upper_limit.append(upper_limit_df.values[i][0])
lower_limit.append(lower_limit_df.values[i][0])
upper, lower = [], []
for i in range(len(upper_df)):
if i < 10:
upper.append(upper_df.values[0][0])
lower.append(lower_df.values[0][0])
else:
upper.append(upper_df.values[i][0])
lower.append(lower_df.values[i][0])
point_temp = result["time"]
STOCK = []
if "volume_up" in result and "volume_updown_diff" in result:
for i in range(len(open)):
STOCK.append({'volume': volume[i], 'volume_down': volume_down[i], 'volume_up': volume_up[i], 'volume_updown_diff': volume_updown_diff[i], 'close': close[i], 'open': open[i], 'high': high[i], 'low': low[i],
'avg5': avg5[i], 'avg20': avg20[i], 'avg60': avg60[i], 'avg120': avg120[i], 'avg240': avg240[i], 'avg480': avg480[i], 'avg1500': avg1500[i]})
else:
for i in range(len(open)):
STOCK.append({'volume': volume[i], 'close': close[i], 'open': open[i], 'high': high[i], 'low': low[i],
'avg5': avg5[i], 'avg20': avg20[i], 'avg60': avg60[i], 'avg120': avg120[i], 'avg240': avg240[i], 'avg480': avg480[i], 'avg1500': avg1500[i]})
# stochastic
stochastic_df = self.stochastic.apply(STOCK, n=30, m=5, t=5)
fast_k = stochastic_df['fast_k'].values.tolist()
slow_k = stochastic_df['slow_k'].values.tolist()
slow_d = stochastic_df['slow_d'].values.tolist()
# macd
#macd_df = self.macd.apply(STOCK, short=12, long=26, t=9)
macd_df = self.macd.apply(STOCK, short=5, long=20, t=5)
macd = macd_df['macd'].values.tolist()
macds = macd_df['macds'].values.tolist()
macdo = macd_df['macdo'].values.tolist()
# rsi
rsi_df = self.rsi.apply(STOCK, period=30, window=5)
rsi = rsi_df['rsi'].values.tolist()
rsis = rsi_df['rsis'].values.tolist()
# ichimokuCloud
ichimokuCloud_df = self.ichimokuCloud.apply(STOCK, c=9, b=26, l=52)
ichimokuCloud_df = ichimokuCloud_df[:len(ichimokuCloud_df) - 51]
changeLine = ichimokuCloud_df['changeLine'].values.tolist()
baseLine = ichimokuCloud_df['baseLine'].values.tolist()
laggingSpan = ichimokuCloud_df['laggingSpan'].values.tolist()
leadingSpan1 = ichimokuCloud_df['leadingSpan1'].values.tolist()
leadingSpan2 = ichimokuCloud_df['leadingSpan2'].values.tolist()
# 결과
if "volume_up" in result and "volume_updown_diff" in result:
temp = {
"ymd": point_temp,
"open": open, "high": high, "low": low, "close": close, "volume": volume, "volume_down": volume_down,
"volume_up": volume_up, "volume_updown_diff": volume_updown_diff,
"trend": trend, "trend_avg": trend_avg,
"avg5": avg5, "avg20": avg20, "avg60": avg60, "avg120": avg120, "avg240": avg240, "avg480": avg480,
"avg1500": avg1500,
"disparity_avg5": disparity_avg5, "disparity_avg20": disparity_avg20,
"disparity_avg30": disparity_avg30, "disparity_avg60": disparity_avg60,
"disparity_avg120": disparity_avg120, "disparity_avg240": disparity_avg240,
"disparity_avg480": disparity_avg480, "disparity_avg1500": disparity_avg1500,
"upper": upper, "lower": lower, 'middle': middle, 'upper_limit': upper_limit,
'lower_limit': lower_limit,
"macd": macd, "macds": macds, "macdo": macdo,
"fast_k": fast_k, "slow_k": slow_k, "slow_d": slow_d,
"rsi": rsi, "rsis": rsis,
"changeLine": changeLine, "baseLine": baseLine, "laggingSpan": laggingSpan,
"leadingSpan1": leadingSpan1, "leadingSpan2": leadingSpan2,
}
else:
temp = {
"ymd": point_temp,
"open": open, "high": high, "low": low, "close": close, "volume": volume,
"trend": trend, "trend_avg": trend_avg,
"avg5": avg5, "avg20": avg20, "avg60": avg60, "avg120": avg120, "avg240": avg240, "avg480": avg480,
"avg1500": avg1500,
"disparity_avg5": disparity_avg5, "disparity_avg20": disparity_avg20,
"disparity_avg30": disparity_avg30, "disparity_avg60": disparity_avg60,
"disparity_avg120": disparity_avg120, "disparity_avg240": disparity_avg240,
"disparity_avg480": disparity_avg480, "disparity_avg1500": disparity_avg1500,
"upper": upper, "lower": lower, 'middle': middle, 'upper_limit': upper_limit,
'lower_limit': lower_limit,
"macd": macd, "macds": macds, "macdo": macdo,
"fast_k": fast_k, "slow_k": slow_k, "slow_d": slow_d,
"rsi": rsi, "rsis": rsis,
"changeLine": changeLine, "baseLine": baseLine, "laggingSpan": laggingSpan,
"leadingSpan1": leadingSpan1, "leadingSpan2": leadingSpan2,
}
data = pd.DataFrame(temp)
df_final_time = pd.DatetimeIndex(point_temp)
data.index = df_final_time
data = data.fillna(-1)
return data
def makeTickData(self, data, mins=30): def makeTickData(self, data, mins=30):
result = {"check": set(), result = {"check": set(),
"time": [], "time": [],
@@ -127,30 +317,63 @@ class HTS_etf(HTS):
return result return result
def makeTickData1(self, data, mins=5):
result = {
"ymd": [],
"open": [], "close": [], "high": [], "low": [], "volume": [], "volume_up": [], "volume_down": [], "volume_updown_diff": []
}
def getLIMITInfo(self, stock_code, ymd, dbfile_name="stock.db"): for i in range(mins, len(data['ymd'])+1):
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, dbfile_name)) result["ymd"].append(data['ymd'][i-1])
cursor = conn.cursor()
cursor.execute('select ymd, open, close, high, low, volume from stock where code=? order by ymd desc limit ?', result["open"].append(data['open'][i-mins])
(stock_code, 100,)) result["close"].append(data['close'][i-1])
db_result = cursor.fetchall()
cursor.close()
conn.close()
match = False result["high"].append(max(data['high'][i - mins: i]))
LIMIT_PRICE = [] result["low"].append(min(data['low'][i - mins: i]))
for i, rows in enumerate(db_result): result["volume"].append(sum(data['volume'][i - mins: i]))
if rows[0].replace('.', '') == ymd:
match = True
if match:
LIMIT_PRICE.append(rows[2])
return {'LOW_PRICE': sum(LIMIT_PRICE[:20]) / len(LIMIT_PRICE[:20])} up = [data['volume'][i - mins + c] for c in range(len(data['volume'][i - mins: i])) if data['open'][i - mins + c] < data['close'][i - mins + c]]
down = [data['volume'][i - mins + c] for c in range(len(data['volume'][i - mins: i])) if data['close'][i - mins + c] < data['open'][i - mins + c]]
result["volume_up"].append(sum(up))
result["volume_down"].append(sum(down))
result["volume_updown_diff"].append(sum(up) - sum(down))
return result
def buyRealTime(self, today, analyzed_day=1000, logFp=None, MAX_PRICE=30000): def makeTickData2(self, data, mins=5):
INFO = self.getLIMITInfo(self.stock_code, today) result = {
"ymd": [],
"open": [], "close": [], "high": [], "low": [], "volume": [], "volume_up": [], "volume_down": [], "volume_updown_diff": []
}
for i in range(mins, len(data['ymd'])+1, mins):
result["ymd"].append(data['ymd'][i-1])
result["open"].append(data['open'][i-mins])
result["close"].append(data['close'][i-1])
result["high"].append(max(data['high'][i - mins: i]))
result["low"].append(min(data['low'][i - mins: i]))
result["volume"].append(data['volume'][i-1])
if data['open'][i-1] < data['close'][i-1]:
result["volume_up"].append(data['volume'][i-1])
result["volume_down"].append(0)
elif data['close'][i-1] < data['open'][i-1]:
result["volume_down"].append(-1*data['volume'][i-1])
result["volume_up"].append(0)
else:
result["volume_up"].append(0)
result["volume_down"].append(0)
up = [data['volume'][i - mins + c] for c in range(len(data['volume'][i - mins: i])) if data['close'][i - mins + c] < data['open'][i - mins + c]]
down = [data['volume'][i - mins + c] for c in range(len(data['volume'][i - mins: i])) if data['close'][i - mins + c] < data['open'][i - mins + c]]
result["volume_updown_diff"].append(sum(up) - sum(down))
return result
def buyRealTime(self, today, MAX_PRICE=30000):
BUY_LIST = {'buy_count': 0, 'buy_avg': 0, 'buy_list': []}
print("START...") print("START...")
THIS_TIME = datetime.now() THIS_TIME = datetime.now()
@@ -160,69 +383,72 @@ class HTS_etf(HTS):
while datetime.strptime(today + " 063000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100",'%Y%m%d %H%M%S'): while datetime.strptime(today + " 063000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100",'%Y%m%d %H%M%S'):
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 090100", '%Y%m%d %H%M%S'): if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 090100", '%Y%m%d %H%M%S'):
self.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(self.stock_code, self.stock_name, MAX_PRICE)) self.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(self.stock_code, self.stock_name, MAX_PRICE))
logFp.write("START {} ({}) SLOW_K: {}\n".format(self.stock_code, self.stock_name, MAX_PRICE))
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'): if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
# 매도를 체크한다. # 매도를 체크한다.
self.sellStocks(self.stock_code) check = self.sellStocks(self.stock_code)
buy_avg = self.getBallance(self.stock_code)
if check or buy_avg == 0:
BUY_LIST['buy_avg'] = 0
BUY_LIST['buy_count'] = 0
BUY_LIST['buy_list'].clear()
time.sleep(0.1) time.sleep(0.1)
try: try:
# 데이터를 가지고 온다. # 데이터를 가지고 온다.
result = self.getRealTime(self.stock_code, today, LAST_DATA) result_m1 = self.getRealTime(self.stock_code, today, LAST_DATA)
except: except:
print("#ERROR:", self.stock_code) print("#ERROR:", self.stock_code)
continue continue
data = self.buySellChecker.analyze(result) result_tic_m1 = self.makeTickData1(result_m1, mins=1)
data.drop(data.index[:len(data) - analyzed_day], inplace=True) data = self.buySellChecker.analyze(result_tic_m1)
result_tic_m30 = self.makeTickData2(result_tic_m1, mins=30)
data_signal = self.buySellChecker.analyze(result_tic_m30)
#data.drop(data.index[:len(data) - analyzed_day], inplace=True)
# 사야 할 시점과 팔아야 할 시점을 체크한다. # 사야 할 시점과 팔아야 할 시점을 체크한다.
bsLine = self.buySellChecker.checkTransaction(self.stock_code, data, INFO, isRealTime=True) bsLine1 = self.buySellChecker.checkTransaction1(self.stock_code, MAX_PRICE, data, data_signal, BUY_LIST, isRealTime=True)
bs_buy_price = bsLine['buy'][0]
bs_buy_weight = bsLine['buy_weight'][0] if 'sell_price' in bsLine1:
bs_sell_price = bsLine['sell'][0] sell_price = bsLine1['sell_price'][-1]
if 0 < sell_price:
profit_rate = 1.002
if buy_avg * profit_rate < data['close'][-1]:
check = self.sellStocks(self.stock_code, sell_price)
if check:
self.orderChecker.sell(datetime.today().strftime('%Y%m%d'), self.stock_code)
BUY_LIST['buy_avg'] = 0
BUY_LIST['buy_count'] = 0
BUY_LIST['buy_list'].clear()
self.bot.sendMsg( "Profit {:.2f}, {} ({})".format(amount * (profit_rate - 1), self.stock_code, self.stock_name))
if 'buy_price' in bsLine1:
buy_price = bsLine1['buy_price'][-1]
buy_count = bsLine1['buy_count'][-1]
if buy_price > 0:
# 매수를 요청 한다.
amount = buy_price * buy_count
orderNum = self.requestOrder(OrderType.buy, self.stock_code, buy_count, buy_price)
self.orderChecker.buy(today, "A" + self.stock_code, buy_count, buy_price, orderNum)
self.orderChecker.buy(datetime.today().strftime('%Y%m%d'), self.stock_code, buy_count, buy_price)
self.bot.post(self.stock_code, self.stock_name, "[BUY] ", buy_price, buy_count, data['rsi'][-1], -1)
# 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다. # 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다.
ORDER_LIST = self.requestOrderList() #ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10) #orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10)
if len(orderListToCancel) > 0: #if len(orderListToCancel) > 0:
self.cancelOrderList(orderListToCancel) # self.cancelOrderList(orderListToCancel)
if bs_buy_price > 1000:
#if not self.orderChecker.exist(today, "A" + self.stock_code, hours=9):
buy_count = int(MAX_PRICE / bs_buy_price)
if buy_count > 0:
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, self.stock_code, buy_count, bs_buy_price)
self.orderChecker.buy(today, "A" + self.stock_code, buy_count, bs_buy_price, orderNum)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, self.stock_code, bs_buy_price, buy_count)
logFp.write("{} BUY {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, buy_count))
if bs_sell_price > 1000:
check = self.sellStocks(self.stock_code, bs_sell_price)
if check:
# 로그 출력
print("SELL", THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, self.stock_name, bs_sell_price)
logFp.write("{} SELL {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, bs_sell_price))
# 로그 출력
print("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f" %
(str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-1]))
logFp.write("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f\n" %
(str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-1]))
if (int(THIS_TIME.strftime("%M")) % 50 == 0 or int(THIS_TIME.strftime("%M")) % 20 == 0): if (int(THIS_TIME.strftime("%M")) % 50 == 0 or int(THIS_TIME.strftime("%M")) % 20 == 0):
self.bot.alarm_live(self.stock_code, self.stock_name, data["close"][len(data["close"])-1], data["macd"][len(data["macd"])-1]) self.bot.alarm_live(self.stock_code, self.stock_name, data["close"][len(data["close"])-1], data["macd"][len(data["macd"])-1])
logFp.flush()
time.sleep(60) time.sleep(60)
THIS_TIME = datetime.now() THIS_TIME = datetime.now()

View File

@@ -19,11 +19,9 @@ if __name__ == "__main__":
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")): if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log")) os.mkdir(os.path.join(RESOURCE_PATH, "log"))
logFp = open(os.path.join(RESOURCE_PATH, "log", today_str + "_" + stock_code + ".log"), "w", encoding='utf-8')
MAX_PRICE = 30000 MAX_PRICE = 300000
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE) hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
logFp.close()
db_filename = os.path.join(RESOURCE_PATH, "hts.db") db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name) hts.insertStockData(today, stock_code, stock_name)

View File

@@ -19,11 +19,9 @@ if __name__ == "__main__":
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")): if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log")) os.mkdir(os.path.join(RESOURCE_PATH, "log"))
logFp = open(os.path.join(RESOURCE_PATH, "log", today_str + "_" + stock_code + ".log"), "w", encoding='utf-8')
MAX_PRICE = 30000 MAX_PRICE = 300000
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE) hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
logFp.close()
db_filename = os.path.join(RESOURCE_PATH, "hts.db") db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name) hts.insertStockData(today, stock_code, stock_name)

View File

@@ -19,11 +19,9 @@ if __name__ == "__main__":
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")): if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log")) os.mkdir(os.path.join(RESOURCE_PATH, "log"))
logFp = open(os.path.join(RESOURCE_PATH, "log", today_str + "_" + stock_code + ".log"), "w", encoding='utf-8')
MAX_PRICE = 30000 MAX_PRICE = 300000
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE) hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
logFp.close()
db_filename = os.path.join(RESOURCE_PATH, "hts.db") db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name) hts.insertStockData(today, stock_code, stock_name)

View File

@@ -19,11 +19,9 @@ if __name__ == "__main__":
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")): if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log")) os.mkdir(os.path.join(RESOURCE_PATH, "log"))
logFp = open(os.path.join(RESOURCE_PATH, "log", today_str + "_" + stock_code + ".log"), "w", encoding='utf-8')
MAX_PRICE = 30000 MAX_PRICE = 300000
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE) hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
logFp.close()
db_filename = os.path.join(RESOURCE_PATH, "hts.db") db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name) hts.insertStockData(today, stock_code, stock_name)

View File

@@ -1,144 +1,211 @@
import pandas as pd import os
from dtw import dtw
import json
import sqlite3
import numpy as np
from datetime import datetime, timedelta
from stock.analysis.Common import Common class BuySellChecker():
from stock.analysis.Stochastic import Stochastic
from stock.analysis.RSI import RSI
from stock.analysis.MACD import MACD
from stock.analysis.IchimokuCloud import IchimokuCloud
PATTERNS = None
RESOURCE_PATH = None
class BuySellChecker: def __init__(self, RESOURCE_PATH, ticker):
common = None self.RESOURCE_PATH = RESOURCE_PATH
stochastic = None self.readBuyPattern(RESOURCE_PATH, ticker)
rsi = None
macd = None
ichimokuCloud = None
BUY_COUNT = None
def __init__(self):
self.common = Common()
self.stochastic = Stochastic()
self.rsi = RSI()
self.macd = MACD()
self.ichimokuCloud = IchimokuCloud()
self.BUY_COUNT = 0
return return
def getBuyPriceAndWeight(self, i, data): def readBuyPattern(self, RESOURCE_PATH, ticker):
buy, weight, type = -1, -1, "" with open(os.path.join(RESOURCE_PATH, "buy_pattern_data.json"), 'r') as f:
PATTERNS = json.load(f)
self.PATTERNS = {'min_max': [], 'stndardization': []}
for key in PATTERNS:
for min_max in PATTERNS[key]['min_max']:
self.PATTERNS['min_max'].append(min_max)
for stndardization in PATTERNS[key]['stndardization']:
self.PATTERNS['stndardization'].append(stndardization)
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)))
""" """
# 매수전략 #1: 다이버전스 def findBuyPoint(self, data, data_signal, i):
if data['macd'][i] < 0 and data['open'][i] < data['close'][i]: # 코사인 유사도(cosine similarity)로 과거 주가의 유사 패턴을 찾아 미래 예측하기
if 0 < len(data['rsi'].tolist()[i - 10:i - 5]): # https://teddylee777.github.io/pandas/cos-sim-stock/
if min(data['rsi'].tolist()[i - 10:i - 5]) < data['rsi'][i - 1]:
if data['low'][i - 1] < min(data['low'].tolist()[i - 10:i - 5]): buy_target = data['close'].iloc[i-179:i+1]
weight = 1 window_size = len(buy_target)
buy = data['close'][i] if window_size == 180:
type = 'Divergence' 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
""" """
high_barrier = 70 def findBuyPoint(self, data, i):
low_barrier = 30 # DTW (Dynamic Time Warping)
Buy_Price=[] # 시계열 유사도: https://m.blog.naver.com/happyrachy/221693939341
Sell_Price=[] if i < 24:
number=[] return False
temp01 = []
temp01_id = []
temp02 = []
temp01_id = []
temp01_min_price = []
temp02_min_price = []
temp01_min_rsi = []
temp02_min_rsi = []
n_id=[]
i_id=[]
flag=1
n = 0
# https://superhky.tistory.com/441 for p in range(len(self.PATTERNS['min_max'])):
find = False size = len(self.PATTERNS['stndardization'][p])
for c in range(i-40, i-1): if i - size + 1 < 0:
if data['rsi'][i-1] > low_barrier and data['rsi'][i] < low_barrier: continue
for k in range(c, i):
if data['rsi'][k-1] < low_barrier and data['rsi'][k] > low_barrier:
temp01 = data['rsi'].iloc[c:k]
temp01_id = temp01.argmin() + c
temp01_min_rsi = data['rsi'][temp01_id]
temp01_min_price = data['close'][temp01_id]
for m in range(k, i): close = data['close'].iloc[i-size+1:i+1]
if data['rsi'][m-1] < low_barrier and data['rsi'][m] < low_barrier:
for n in range(m, i):
if data['rsi]'][n-1] < low_barrier and data['rsi'][n] < low_barrier:
temp02 = data['rsi'].iloc[m:n]
temp02_id = temp02.argmin() + m
temp02_min_rsi = data['rsi'][temp02_id]
temp02_min_price = data['close'][temp02_id]
if temp01_min_rsi < temp02_min_rsi and temp01_min_price > temp02_min_price and flag == 1: #min_max = np.array(self.PATTERNS['min_max'][p]).reshape(-1, 1)
if c == i-1: stndardization = np.array(self.PATTERNS['stndardization'][p]).reshape(-1, 1)
weight = 1
buy = data['close'][i]
type = 'Divergence'
find = True
break
if find: break
if find: break
if find: break
"""
# 매수전략 #3: stochastic + rsi + macd
check = False
if data['slow_k'][i - 1] < data['slow_k'][i] and data['slow_d'][i] < data['slow_k'][i]:
# 과매도 체크 #min_max_y = np.array((close - close.min()) / (close.max() - close.min())).reshape(-1, 1)
index = -1 stndardization_y = np.array((close - close.mean()) / close.std()).reshape(-1, 1)
for c in range(i - 40, i):
if data['slow_k'][i] < 20: #manhattan_distance = lambda min_max, min_max_y: np.abs(min_max - min_max_y)
index = c #min_max_d, cost_matrix, acc_cost_matrix, path = dtw(min_max, min_max_y, dist=manhattan_distance)
check = True
if check: 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)
check = False
for d in range(index, i): if stndardization_d < 2:
if 80 < data['slow_k'][d]: #print(i, data['ymd'].iloc[i], stndardization_d)
check = True return True
break return False
if not check:
# 과매도 후 과매수가 아니라면 def getMacd(self, ticker_code, day, mins=1):
if data['rsi'][i - 1] < 50 and 50 < data['rsi'][i]:
if data['macds'][i] < data['macd'][i] < 0: table = 'minutely_max_macd_' + str(mins)
weight = 1
buy = data['close'][i] conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, 'coins.db'))
type = 'S+R+M' cursor = conn.cursor()
"""
return buy, weight, type 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 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
if isRealTime:
macds = data['macd'][i-300:i].to_list()
if 0 < len(macds):
macds_max = max(macds)
mi = i-300 + macds.index(macds_max)
if data['macd'][i] < macds_max and data['close'][mi] < data['close'][i]:
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
else:
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
else:
macds = self.getMacd(ticker['ticker_code'], data['ymd'][i].strftime('%Y%m%d'), mins=1)
if len(macds) == 0:
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
macds_sort = sorted(macds, key=lambda x:x[0], reverse=True)
if data['macd'][i] < macds_sort[0][1] and macds_sort[0][2] < data['close'][i]:
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
duration = 3
if sum(data['trend_avg'][i - duration:i]) / duration < data['trend_avg'][i]:
# 상승 트렌드
if data_signal['avg20'][si] < data_signal['avg5'][si]:
# 방법 1:
if max(data['volume_up'][i-180:i]) < data['volume_up'][i]:
if data_signal['slow_k'][si] < 70:
if BUY_LIST is not None and 0 < len(BUY_LIST['buy_list']) and BUY_LIST['buy_list'][-1]['buy_price'] < data['close'][i]:
buy_price = data['close'][i]
buy_type = 'volume_up'
buy_ymd = data['ymd'][i]
if data['slow_k'][si] < 30:
buy_count = MAX_BUY_PRICE / (1 * data['close'][i])
elif data['slow_k'][si] < 50:
buy_count = MAX_BUY_PRICE / (2 * data['close'][i])
else:
buy_count = MAX_BUY_PRICE / (3 * data['close'][i])
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
else:
buy_price = data['close'][i]
buy_type = 'volume_up'
buy_ymd = data['ymd'][i]
if data['slow_k'][si] < 30:
buy_count = MAX_BUY_PRICE / (1 * data['close'][i])
elif data['slow_k'][si] < 50:
buy_count = MAX_BUY_PRICE / (2 * data['close'][i])
else:
buy_count = MAX_BUY_PRICE / (3 * data['close'][i])
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
# 방법 2:
if data['avg480'][i] < data['avg120'][i] < data['avg60'][i] < data['avg20'][i] < data['avg5'][i] < data['close'][i]:
if data['avg240'][i] < min(data['avg5'][i], data['avg20'][i], data['avg60'][i], data['avg120'][i]):
if BUY_LIST is not None and 0 < len(BUY_LIST['buy_list']) and data['ymd'][i] < BUY_LIST['buy_list'][-1]['buy_ymd'] + timedelta(minutes=10):
if BUY_LIST['buy_list'][-1]['buy_price'] < data['close'][i]:
buy_price = data['close'][i]
buy_type = 'golden'
buy_ymd = data['ymd'][i]
if data['slow_k'][si] < 30:
buy_count = MAX_BUY_PRICE / (1 * data['close'][i])
elif data['slow_k'][si] < 50:
buy_count = MAX_BUY_PRICE / (2 * data['close'][i])
else:
buy_count = MAX_BUY_PRICE / (3 * data['close'][i])
else:
buy_price = data['close'][i]
buy_type = 'golden'
buy_ymd = data['ymd'][i]
if data['slow_k'][si] < 30:
buy_count = MAX_BUY_PRICE / (1 * data['close'][i])
elif data['slow_k'][si] < 50:
buy_count = MAX_BUY_PRICE / (2 * data['close'][i])
else:
buy_count = MAX_BUY_PRICE / (3 * data['close'][i])
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
def getSellPriceAndWeight(self, i, data): return buy_ymd, buy_price, buy_count, buy_cut, buy_type
sell, weight, type = -1, -1, ""
max_value = max(data['macd'].tolist()) * 0.8 def getSellPriceAndWeight1(self, ticker, i, data, data_signal, BUY_LIST=None):
if (max_value < data['macd'][i] or 1.9 < data['macds'][i]) and (0 < data['macdo'][i-1] and data['macdo'][i] <= 0): sell_price, sell_count = -1, -1
#if data['macds'][i-1] < data['macd'][i-1] and data['macd'][i] < data['macds'][i]:
weight = 1
sell = data['close'][i]
type = 'method1'
# 매수전략 #2: RSI 과매수에서 데드크로스 if BUY_LIST is not None and 0 < len(BUY_LIST['buy_list']):
if (data['macds'][i - 1] < data['macd'][i - 1] and data['macd'][i] < data['macds'][i]): # 방법1에 대해서는 1% 이익시 매도 한다. (Upbit.py 파일에서)
if 70 < data['rsi'][i]:
weight = 1
sell = data['close'][i]
type = 'method2'
# 방법2에 대한 매도
if data['close'][i-1] < data['open'][i-1] and data['close'][i] < data['open'][i]:
count = sum([price['buy_count'] for price in BUY_LIST['buy_list'] if price['buy_type'] == 'golden'])
if 0 < count:
sell_price = data['close'][i]
sell_count = sum([price['buy_count'] for price in BUY_LIST['buy_list']])
return sell, weight, type return sell_price, sell_count
def checkTransaction1(self, ticker, MAX_BUY_PRICE, data, data_signal, BUY_LIST=None, isRealTime=True):
def checkTransaction(self, data, isRealTime=True):
# 어제 오늘 데이터로 분석 # 어제 오늘 데이터로 분석
bsLine = {} bsLine = {}
@@ -149,150 +216,52 @@ class BuySellChecker:
# isRealTime=True, 실시간 적용 # isRealTime=True, 실시간 적용
last_index = size - 1 last_index = size - 1
buy, buy_weight, buy_type = self.getBuyPriceAndWeight(last_index, data) sell_price, sell_weight = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST)
sell, sell_weight, sell_type = self.getSellPriceAndWeight(last_index, data) bsLine['sell_price'] = [sell_price]
bsLine['buy'] = [buy]
bsLine['buy_weight'] = [buy_weight]
bsLine['buy_type'] = [buy_type]
bsLine['sell'] = [sell]
bsLine['sell_weight'] = [sell_weight] bsLine['sell_weight'] = [sell_weight]
bsLine['sell_type'] = [sell_type]
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 BUY_LIST is not None and 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: else:
# Type=False, 시뮬레이션 적용 # Type=False, 시뮬레이션 적용
bsLine['buy'] = [-1 for i in range(size)] bsLine['buy_ymd'] = [-1 for i in range(size)]
bsLine['buy_weight'] = [-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['buy_type'] = ['' for i in range(size)]
bsLine['sell'] = [-1 for i in range(size)] bsLine['sell_price'] = [-1 for i in range(size)]
bsLine['sell_weight'] = [-1 for i in range(size)] bsLine['sell_weight'] = [-1 for i in range(size)]
bsLine['sell_type'] = ['' for i in range(size)]
for last_index in range(size): for last_index in range(size):
buy, buy_weight, buy_type = self.getBuyPriceAndWeight(last_index, data)
sell, sell_weight, sell_type = self.getSellPriceAndWeight(last_index, data) sell_price, sell_weight = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST)
bsLine['buy'][last_index] = buy bsLine['sell_price'][last_index] = sell_price
bsLine['buy_weight'][last_index] = buy_weight bsLine['sell_weight'][last_index] = sell_weight
if sell_price < 0:
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 bsLine['buy_type'][last_index] = buy_type
bsLine['sell'][last_index] = sell if BUY_LIST is not None and 0 < buy_price:
bsLine['sell_weight'][last_index] = sell_weight 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})
bsLine['sell_type'][last_index] = sell_type
else: else:
bsLine['buy'] = [-1] bsLine['buy_price'] = [-1]
bsLine['buy_weight'] = [-1] bsLine['buy_count'] = [-1]
bsLine['buy_cut'] = [-1]
bsLine['buy_type'] = [''] bsLine['buy_type'] = ['']
bsLine['sell'] = [-1] bsLine['sell_price'] = [-1]
bsLine['sell_weight'] = [-1] bsLine['sell_weight'] = [-1]
bsLine['sell_type'] = ['']
return bsLine return bsLine
def analyze(self, result):
# 기본 캔들 정보
open = result["open"]
close = result["close"]
high = result["high"]
low = result["low"]
vol = result["vol"]
# 이동 평균
close_df = pd.DataFrame(close)
avg5_list = close_df.rolling(window=5).mean().fillna(close[0]).values.tolist()
avg5 = [item[0] for item in avg5_list]
avg20_list = close_df.rolling(window=20).mean().fillna(close[0]).values.tolist()
avg20 = [item[0] for item in avg20_list]
avg30_list = close_df.rolling(window=30).mean().fillna(close[0]).values.tolist()
avg30 = [item[0] for item in avg30_list]
avg60_list = close_df.rolling(window=60).mean().fillna(close[0]).values.tolist()
avg60 = [item[0] for item in avg60_list]
avg120_list = close_df.rolling(window=120).mean().fillna(close[0]).values.tolist()
avg120 = [item[0] for item in avg120_list]
avg200_list = close_df.rolling(window=200).mean().fillna(close[0]).values.tolist()
avg200 = [item[0] for item in avg200_list]
open_df = pd.DataFrame(close)
disparity_avg5_list = (open_df / close_df.rolling(window=5).mean()).values.tolist()
disparity_avg5 = [item[0] for item in disparity_avg5_list]
disparity_avg20_list = (open_df / close_df.rolling(window=20).mean()).values.tolist()
disparity_avg20 = [item[0] for item in disparity_avg20_list]
disparity_avg30_list = (open_df / close_df.rolling(window=30).mean()).values.tolist()
disparity_avg30 = [item[0] for item in disparity_avg30_list]
disparity_avg60_list = (open_df / close_df.rolling(window=60).mean()).values.tolist()
disparity_avg60 = [item[0] for item in disparity_avg60_list]
disparity_avg120_list = (open_df / close_df.rolling(window=120).mean()).values.tolist()
disparity_avg120 = [item[0] for item in disparity_avg120_list]
disparity_avg200_list = (open_df / close_df.rolling(window=200).mean()).values.tolist()
disparity_avg200 = [item[0] for item in disparity_avg200_list]
# 볼린져 밴드
df = pd.DataFrame(close)
max20 = df.rolling(window=20).mean()
stddev20 = df.rolling(window=20).std()
upper_df = max20 + (stddev20 * 2) # 상단 볼린저 밴드
lower_df = max20 - (stddev20 * 2) # 하단 볼린저 밴드
upper, lower = [], []
for i in range(len(upper_df)):
if i < 10:
upper.append(upper_df.values[0][0])
lower.append(lower_df.values[0][0])
else:
upper.append(upper_df.values[i][0])
lower.append(lower_df.values[i][0])
point_temp = result["time"]
STOCK = []
for i in range(len(open)):
STOCK.append({'volume': vol[i], 'close': close[i], 'open': open[i], 'high': high[i], 'low': low[i],
'avg5': avg5[i], 'avg20': avg20[i], 'avg30': avg30[i], 'avg60': avg60[i], 'avg120': avg120[i], 'avg200': avg200[i]})
# stochastic
stochastic_df = self.stochastic.apply(STOCK, n=30, m=5, t=5)
fast_k = stochastic_df['fast_k'].values.tolist()
slow_k = stochastic_df['slow_k'].values.tolist()
slow_d = stochastic_df['slow_d'].values.tolist()
# macd
#macd_df = self.macd.apply(STOCK, short=12, long=26, t=9)
macd_df = self.macd.apply(STOCK, short=5, long=20, t=5)
macd = macd_df['macd'].values.tolist()
macds = macd_df['macds'].values.tolist()
macdo = macd_df['macdo'].values.tolist()
# rsi
rsi_df = self.rsi.apply(STOCK, period=30, window=5)
rsi = rsi_df['rsi'].values.tolist()
rsis = rsi_df['rsis'].values.tolist()
# ichimokuCloud
ichimokuCloud_df = self.ichimokuCloud.apply(STOCK, c=9, b=26, l=52)
ichimokuCloud_df = ichimokuCloud_df[:len(ichimokuCloud_df) - 51]
changeLine = ichimokuCloud_df['changeLine'].values.tolist()
baseLine = ichimokuCloud_df['baseLine'].values.tolist()
laggingSpan = ichimokuCloud_df['laggingSpan'].values.tolist()
leadingSpan1 = ichimokuCloud_df['leadingSpan1'].values.tolist()
leadingSpan2 = ichimokuCloud_df['leadingSpan2'].values.tolist()
# 결과
temp = {
"date": point_temp,
"open": open, "high": high, "low": low, "close": close, "volume": vol,
"avg5": avg5, "avg20": avg20, "avg30": avg30, "avg60": avg60, "avg120": avg120, "avg200": avg200,
"disparity_avg5": disparity_avg5, "disparity_avg20": disparity_avg20, "disparity_avg30": disparity_avg30,
"disparity_avg60": disparity_avg60, "disparity_avg120": disparity_avg120, "disparity_avg200": disparity_avg200,
"upper": upper, "lower": lower,
"macd": macd, "macds": macds, "macdo": macdo,
"fast_k": fast_k, "slow_k": slow_k, "slow_d": slow_d,
"rsi": rsi, "rsis": rsis,
"changeLine": changeLine, "baseLine": baseLine, "laggingSpan": laggingSpan, "leadingSpan1": leadingSpan1,
"leadingSpan2": leadingSpan2,
}
data = pd.DataFrame(temp)
df_final_time = pd.DatetimeIndex(point_temp)
data.index = df_final_time
data = data.fillna(-1)
return data

View File

@@ -1,6 +1,7 @@
from datetime import datetime from datetime import datetime
import telegram import telegram
import asyncio import asyncio
import platform
from multiprocessing import Pool from multiprocessing import Pool
class TelegramBot: class TelegramBot:
@@ -23,9 +24,9 @@ class TelegramBot:
username for the bot: ncue_stock_bot username for the bot: ncue_stock_bot
token to access the HTTP API: 6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw token to access the HTTP API: 6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw
""" """
self.botname = "stockbot" self.botname = "coinbot"
self.username = "ncue_stock_bot" self.username = "ncue_coin_bot"
self.token = "6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw" self.token = "6435061393:AAHOh9wB5yGNGUdb3SfCYJrrWTBe7wgConM"
self.chat_id = '574661323' self.chat_id = '574661323'
self.client = telegram.Bot(token=self.token) self.client = telegram.Bot(token=self.token)
@@ -36,25 +37,29 @@ class TelegramBot:
@staticmethod @staticmethod
def send(text): def send(text):
client = telegram.Bot(token="6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw") client = telegram.Bot(token="6435061393:AAHOh9wB5yGNGUdb3SfCYJrrWTBe7wgConM")
#client.sendMessage(chat_id='574661323', text=text) if platform.system().lower() == 'windows':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(client.send_message(chat_id='574661323', text=text)) asyncio.run(client.send_message(chat_id='574661323', text=text))
return return
def alarm_live(self, stock_code, stock_name): def alarm_live(self, stock_code, stock_name):
if self.enable: if self.enable:
this_time = datetime.now() this_time = datetime.now()
text = "ALIVE (" + this_time.strftime('%Y-%m-%d %H:%M:%S') + ") " + stock_code + "(" + stock_name +")" text = "[ALIVE] {} {} ({})".format(this_time.strftime('%H:%M'), stock_code, stock_name)
pool = Pool(12) pool = Pool(12)
pool.map(self.send, [text]) pool.map(self.send, [text])
print(text) print(text)
return return
def post(self, stock_code, stock_name, type, price, count): def post(self, stock_code, stock_name, type, price, amount, rsi, balance=0):
if self.enable: if self.enable:
this_time = datetime.now() this_time = datetime.now()
text = "DATE TIME:" + this_time.strftime('%Y-%m-%d %H:%M:%S') + ", " + "stock_code:" + stock_code + ", " + "stock_name:" + stock_name + ", " + "type:" + type + ", " + "price:" + str(price) + ", " + "count:" + str(count) if 0 < balance:
text = "{}, {}, code: {}, name: {}, price: {}, amount: {}, (balance: {:2f}), (rsi: {:2f})".format(type, this_time.strftime('%H:%M'), stock_code, stock_name, price, amount, balance, rsi)
else:
text = "{}, {}, code: {}, name: {}, price: {}, amount: {}, (rsi: {:2f})".format(type, this_time.strftime('%H:%M'), stock_code, stock_name, price, amount, rsi)
pool = Pool(12) pool = Pool(12)
pool.map(self.send, [text]) pool.map(self.send, [text])
print(text) print(text)
@@ -63,7 +68,7 @@ class TelegramBot:
def sendMsg(self, msg): def sendMsg(self, msg):
if self.enable: if self.enable:
this_time = datetime.now() this_time = datetime.now()
text = "DATE TIME:" + this_time.strftime('%Y-%m-%d %H:%M:%S') + ", " + "msg:" + msg text = "{}: {}".format(this_time.strftime('%H:%M'), msg)
pool = Pool(12) pool = Pool(12)
pool.map(self.send, [text]) pool.map(self.send, [text])
print(text) print(text)
@@ -76,10 +81,9 @@ if __name__ == "__main__":
stock_name = "x2" stock_name = "x2"
type = "BUY" type = "BUY"
price = 2000 price = 2000
count = 2
telegramBot = TelegramBot() telegramBot = TelegramBot()
telegramBot.alarm_live(stock_code, stock_name) telegramBot.alarm_live(stock_code, stock_name)
telegramBot.post(stock_code, stock_name, type, price, count) telegramBot.post(stock_code, stock_name, type, price)