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 os
import sqlite3
import pandas as pd
from datetime import datetime
from hts.HTS import HTS
@@ -11,11 +10,14 @@ from stock.util.LabelChecker import LabelChecker
from stock.util.TelegramBot import TelegramBot
from stock.analysis.StockStatus import StockStatus
from hts.BuySellChecker_122630 import BuySellChecker_122630
from hts.BuySellChecker_233740 import BuySellChecker_233740
from hts.BuySellChecker_251340 import BuySellChecker_251340
from hts.BuySellChecker_252670 import BuySellChecker_252670
from stock.analysis.Common import Common
from stock.analysis.Stochastic import Stochastic
from stock.analysis.RSI import RSI
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):
RESOURCE_PATH = None
@@ -25,10 +27,16 @@ class HTS_etf(HTS):
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
bot = None
stockStatus = None
common = None
stochastic = None
rsi = None
macd = None
ichimokuCloud = None
def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP):
super().__init__(RESOURCE_PATH)
@@ -42,19 +50,19 @@ class HTS_etf(HTS):
self.bot = TelegramBot()
self.stockStatus = StockStatus(RESOURCE_PATH)
self.buySellChecker = None
if stock_code == '122630':
self.buySellChecker = BuySellChecker_122630()
elif stock_code == '233740':
self.buySellChecker = BuySellChecker_233740()
elif stock_code == '251340':
self.buySellChecker = BuySellChecker_251340()
elif stock_code == '252670':
self.buySellChecker = BuySellChecker_252670()
self.common = Common()
self.stochastic = Stochastic()
self.rsi = RSI()
self.macd = MACD()
self.ichimokuCloud = IchimokuCloud()
self.buySellChecker = BuySellChecker()
return
def getBallance(self):
return
def sellStocks(self, stock_code=None, bs_sell_price=None):
check = False
jangoDic = self.requstJango()
@@ -64,19 +72,19 @@ class HTS_etf(HTS):
if code == "A" + stock_code:
if bs_sell_price is not None:
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% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price)
check = True
else:
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% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
check = True
else:
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% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
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, 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):
result = {"check": set(),
"time": [],
@@ -127,30 +317,63 @@ class HTS_etf(HTS):
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"):
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, dbfile_name))
cursor = conn.cursor()
for i in range(mins, len(data['ymd'])+1):
result["ymd"].append(data['ymd'][i-1])
cursor.execute('select ymd, open, close, high, low, volume from stock where code=? order by ymd desc limit ?',
(stock_code, 100,))
db_result = cursor.fetchall()
cursor.close()
conn.close()
result["open"].append(data['open'][i-mins])
result["close"].append(data['close'][i-1])
match = False
LIMIT_PRICE = []
for i, rows in enumerate(db_result):
if rows[0].replace('.', '') == ymd:
match = True
if match:
LIMIT_PRICE.append(rows[2])
result["high"].append(max(data['high'][i - mins: i]))
result["low"].append(min(data['low'][i - mins: i]))
result["volume"].append(sum(data['volume'][i - mins: i]))
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):
INFO = self.getLIMITInfo(self.stock_code, today)
def makeTickData2(self, data, mins=5):
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...")
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'):
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))
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'):
# 매도를 체크한다.
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)
try:
# 데이터를 가지고 온다.
result = self.getRealTime(self.stock_code, today, LAST_DATA)
result_m1 = self.getRealTime(self.stock_code, today, LAST_DATA)
except:
print("#ERROR:", self.stock_code)
continue
data = self.buySellChecker.analyze(result)
data.drop(data.index[:len(data) - analyzed_day], inplace=True)
result_tic_m1 = self.makeTickData1(result_m1, mins=1)
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)
bs_buy_price = bsLine['buy'][0]
bs_buy_weight = bsLine['buy_weight'][0]
bs_sell_price = bsLine['sell'][0]
bsLine1 = self.buySellChecker.checkTransaction1(self.stock_code, MAX_PRICE, data, data_signal, BUY_LIST, isRealTime=True)
if 'sell_price' in bsLine1:
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분 이상 된 매수 주문을 취소 한다.
ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10)
if len(orderListToCancel) > 0:
self.cancelOrderList(orderListToCancel)
#ORDER_LIST = self.requestOrderList()
#orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10)
#if len(orderListToCancel) > 0:
# 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):
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)
THIS_TIME = datetime.now()

View File

@@ -19,11 +19,9 @@ if __name__ == "__main__":
if not os.path.exists(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
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE)
logFp.close()
MAX_PRICE = 300000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
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")):
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
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE)
logFp.close()
MAX_PRICE = 300000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
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")):
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
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE)
logFp.close()
MAX_PRICE = 300000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
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")):
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
hts.buyRealTime(today_str, analyzed_day=1000, logFp=logFp, MAX_PRICE=MAX_PRICE)
logFp.close()
MAX_PRICE = 300000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
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
from stock.analysis.Stochastic import Stochastic
from stock.analysis.RSI import RSI
from stock.analysis.MACD import MACD
from stock.analysis.IchimokuCloud import IchimokuCloud
class BuySellChecker():
PATTERNS = None
RESOURCE_PATH = None
class BuySellChecker:
common = None
stochastic = None
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
def __init__(self, RESOURCE_PATH, ticker):
self.RESOURCE_PATH = RESOURCE_PATH
self.readBuyPattern(RESOURCE_PATH, ticker)
return
def getBuyPriceAndWeight(self, i, data):
buy, weight, type = -1, -1, ""
def readBuyPattern(self, RESOURCE_PATH, ticker):
with open(os.path.join(RESOURCE_PATH, "buy_pattern_data.json"), 'r') as f:
PATTERNS = json.load(f)
"""
# 매수전략 #1: 다이버전스
if data['macd'][i] < 0 and data['open'][i] < data['close'][i]:
if 0 < len(data['rsi'].tolist()[i - 10:i - 5]):
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]):
weight = 1
buy = data['close'][i]
type = 'Divergence'
"""
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
high_barrier = 70
low_barrier = 30
Buy_Price=[]
Sell_Price=[]
number=[]
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
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
# https://superhky.tistory.com/441
find = False
for c in range(i-40, i-1):
if data['rsi'][i-1] > low_barrier and data['rsi'][i] < low_barrier:
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]
def cosine_similarity(self, x, y):
return np.dot(x, y) / (np.sqrt(np.dot(x, x)) * np.sqrt(np.dot(y, y)))
for m in range(k, i):
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]
"""
def findBuyPoint(self, data, data_signal, i):
# 코사인 유사도(cosine similarity)로 과거 주가의 유사 패턴을 찾아 미래 예측하기
# https://teddylee777.github.io/pandas/cos-sim-stock/
if temp01_min_rsi < temp02_min_rsi and temp01_min_price > temp02_min_price and flag == 1:
if c == i-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]:
buy_target = data['close'].iloc[i-179:i+1]
window_size = len(buy_target)
if window_size == 180:
buy_target = (buy_target - buy_target.min()) / (buy_target.max() - buy_target.min())
for pattern in self.PATTERNS:
cos_similarity = self.cosine_similarity(pattern, buy_target)
if 0.995 < cos_similarity:
return True
# 과매도 체크
index = -1
for c in range(i - 40, i):
if data['slow_k'][i] < 20:
index = c
check = True
if check:
# 과매도 후 과매수 였는지 체크
check = False
for d in range(index, i):
if 80 < data['slow_k'][d]:
check = True
break
if not check:
# 과매도 후 과매수가 아니라면
if data['rsi'][i - 1] < 50 and 50 < data['rsi'][i]:
if data['macds'][i] < data['macd'][i] < 0:
weight = 1
buy = data['close'][i]
type = 'S+R+M'
"""
return buy, weight, type
return False
"""
def findBuyPoint(self, data, i):
# DTW (Dynamic Time Warping)
# 시계열 유사도: https://m.blog.naver.com/happyrachy/221693939341
if i < 24:
return False
for p in range(len(self.PATTERNS['min_max'])):
size = len(self.PATTERNS['stndardization'][p])
if i - size + 1 < 0:
continue
close = data['close'].iloc[i-size+1:i+1]
#min_max = np.array(self.PATTERNS['min_max'][p]).reshape(-1, 1)
stndardization = np.array(self.PATTERNS['stndardization'][p]).reshape(-1, 1)
#min_max_y = np.array((close - close.min()) / (close.max() - close.min())).reshape(-1, 1)
stndardization_y = np.array((close - close.mean()) / close.std()).reshape(-1, 1)
#manhattan_distance = lambda min_max, min_max_y: np.abs(min_max - min_max_y)
#min_max_d, cost_matrix, acc_cost_matrix, path = dtw(min_max, min_max_y, dist=manhattan_distance)
manhattan_distance = lambda stndardization, stndardization_y: np.abs(stndardization - stndardization_y)
stndardization_d, cost_matrix, acc_cost_matrix, path = dtw(stndardization, stndardization_y, dist=manhattan_distance)
if stndardization_d < 2:
#print(i, data['ymd'].iloc[i], stndardization_d)
return True
return False
def getMacd(self, ticker_code, day, mins=1):
table = 'minutely_max_macd_' + str(mins)
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, 'coins.db'))
cursor = conn.cursor()
day1 = (datetime.strptime(day, '%Y%m%d') - timedelta(1)).strftime('%Y%m%d')
cursor.execute('SELECT ymd, hms, macd, close FROM '+table+' WHERE (CODE=? or CODE=?) and (ymd=? or ymd=?) order by macd desc', (ticker_code, ticker_code.replace('KRW-', ''), day, day1, ))
db_result1 = cursor.fetchall()
cursor.close()
conn.close()
macd_limit = [(datetime.strptime(rows[0]+" "+rows[1], '%Y%m%d %H%M%S'), rows[2], rows[3]) for rows in db_result1]
macd_dup = list(set(macd_limit))
return macd_dup
def 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):
sell, weight, type = -1, -1, ""
return buy_ymd, buy_price, buy_count, buy_cut, buy_type
max_value = max(data['macd'].tolist()) * 0.8
if (max_value < data['macd'][i] or 1.9 < data['macds'][i]) and (0 < data['macdo'][i-1] and data['macdo'][i] <= 0):
#if data['macds'][i-1] < data['macd'][i-1] and data['macd'][i] < data['macds'][i]:
weight = 1
sell = data['close'][i]
type = 'method1'
def getSellPriceAndWeight1(self, ticker, i, data, data_signal, BUY_LIST=None):
sell_price, sell_count = -1, -1
# 매수전략 #2: RSI 과매수에서 데드크로스
if (data['macds'][i - 1] < data['macd'][i - 1] and data['macd'][i] < data['macds'][i]):
if 70 < data['rsi'][i]:
weight = 1
sell = data['close'][i]
type = 'method2'
if BUY_LIST is not None and 0 < len(BUY_LIST['buy_list']):
# 방법1에 대해서는 1% 이익시 매도 한다. (Upbit.py 파일에서)
# 방법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 = {}
@@ -149,150 +216,52 @@ class BuySellChecker:
# isRealTime=True, 실시간 적용
last_index = size - 1
buy, buy_weight, buy_type = self.getBuyPriceAndWeight(last_index, data)
sell, sell_weight, sell_type = self.getSellPriceAndWeight(last_index, data)
bsLine['buy'] = [buy]
bsLine['buy_weight'] = [buy_weight]
bsLine['buy_type'] = [buy_type]
bsLine['sell'] = [sell]
sell_price, sell_weight = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST)
bsLine['sell_price'] = [sell_price]
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:
# Type=False, 시뮬레이션 적용
bsLine['buy'] = [-1 for i in range(size)]
bsLine['buy_weight'] = [-1 for i in range(size)]
bsLine['buy_ymd'] = [-1 for i in range(size)]
bsLine['buy_price'] = [-1 for i in range(size)]
bsLine['buy_count'] = [-1 for i in range(size)]
bsLine['buy_cut'] = [-1 for i in range(size)]
bsLine['buy_type'] = ['' for i in range(size)]
bsLine['sell'] = [-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_type'] = ['' for i 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)
bsLine['buy'][last_index] = buy
bsLine['buy_weight'][last_index] = buy_weight
bsLine['buy_type'][last_index] = buy_type
bsLine['sell'][last_index] = sell
sell_price, sell_weight = self.getSellPriceAndWeight1(ticker, last_index, data, data_signal, BUY_LIST)
bsLine['sell_price'][last_index] = sell_price
bsLine['sell_weight'][last_index] = sell_weight
bsLine['sell_type'][last_index] = sell_type
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
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:
bsLine['buy'] = [-1]
bsLine['buy_weight'] = [-1]
bsLine['buy_price'] = [-1]
bsLine['buy_count'] = [-1]
bsLine['buy_cut'] = [-1]
bsLine['buy_type'] = ['']
bsLine['sell'] = [-1]
bsLine['sell_price'] = [-1]
bsLine['sell_weight'] = [-1]
bsLine['sell_type'] = ['']
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
import telegram
import asyncio
import platform
from multiprocessing import Pool
class TelegramBot:
@@ -23,9 +24,9 @@ class TelegramBot:
username for the bot: ncue_stock_bot
token to access the HTTP API: 6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw
"""
self.botname = "stockbot"
self.username = "ncue_stock_bot"
self.token = "6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw"
self.botname = "coinbot"
self.username = "ncue_coin_bot"
self.token = "6435061393:AAHOh9wB5yGNGUdb3SfCYJrrWTBe7wgConM"
self.chat_id = '574661323'
self.client = telegram.Bot(token=self.token)
@@ -36,25 +37,29 @@ class TelegramBot:
@staticmethod
def send(text):
client = telegram.Bot(token="6874078562:AAEHxGDavfc0ssAXPQIaW8JGYmTR7LNUJOw")
#client.sendMessage(chat_id='574661323', text=text)
client = telegram.Bot(token="6435061393:AAHOh9wB5yGNGUdb3SfCYJrrWTBe7wgConM")
if platform.system().lower() == 'windows':
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
asyncio.run(client.send_message(chat_id='574661323', text=text))
return
def alarm_live(self, stock_code, stock_name):
if self.enable:
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.map(self.send, [text])
print(text)
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:
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.map(self.send, [text])
print(text)
@@ -63,7 +68,7 @@ class TelegramBot:
def sendMsg(self, msg):
if self.enable:
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.map(self.send, [text])
print(text)
@@ -76,10 +81,9 @@ if __name__ == "__main__":
stock_name = "x2"
type = "BUY"
price = 2000
count = 2
telegramBot = TelegramBot()
telegramBot.alarm_live(stock_code, stock_name)
telegramBot.post(stock_code, stock_name, type, price, count)
telegramBot.post(stock_code, stock_name, type, price)