275 lines
10 KiB
Python
275 lines
10 KiB
Python
# https://bibot.tistory.com/63
|
|
# https://nonmeyet.tistory.com/entry/Python-TALib%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%B9%84%ED%8A%B8%EC%BD%94%EC%9D%B8%EC%A3%BC%EA%B0%80%EA%B8%B0%EC%88%A0%EB%B6%84%EC%84%9D-%EB%B3%B4%EC%A1%B0%EC%A7%80%ED%91%9C-%EC%B6%94%EA%B0%80
|
|
# https://lunadaddy.tistory.com/122
|
|
# https://wikidocs.net/186885
|
|
|
|
import os
|
|
import numpy as np
|
|
np.seterr(divide='ignore', invalid='ignore')
|
|
import pyupbit
|
|
import math
|
|
import sqlite3
|
|
# https://www.lfd.uci.edu/~gohlke/pythonlibs/#ta-lib
|
|
# https://lunadaddy.tistory.com/122
|
|
import talib
|
|
import pandas as pd
|
|
from datetime import datetime, timedelta
|
|
|
|
from stock.analysis.IchimokuCloud import IchimokuCloud
|
|
|
|
class JSDPattern:
|
|
RESOURCE_PATH = None
|
|
ichimokuCloud = None
|
|
scaler = None
|
|
|
|
def __init__(self, RESOURCE_PATH=None):
|
|
if RESOURCE_PATH is None:
|
|
self.RESOURCE_PATH = os.path.join(os.getcwd(), "resources")
|
|
else:
|
|
self.RESOURCE_PATH = RESOURCE_PATH
|
|
|
|
self.ichimokuCloud = IchimokuCloud()
|
|
return
|
|
|
|
def makeTickData(self, data, mins=1):
|
|
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 append(self, df=None, result=None):
|
|
data = {
|
|
"ymd": [],
|
|
"open": [], "close": [], "high": [], "low": [], "volume": []
|
|
}
|
|
|
|
if result is not None:
|
|
for i in range(len(result['ymd'])):
|
|
data['ymd'].append(result['ymd'][i])
|
|
data['open'].append(result['open'][i])
|
|
data['close'].append(result['close'][i])
|
|
data['high'].append(result['high'][i])
|
|
data['low'].append(result['low'][i])
|
|
data['volume'].append(result['volume'][i])
|
|
|
|
if df is not None:
|
|
for i in range(len(df)):
|
|
data['ymd'].append(df.index[i])
|
|
data['open'].append(df['open'].iloc[i])
|
|
data['close'].append(df['close'].iloc[i])
|
|
data['high'].append(df['high'].iloc[i])
|
|
data['low'].append(df['low'].iloc[i])
|
|
data['volume'].append(df['volume'].iloc[i])
|
|
|
|
return data
|
|
|
|
def getDBData(self, stock_code, day, mins, get_days=14):
|
|
|
|
if mins == 3:
|
|
table = 'minute3'
|
|
elif mins == 5:
|
|
table = 'minute5'
|
|
elif mins == 10:
|
|
table = 'minute10'
|
|
elif mins == 20:
|
|
table = 'minute20'
|
|
elif mins == 30:
|
|
table = 'minute30'
|
|
elif mins == 60:
|
|
table = 'minute60'
|
|
elif mins == 200:
|
|
table = 'minute200'
|
|
elif mins == 1440:
|
|
table = 'daily'
|
|
else:
|
|
table = 'minutely'
|
|
|
|
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, 'coins.db'))
|
|
cursor = conn.cursor()
|
|
|
|
result = {"ymd": [], "open": [], "close": [], "high": [], "low": [], "volume": [], "label": []}
|
|
for i in range(get_days, -1, -1):
|
|
this_day = (datetime.strptime(day, '%Y%m%d') - timedelta(i)).strftime('%Y%m%d')
|
|
cursor.execute('SELECT ymd, hms, open, high, low, close, volume FROM ' + table + ' WHERE (CODE=? or CODE=?) and (ymd=?) order by ymd, hms', (stock_code, stock_code.replace('KRW-', ''), this_day,))
|
|
|
|
db_result = cursor.fetchall()
|
|
for rows in db_result:
|
|
ymd = rows[0] # hts.날짜
|
|
hms = rows[1] # hts.시간
|
|
open = rows[2] # hts.시가
|
|
high = rows[3] # hts.고가
|
|
low = rows[4] # hts.저가
|
|
close = rows[5] # hts.종가
|
|
vol = rows[6] # hts.거래량
|
|
|
|
temp = datetime.strptime(str(ymd) + " " + hms, '%Y%m%d %H%M%S')
|
|
|
|
result["ymd"].append(temp)
|
|
result["open"].append(float(open))
|
|
result["close"].append(float(close))
|
|
result["high"].append(float(high))
|
|
result["low"].append(float(low))
|
|
result["volume"].append(float(vol))
|
|
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
return result
|
|
|
|
def getCoinData(self, ticker, mins=None, to=None, ymd=None, get_days=14):
|
|
result = None
|
|
|
|
if ymd is not None and datetime.now() < datetime.strptime(ymd, '%Y%m%d'):
|
|
ymd = None
|
|
|
|
if ymd is None:
|
|
if to is None:
|
|
if mins is None:
|
|
df = pyupbit.get_ohlcv(ticker=ticker['ticker_code'])
|
|
else:
|
|
if mins == 1440:
|
|
df = pyupbit.get_ohlcv(ticker=ticker['ticker_code'], interval='minute1', count=1)
|
|
else:
|
|
df = pyupbit.get_ohlcv(ticker=ticker['ticker_code'], interval='minute' + str(mins))
|
|
else:
|
|
df = pyupbit.get_ohlcv(ticker=ticker['ticker_code'], interval='minute' + str(mins), to=to)
|
|
|
|
if df is not None:
|
|
df["datetime"] = df.index
|
|
df = df[['open', 'high', 'low', 'close', 'volume']].astype(float)
|
|
|
|
if mins is not None:
|
|
result = self.getDBData(ticker['ticker_code'], datetime.today().strftime('%Y%m%d'), mins=mins, get_days=get_days)
|
|
|
|
data = self.append(df, result)
|
|
|
|
else:
|
|
result = self.getDBData(ticker['ticker_code'], ymd, mins=mins, get_days=get_days)
|
|
data = self.append(df=None, result=result)
|
|
|
|
return data
|
|
|
|
def is_Support(self, low, i, observation_time=5):
|
|
# https://sine-qua-none.tistory.com/198
|
|
|
|
# c1 = df.Low[i] < df.Low[i - 1] < df.Low[i - 2] < df.Low[i - 3]
|
|
# c2 = df.Low[i] < df.Low[i + 1] < df.Low[i + 2] < df.Low[i + 3]
|
|
# return c1 & c2
|
|
|
|
#if low[i] == np.min(low[i - 2*self.observation_time:i + 1]):
|
|
if low[i] == np.min(low[i - observation_time:i + observation_time + 1]):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def is_Resistance(self, high, i, observation_time=5):
|
|
# https://sine-qua-none.tistory.com/198
|
|
|
|
# c1 = df.High[i] > df.High[i - 1] > df.High[i - 2] > df.High[i - 3]
|
|
# c2 = df.High[i] > df.High[i + 1] > df.High[i + 2] > df.High[i + 3]
|
|
# return c1 & c2
|
|
# if df['high'][i] == np.max(df['high'][i - self.observation_time:i + self.observation_time + 1]):
|
|
#if high[i] == np.max(high[i - 2*self.observation_time:i + 1]):
|
|
if high[i] == np.max(high[i - observation_time:i + observation_time + 1]):
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
|
|
def getDiff_Rate(self, price1, price2, duration=1440, move=None):
|
|
# price1: close, price2: laggingSpan_27
|
|
diff = [0 for i in range(len(price1))]
|
|
diff_rate = [0 for i in range(len(price1))]
|
|
|
|
for i in range(0, len(price1)):
|
|
if price1[i] is not None and not math.isnan(price1[i]) and price2[i] is not None and not math.isnan(price2[i]):
|
|
diff[i] = price1[i] - price2[i]
|
|
else:
|
|
diff[i] = np.nan
|
|
|
|
if len(price1) < duration:
|
|
duration = 52
|
|
|
|
for i in range(0, len(price1)):
|
|
|
|
if duration <= i:
|
|
l = [d for d in diff[i - duration:i + 1] if d is not None and 0 < d]
|
|
if 0 < len(l):
|
|
min_v_p = np.min(l)
|
|
else:
|
|
min_v_p = 0
|
|
l = [d for d in diff[i - duration:i + 1] if d is not None and 0 < d]
|
|
if 0 < len(l):
|
|
max_v_p = np.max(l)
|
|
else:
|
|
max_v_p = 0
|
|
l = [d for d in diff[i - duration:i + 1] if d is not None and d < 0]
|
|
if 0 < len(l):
|
|
min_v_m = np.min(l)
|
|
else:
|
|
min_v_m = 0
|
|
l = [d for d in diff[i - duration:i + 1] if d is not None and d < 0]
|
|
if 0 < len(l):
|
|
max_v_m = np.max(l)
|
|
else:
|
|
max_v_m = 0
|
|
|
|
if diff[i] is not None and not math.isnan(diff[i]):
|
|
if 0 <= diff[i]:
|
|
if max_v_p - min_v_p == 0:
|
|
diff_rate[i] = 0
|
|
else:
|
|
diff_rate[i] = (diff[i] - min_v_p) / (max_v_p - min_v_p)
|
|
else:
|
|
if max_v_m - min_v_m == 0:
|
|
diff_rate[i] = 0
|
|
else:
|
|
diff_rate[i] = ((diff[i] - min_v_m) / (max_v_m - min_v_m)) - 1
|
|
else:
|
|
diff_rate[i] = np.nan
|
|
|
|
return diff, diff_rate
|
|
|
|
|
|
def getDisparity_low_min(self, ticker, min='minutely'):
|
|
try:
|
|
self.conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "coins.db"))
|
|
self.cursor = self.conn.cursor()
|
|
|
|
self.cursor.execute("SELECT lowest_disparity FROM disparity WHERE (CODE=? or CODE=?) AND TYPE=?", (ticker['ticker_code'], ticker['ticker_code'].replace('KRW-', ''), min))
|
|
db_result = self.cursor.fetchall()
|
|
self.cursor.close()
|
|
self.conn.close()
|
|
|
|
if 0 < len(db_result):
|
|
return db_result[0][0]
|
|
|
|
except:
|
|
return 0.90
|
|
return 0.90
|