This commit is contained in:
dsyoon
2024-04-26 07:47:48 +09:00
parent 3bbfdf2f7a
commit d5e5316fce
25 changed files with 1699 additions and 3665 deletions

View File

@@ -1,50 +0,0 @@
import time
import requests
from bs4 import BeautifulSoup
from datetime import datetime
from stock.util.TelegramBot import TelegramBot
class HTS_Alert :
bot = None
def __init__(self):
self.bot = TelegramBot()
return
def checkPrice(self, code):
code_index = 0
PERCENT = ["50%", "50%"]
CHECK_PRICE = [2565, 2422]
THIS_TIME = datetime.now()
today = datetime.today().strftime('%Y%m%d')
while datetime.strptime(today + " 080000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
url = 'https://finance.naver.com/item/main.naver?code={code}'.format(code=code.strip())
res = requests.get(url)
html = res.text
soup = BeautifulSoup(html, 'html.parser')
post = soup.select_one('#chart_area > .rate_info > .today > .no_today > em')
arr = post.text.split("\n")
c_price = int(arr[1].replace(',', ''))
if c_price < CHECK_PRICE[code_index]:
self.bot.sendMsg(code + " " + str(CHECK_PRICE[code_index]) + " " + PERCENT[code_index] + "를 파세요...")
code_index += 1
if code_index > len(CHECK_PRICE):
break
time.sleep(60)
THIS_TIME = datetime.now()
return
if __name__ == "__main__":
hTS_Alert = HTS_Alert()
week = datetime.today().weekday()
if week in (0, 1, 2, 3, 4): # 0:월, 1:화, 2:수, 3:목, 4:금, 5:토, 6:일
post = hTS_Alert.checkPrice('252670')
print ("done...")

View File

@@ -1,31 +0,0 @@
import os
from datetime import datetime
from HTS_etf import HTS_etf
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stock_code = "122630"
stock_name = "KODEX 레버리지"
hts = HTS_etf(RESOURCE_PATH, stock_code, stock_name, SELL_GAP=80)
hts.connect2DB("hts.db")
today_str = today.strftime('%Y%m%d')
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log"))
MAX_PRICE = 500000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name)
hts.disconnect()
hts.bot.sendMsg("done... {} ({})".format(stock_code, stock_name))
print("done...")

View File

@@ -1,31 +0,0 @@
import os
from datetime import datetime
from HTS_etf import HTS_etf
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stock_code = "233740"
stock_name = "KODEX 코스닥150레버리지"
hts = HTS_etf(RESOURCE_PATH, stock_code, stock_name, SELL_GAP=70)
hts.connect2DB("hts.db")
today_str = today.strftime('%Y%m%d')
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log"))
MAX_PRICE = 500000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name)
hts.disconnect()
hts.bot.sendMsg("done... {} ({})".format(stock_code, stock_name))
print("done...")

View File

@@ -1,31 +0,0 @@
import os
from datetime import datetime
from HTS_etf import HTS_etf
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stock_code = "251340"
stock_name = "KODEX 코스닥150선물인버스"
hts = HTS_etf(RESOURCE_PATH, stock_code, stock_name, SELL_GAP=50)
hts.connect2DB("hts.db")
today_str = today.strftime('%Y%m%d')
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log"))
MAX_PRICE = 500000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name)
hts.disconnect()
hts.bot.sendMsg("done... {} ({})".format(stock_code, stock_name))
print("done...")

View File

@@ -1,31 +0,0 @@
import os
from datetime import datetime
from HTS_etf import HTS_etf
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stock_code = "252670"
stock_name = "KODEX 200선물인버스2X"
hts = HTS_etf(RESOURCE_PATH, stock_code, stock_name, SELL_GAP=30)
hts.connect2DB("hts.db")
today_str = today.strftime('%Y%m%d')
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log"))
MAX_PRICE = 500000
hts.buyRealTime(today_str, MAX_PRICE=MAX_PRICE)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(today, stock_code, stock_name)
hts.disconnect()
hts.bot.sendMsg("done... {} ({})".format(stock_code, stock_name))
print("done...")

View File

@@ -1,80 +0,0 @@
import os
import json
import time
import psutil
from datetime import datetime
from HTS_etf import HTS_etf
if __name__ == "__main__":
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
stocks = [
{'stock_code': '122630', 'stock_name': 'KODEX 레버리지'},
{'stock_code': '233740', 'stock_name': 'KODEX 코스닥150레버리지'},
{'stock_code': '251340', 'stock_name': 'KODEX 코스닥150선물인버스'},
{'stock_code': '252670', 'stock_name': 'KODEX 200선물인버스2X'}
]
hts = HTS_etf(RESOURCE_PATH)
hts.connect2DB("hts.db")
today = datetime.today().strftime('%Y%m%d')
if not os.path.exists(os.path.join(RESOURCE_PATH, "log")):
os.mkdir(os.path.join(RESOURCE_PATH, "log"))
BUY_LIST = {}
for stock in stocks:
with open("config.json", "r", encoding="utf-8") as f:
config = json.load(f)
if stock['stock_code'] not in BUY_LIST:
BUY_LIST[stock['stock_code']] = {}
BUY_LIST[stock['stock_code']]['MAX_BUY_PRICE'] = config['MAX_BUY_PRICE']
BUY_LIST[stock['stock_code']]['BUY_LIST_1'] = config['BUY_LIST_1']
BUY_LIST[stock['stock_code']]['BUY_LIST_1']["disparity"] = hts.getDisparityLimit(stock)
print("START...")
close_data = {}
INIT = True
while datetime.strptime(today + " 060000", '%Y%m%d %H%M%S') < datetime.now() < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'):
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < datetime.now() < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
THIS_TIME = datetime.now()
for stock in stocks:
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < datetime.now() < datetime.strptime(today + " 090100", '%Y%m%d %H%M%S'):
hts.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(stock['stock_code'], stock['stock_name'], BUY_LIST[stock['stock_code']]['MAX_BUY_PRICE']))
LAST_DATA = hts.getLastData(stock['stock_code'], today)
result_m1 = hts.getRealTime(stock['stock_code'], today, LAST_DATA)
result_tic_m1 = hts.makeTickData1(result_m1, mins=1)
data = hts.analyze(result_tic_m1)
result_tic_m30 = hts.makeTickData2(result_tic_m1, mins=30)
data_signal = hts.analyze(result_tic_m30)
# data.drop(data.index[:len(data) - analyzed_day], inplace=True)
hts.buyRealTime(stock, data, data_signal, BUY_LIST[stock['stock_code']]['MAX_BUY_PRICE'], BUY_LIST[stock['stock_code']]['BUY_LIST_1'])
close_data[stock['stock_code']] = data['close'][-1]
if INIT:
hts.bot.sendMsg("Alive... close: {}".format(str(close_data)))
INIT = False
if int(THIS_TIME.strftime("%M")) % 50 == 0:
vm = psutil.virtual_memory()
vm_item = dict()
vm_item['free'] = vm.available // (1024 * 1024)
vm_item['idle'] = vm.available / vm.total * 100
hts.bot.sendMsg("Alive... close: {}, mem: {:.1f}".format(str(close_data), vm_item['idle']))
time.sleep(60)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
for stock in stocks:
hts.insertStockData(today, stock['stock_code'], stock['stock_name'])
hts.disconnect()
hts.bot.sendMsg("done...")
print("done...")

View File

@@ -1,400 +0,0 @@
import time
import os
import math
import sqlite3
from datetime import datetime, timedelta
from hts.HTS import HTS
from hts.OrderType import OrderType
from hts.BuySellChecker import BuySellChecker
from hts.OrderChecker import OrderChecker
from stock.util.LabelChecker import LabelChecker
from stock.util.TelegramBot import TelegramBot
from stock.analysis.StockStatus import StockStatus
class HTS_etf (HTS):
RESOURCE_PATH = None
stock_code = None
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
bot = None
stockStatus = None
def __init__(self, RESOURCE_PATH):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.orderChecker = OrderChecker(self.RESOURCE_PATH, "ETF")
self.buySellChecker = BuySellChecker()
self.labelChecker = LabelChecker(RESOURCE_PATH)
self.bot = TelegramBot()
self.stockStatus = StockStatus(RESOURCE_PATH)
return
def connect2StockDB(self):
self.conn_stock = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "resources/stock.db"))
self.cursor_stock = self.conn_stock.cursor()
return
def disconnectStockDB(self):
self.cursor_stock.close()
self.conn_stock.close()
return
def sellStocks(self, stock_code=None, bs_sell_price=None):
check = False
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if stock_code is not None:
if code == "A"+stock_code and bs_sell_price is not None:
if jangoDic[code]['매도가능'] > 0:
if 2 < jangoDic[code]['평가손익']:
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price)
self.bot.post(code, jangoDic[code]['종목명'], "SELL", bs_sell_price, jangoDic[code]['매도가능'])
check = True
else:
continue
else:
if jangoDic[code]['매도가능'] > 0:
if 3 < jangoDic[code]['평가손익']:
# 3% 이상 시 수익 매도
currentStock = self.currentStock(code[1:])
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], currentStock['close'])
self.bot.post(code, jangoDic[code]['종목명'], "SELL", currentStock['close'], jangoDic[code]['매도가능'])
check = True
return check
def getSellingPrice(self, log_time, stock_code, final_price, without_loss=False):
# final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미
# final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미
# final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임
orderNum = None
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if jangoDic[code]['매도가능'] > 0:
if without_loss:
if jangoDic[code]['장부가']*0.07 < jangoDic[code]['장부가'] - final_price:
sell_price = jangoDic[code]['장부가']
if code == "A" + stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price
else:
max_price = max(jangoDic[code]['장부가'], final_price)
sell_price = (int(max_price) - int(max_price) % 5) + 5
if code == "A"+stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price
return orderNum, None, None, None
def makeTickData(self, data, mins=30):
result = {"check": set(),
"time": [],
"open": [],
"close": [],
"high": [],
"low": [],
"vol": [],
"label": []}
for i in range(mins, len(data['time'])+1):
result["check"].add(data['time'][i-1])
result["time"].append(data['time'][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["vol"].append(sum(data['vol'][i - mins: i]))
return result
def getStockType(self, stock_code, short=False):
slow_k, p_slow_k, slow_k_week, p_slow_k_week, slow_k_month, p_slow_k_month = -1, -1, -1, -1, -1, -1
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis where code=? group by 1 order by ymd desc',(stock_code,))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k = item[0]
elif i == 1:
p_slow_k = item[0]
else:
break
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis_weekly where code=? group by 1 order by ymd desc', (stock_code, ))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k_week = item[0]
elif i == 1:
p_slow_k_week = item[0]
else:
break
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis_monthly where code=? group by 1 order by ymd desc',(stock_code,))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k_month = item[0]
elif i == 1:
p_slow_k_month = item[0]
else:
break
if slow_k is None or p_slow_k is None:
slow_k , p_slow_k = -1, -1
if slow_k_week is None or p_slow_k_week is None:
slow_k_week, p_slow_k_week = -1, -1
if slow_k_month is None or p_slow_k_month is None:
slow_k_month, p_slow_k_month = -1, -1
type_stock = {'day':1, 'week':10, 'month':100}
if stock_code == "^KS11":
if slow_k < 20: type_stock['day'] = 10
if 20 < slow_k < 25: type_stock['day'] = 7.5
if 25 < slow_k < 30: type_stock['day'] = 5
if 30 < slow_k < 35: type_stock['day'] = 2.5
if slow_k_week < 20: type_stock['week'] = 100
if 20 < slow_k_week < 25: type_stock['week'] = 75
if 25 < slow_k_week < 30: type_stock['week'] = 50
if 30 < slow_k_week < 35: type_stock['week'] = 25
if slow_k_month < 20: type_stock['month'] = 1000
if 20 < slow_k_month < 25: type_stock['month'] = 750
if 25 < slow_k_month < 30: type_stock['month'] = 500
if 30 < slow_k_month < 35: type_stock['month'] = 250
else:
if slow_k < 10: type_stock['day'] = 10
if 10 < slow_k < 15: type_stock['day'] = 7.5
if 15 < slow_k < 20: type_stock['day'] = 5
if 20 < slow_k < 25: type_stock['day'] = 2.5
if slow_k_week < 10: type_stock['week'] = 100
if 10 < slow_k_week < 15: type_stock['week'] = 75
if 15 < slow_k_week < 20: type_stock['week'] = 50
if 20 < slow_k_week < 25: type_stock['week'] = 25
if slow_k_month < 10: type_stock['month'] = 1000
if 10 < slow_k_month < 15: type_stock['month'] = 750
if 15 < slow_k_month < 20: type_stock['month'] = 500
if 20 < slow_k_month < 25: type_stock['month'] = 250
return type_stock
def getBuyCount(self, bs_buy_price, kospi_type, stock_type):
base_price = 10000
log_base = 1.2
p_k_m, p_k_w, p_k_d, p_s_m, p_s_w, p_s_d = 0.3, 0.2, 0.05, 0.25, 0.18, 0.02
weight_1, weight_2, weight_3, weight_4, weight_5 = 0.5, 0.3, 0.14, 0.05, 0.01
kospi_weight = weight_5
if kospi_type['day'] == 10: kospi_weight = weight_1
if kospi_type['day'] == 7.5: kospi_weight = weight_2
if kospi_type['day'] == 5: kospi_weight = weight_3
if kospi_type['day'] == 2.5: kospi_weight = weight_4
stock_weight = weight_5
if stock_type['day'] == 10: stock_weight = weight_1
if stock_type['day'] == 7.5: stock_weight = weight_2
if stock_type['day'] == 5: stock_weight = weight_3
if stock_type['day'] == 2.5: stock_weight = weight_4
max_price = math.log(
kospi_weight * p_k_m * kospi_type['month'] +
kospi_weight * p_k_w * kospi_type['week'] +
kospi_weight * p_k_d * kospi_type['day'] +
stock_weight * p_s_m * stock_type['month'] +
stock_weight * p_s_w * stock_type['week'] +
stock_weight * p_s_d * stock_type['day'], log_base) * base_price
buy_count = 0
if max_price > 1:
buy_count = int(math.floor(max_price / bs_buy_price))
return buy_count
def buyRealTime(self, today, stocks, analyzed_day=1000):
print ("START...")
THIS_TIME = datetime.now()
kospi_type = self.getStockType("^KS11", short=False)
LAST_DATA = {}
for stock in stocks:
LAST_DATA[stock['stock_code']] = self.getLastData(stock['stock_code'], today)
while datetime.strptime(today + " 070000", '%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 + " 151500", '%Y%m%d %H%M%S'):
# 매도를 체크한다.
# self.sellStocks()
for idx, stock in enumerate(stocks):
time.sleep(0.1)
print("%5d: %8s, %-50s"%(idx, stock['stock_code'], stock['stock_name']))
try:
# 데이터를 가지고 온다.
data = self.getRealTime(stock['stock_code'], today, LAST_DATA[stock['stock_code']])
except:
print("#ERROR:", stock['stock_code'], stock['stock_name'])
continue
# 현재 매수가
bs_buy_price = data["close"][len(data["close"]) - 1]
# 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다.
ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.cancel(today, "A" + stock['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" + stock['stock_code'], hours=5):
stock_type = self.getStockType(stock['stock_code'], short=False)
buy_count = self.getBuyCount(bs_buy_price, kospi_type, stock_type)
if buy_count > 0:
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, stock['stock_code'], buy_count , bs_buy_price)
self.orderChecker.buy(today, "A" + stock['stock_code'], buy_count, bs_buy_price, orderNum)
# bot에 메시지를 보냄
self.bot.post(stock['stock_code'], stock['stock_name'], "BUY", bs_buy_price, buy_count)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock['stock_code'], stock['stock_name'], bs_buy_price, buy_count)
# 로그 출력
print("TIMECHECK: %s, code: %s, name: %s, buy: %d, avg5: %.2f, avg30: %.2f, open: %d, high: %d, low: %d, slow_k: %.2f" %
(str(THIS_TIME), stock['stock_code'], stock['stock_name'], bs_buy_price, data["avg5"][0], data["avg30"][0],
data["open"][0], data["high"][0], data["low"][0], data["slow_k"][0]))
"""
elif datetime.strptime(today + " 151530", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151600", '%Y%m%d %H%M%S'):
# 3시 15분 30초부터 3시 16분 사이는 잔량을 매도한다.
if not final_sell_check:
####
# 손해 보지 않는 가격에 매도한다.
####
for stock in stocks:
# 주문 리스트를 가져온다.
orderList = self.requestOrderList()
# 15:10:00 이후라면 모든 미체결 취소한다.
self.cancelOrderList(orderList)
# 매도 가격을 가져온다.
result = self.getRealTime(stock['stock_code'], today, LAST_DATA[stock['stock_code']])
final_price = result["close"][len(result["close"]) - 1]
orderNum, sell_time, jango, sell_price = self.getSellingPrice(THIS_TIME, stock['stock_code'], final_price, without_loss=True)
# 로그 출력
print("SELL", sell_time, stock['stock_code'], stock['stock_name'], final_price, str(orderNum), jango, sell_price)
final_sell_check = True
"""
time.sleep(3600)
THIS_TIME = datetime.now()
return True
def updteTodayStock(self, stock_code, today_str):
bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str)
self.labelChecker.updateLabel(stock_code, bsLine, data, today_str)
return
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stocks = [
{"stock_code": "122630", "stock_name": "KODEX 레버리지"},
{"stock_code": "305720", "stock_name": "KODEX 2차전지산업"},
{"stock_code": "102780", "stock_name": "KODEX 삼성그룹"},
{"stock_code": "139260", "stock_name": "TIGER 200 IT"},
{"stock_code": "091180", "stock_name": "KODEX 자동차"},
{"stock_code": "401470", "stock_name": "KODEX K-메타버스액티브"},
{"stock_code": "329200", "stock_name": "TIGER 리츠부동산인프라"},
{"stock_code": "091170", "stock_name": "KODEX 은행"},
{"stock_code": "091160", "stock_name": "KODEX 반도체"},
{"stock_code": "161510", "stock_name": "ARIRANG 고배당주"},
{"stock_code": "228800", "stock_name": "TIGER 여행레저"},
{"stock_code": "150460", "stock_name": "TIGER 중국소비테마"},
{"stock_code": "143860", "stock_name": "TIGER 헬스케어"},
{"stock_code": "228810", "stock_name": "TIGER 미디어컨텐츠"},
{"stock_code": "139220", "stock_name": "TIGER 200 건설"},
{"stock_code": "139280", "stock_name": "TIGER 경기방어"},
{"stock_code": "322400", "stock_name": "HANARO e커머스"},
{"stock_code": "157490", "stock_name": "TIGER 소프트웨어"},
{"stock_code": "228790", "stock_name": "TIGER 화장품"},
{"stock_code": "139230", "stock_name": "TIGER 200 중공업"},
{"stock_code": "396500", "stock_name": "TIGER Fn반도체TOP10"},
{"stock_code": "365000", "stock_name": "TIGER KRX인터넷K-뉴딜"},
{"stock_code": "102970", "stock_name": "KODEX 증권"},
{"stock_code": "117680", "stock_name": "KODEX 철강"},
{"stock_code": "244580", "stock_name": "KODEX 바이오"},
{"stock_code": "266360", "stock_name": "KODEX 미디어&엔터테인먼트"},
{"stock_code": "375770", "stock_name": "KODEX 탄소효율그린뉴딜"},
{"stock_code": "364990", "stock_name": "TIGER KRX게임K-뉴딜"},
{"stock_code": "388420", "stock_name": "KBSTAR 비메모리반도체액티브"},
{"stock_code": "117460", "stock_name": "KODEX 에너지화학"},
{"stock_code": "300950", "stock_name": "KODEX 게임산업"},
{"stock_code": "266410", "stock_name": "KODEX 필수소비재"},
{"stock_code": "140700", "stock_name": "KODEX 보험"},
{"stock_code": "139270", "stock_name": "TIGER 200 금융"},
{"stock_code": "395160", "stock_name": "KODEX Fn시스템반도체"},
{"stock_code": "140710", "stock_name": "KODEX 운송"},
{"stock_code": "139240", "stock_name": "TIGER 200 철강소재"},
{"stock_code": "395150", "stock_name": "KODEX Fn웹툰&드라마"},
{"stock_code": "307510", "stock_name": "TIGER 의료기기"},
{"stock_code": "315270", "stock_name": "TIGER 200커뮤니케이션서비스"},
{"stock_code": "132030", "stock_name": "KODEX 골드선물(H)"},
{"stock_code": "144600", "stock_name": "KODEX 은선물(H)"},
{"stock_code": "261220", "stock_name": "KODEX WTI원유선물(H)"},
{"stock_code": "271050", "stock_name": "KODEX WTI원유선물인버스(H)"},
{"stock_code": "138910", "stock_name": "KODEX 구리선물(H)"}
]
hts = HTS_etf(RESOURCE_PATH)
hts.connect2DB("hts.db")
hts.connect2StockDB()
today_str = today.strftime('%Y%m%d')
hts.buyRealTime(today_str, stocks, analyzed_day=1000)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(stocks, today)
hts.disconnectStockDB()
hts.disconnect()
print ("done...")

View File

@@ -1,358 +0,0 @@
import time
import os
import math
import sqlite3
from datetime import datetime, timedelta
from hts.HTS import HTS
from hts.OrderType import OrderType
from hts.BuySellChecker import BuySellChecker
from hts.OrderChecker import OrderChecker
from stock.util.LabelChecker import LabelChecker
from stock.util.TelegramBot import TelegramBot
from stock.analysis.StockStatus import StockStatus
class HTS_etf (HTS):
RESOURCE_PATH = None
stock_code = None
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
bot = None
stockStatus = None
def __init__(self, RESOURCE_PATH):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.orderChecker = OrderChecker(self.RESOURCE_PATH, "ETF")
self.buySellChecker = BuySellChecker()
self.labelChecker = LabelChecker(RESOURCE_PATH)
self.bot = TelegramBot()
self.stockStatus = StockStatus(RESOURCE_PATH)
return
def connect2StockDB(self):
self.conn_stock = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "resources/stock.db"))
self.cursor_stock = self.conn_stock.cursor()
return
def disconnectStockDB(self):
self.cursor_stock.close()
self.conn_stock.close()
return
def sellStocks(self, stock_code=None, bs_sell_price=None):
check = False
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if stock_code is not None:
if code == "A"+stock_code and bs_sell_price is not None:
if jangoDic[code]['매도가능'] > 0:
if 2 < jangoDic[code]['평가손익']:
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price)
self.bot.post(code, jangoDic[code]['종목명'], "SELL", bs_sell_price, jangoDic[code]['매도가능'])
check = True
else:
continue
else:
if jangoDic[code]['매도가능'] > 0:
if 3 < jangoDic[code]['평가손익']:
# 3% 이상 시 수익 매도
currentStock = self.currentStock(code[1:])
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], currentStock['close'])
self.bot.post(code, jangoDic[code]['종목명'], "SELL", currentStock['close'], jangoDic[code]['매도가능'])
check = True
return check
def getSellingPrice(self, log_time, stock_code, final_price, without_loss=False):
# final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미
# final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미
# final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임
orderNum = None
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if jangoDic[code]['매도가능'] > 0:
if without_loss:
if jangoDic[code]['장부가']*0.07 < jangoDic[code]['장부가'] - final_price:
sell_price = jangoDic[code]['장부가']
if code == "A" + stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price
else:
max_price = max(jangoDic[code]['장부가'], final_price)
sell_price = (int(max_price) - int(max_price) % 5) + 5
if code == "A"+stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
return orderNum, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price
return orderNum, None, None, None
def makeTickData(self, data, mins=30):
result = {"check": set(),
"time": [],
"open": [],
"close": [],
"high": [],
"low": [],
"vol": [],
"label": []}
for i in range(mins, len(data['time'])+1):
result["check"].add(data['time'][i-1])
result["time"].append(data['time'][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["vol"].append(sum(data['vol'][i - mins: i]))
return result
def getStockType(self, stock_code, short=False):
slow_k, p_slow_k, slow_k_week, p_slow_k_week, slow_k_month, p_slow_k_month = -1, -1, -1, -1, -1, -1
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis where code=? group by 1 order by ymd desc',(stock_code,))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k = item[0]
elif i == 1:
p_slow_k = item[0]
else:
break
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis_weekly where code=? group by 1 order by ymd desc', (stock_code, ))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k_week = item[0]
elif i == 1:
p_slow_k_week = item[0]
else:
break
self.cursor_stock.execute('select stochastic_slow_k, max(ymd) from stock_analysis_monthly where code=? group by 1 order by ymd desc',(stock_code,))
items = self.cursor_stock.fetchall()
if items is not None and len(items) > 1:
for i, item in enumerate(items):
if i == 0:
slow_k_month = item[0]
elif i == 1:
p_slow_k_month = item[0]
else:
break
if slow_k is None or p_slow_k is None:
slow_k , p_slow_k = -1, -1
if slow_k_week is None or p_slow_k_week is None:
slow_k_week, p_slow_k_week = -1, -1
if slow_k_month is None or p_slow_k_month is None:
slow_k_month, p_slow_k_month = -1, -1
type_stock = {'day':1, 'week':10, 'month':100}
if short:
if slow_k < 10: type_stock['day'] = 10
if 10 < slow_k < 15: type_stock['day'] = 7.5
if 15 < slow_k < 20: type_stock['day'] = 5
if 20 < slow_k < 25: type_stock['day'] = 2.5
if slow_k_week < 10: type_stock['week'] = 100
if 10 < slow_k_week < 15: type_stock['week'] = 75
if 15 < slow_k_week < 20: type_stock['week'] = 50
if 20 < slow_k_week < 25: type_stock['week'] = 25
if slow_k_month < 10: type_stock['month'] = 1000
if 10 < slow_k_month < 15: type_stock['month'] = 750
if 15 < slow_k_month < 20: type_stock['month'] = 500
if 20 < slow_k_month < 25: type_stock['month'] = 250
else:
if slow_k > 90: type_stock['day'] = 10
if 85 < slow_k < 90: type_stock['day'] = 7.5
if 80 < slow_k < 85: type_stock['day'] = 5
if 75 < slow_k < 80: type_stock['day'] = 2.5
if slow_k_week > 90: type_stock['week'] = 100
if 85 < slow_k_week < 90: type_stock['week'] = 75
if 80 < slow_k_week < 85: type_stock['week'] = 50
if 75 < slow_k_week < 80: type_stock['week'] = 25
if slow_k_month > 90: type_stock['month'] = 1000
if 85 < slow_k_month < 90: type_stock['month'] = 750
if 80 < slow_k_month < 85: type_stock['month'] = 500
if 75 < slow_k_month < 80: type_stock['month'] = 250
return type_stock
def getBuyCount(self, bs_buy_price, kospi_type, stock_type):
base_price = 10000
log_base = 1.2
p_k_m, p_k_w, p_k_d, p_s_m, p_s_w, p_s_d = 0.3, 0.2, 0.05, 0.25, 0.18, 0.02
weight_1, weight_2, weight_3, weight_4, weight_5 = 0.5, 0.3, 0.14, 0.05, 0.01
kospi_weight = weight_5
if kospi_type['day'] == 10: kospi_weight = weight_1
if kospi_type['day'] == 7.5: kospi_weight = weight_2
if kospi_type['day'] == 5: kospi_weight = weight_3
if kospi_type['day'] == 2.5: kospi_weight = weight_4
stock_weight = weight_5
if stock_type['day'] == 10: stock_weight = weight_1
if stock_type['day'] == 7.5: stock_weight = weight_2
if stock_type['day'] == 5: stock_weight = weight_3
if stock_type['day'] == 2.5: stock_weight = weight_4
max_price = math.log(
kospi_weight * p_k_m * kospi_type['month'] +
kospi_weight * p_k_w * kospi_type['week'] +
kospi_weight * p_k_d * kospi_type['day'] +
stock_weight * p_s_m * stock_type['month'] +
stock_weight * p_s_w * stock_type['week'] +
stock_weight * p_s_d * stock_type['day'], log_base) * base_price
buy_count = 0
if max_price > 1:
buy_count = int(math.floor(max_price / bs_buy_price))
return buy_count
def buyRealTime(self, today, stocks, analyzed_day=1000):
print ("START...")
THIS_TIME = datetime.now()
kospi_type = self.getStockType("^KS11", short=False)
LAST_DATA = {}
for stock in stocks:
LAST_DATA[stock['stock_code']] = self.getLastData(stock['stock_code'], today)
while datetime.strptime(today + " 070000", '%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 + " 151500", '%Y%m%d %H%M%S'):
# 매도를 체크한다.
# self.sellStocks()
for idx, stock in enumerate(stocks):
time.sleep(0.1)
print("%5d: %8s, %-50s"%(idx, stock['stock_code'], stock['stock_name']))
try:
# 데이터를 가지고 온다.
data = self.getRealTime(stock['stock_code'], today, LAST_DATA[stock['stock_code']])
except:
print("#ERROR:", stock['stock_code'], stock['stock_name'])
continue
# 현재 매수가
bs_buy_price = data["close"][len(data["close"]) - 1]
# 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다.
ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.cancel(today, "A" + stock['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" + stock['stock_code'], hours=5):
stock_type = self.getStockType(stock['stock_code'], short=True)
buy_count = self.getBuyCount(bs_buy_price, kospi_type, stock_type)
if buy_count > 0:
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, stock['stock_code'], buy_count , bs_buy_price)
self.orderChecker.buy(today, "A" + stock['stock_code'], buy_count, bs_buy_price, orderNum)
# bot에 메시지를 보냄
self.bot.post(stock['stock_code'], stock['stock_name'], "BUY", bs_buy_price, buy_count)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock['stock_code'], stock['stock_name'], bs_buy_price, buy_count)
# 로그 출력
print("TIMECHECK: %s, code: %s, name: %s, buy: %d, avg5: %.2f, avg30: %.2f, open: %d, high: %d, low: %d, slow_k: %.2f" %
(str(THIS_TIME), stock['stock_code'], stock['stock_name'], bs_buy_price, data["avg5"][0], data["avg30"][0],
data["open"][0], data["high"][0], data["low"][0], data["slow_k"][0]))
"""
elif datetime.strptime(today + " 151530", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151600", '%Y%m%d %H%M%S'):
# 3시 15분 30초부터 3시 16분 사이는 잔량을 매도한다.
if not final_sell_check:
####
# 손해 보지 않는 가격에 매도한다.
####
for stock in stocks:
# 주문 리스트를 가져온다.
orderList = self.requestOrderList()
# 15:10:00 이후라면 모든 미체결 취소한다.
self.cancelOrderList(orderList)
# 매도 가격을 가져온다.
result = self.getRealTime(stock['stock_code'], today, LAST_DATA[stock['stock_code']])
final_price = result["close"][len(result["close"]) - 1]
orderNum, sell_time, jango, sell_price = self.getSellingPrice(THIS_TIME, stock['stock_code'], final_price, without_loss=True)
# 로그 출력
print("SELL", sell_time, stock['stock_code'], stock['stock_name'], final_price, str(orderNum), jango, sell_price)
final_sell_check = True
"""
time.sleep(3600)
THIS_TIME = datetime.now()
return True
def updteTodayStock(self, stock_code, today_str):
bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str)
self.labelChecker.updateLabel(stock_code, bsLine, data, today_str)
return
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stocks = [
{"stock_code": "252670", "stock_name": "KODEX 200선물인버스2X"}
]
hts = HTS_etf(RESOURCE_PATH)
hts.connect2DB("hts.db")
hts.connect2StockDB()
today_str = today.strftime('%Y%m%d')
hts.buyRealTime(today_str, stocks, analyzed_day=1000)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
hts.insertStockData(stocks, today)
hts.disconnectStockDB()
hts.disconnect()
print ("done...")

View File

@@ -1,181 +0,0 @@
import re
import os
import time
import psutil
import sqlite3
from datetime import datetime, timedelta
from hts.HTS import HTS
from hts.OrderType import OrderType
from hts.BuySellChecker import BuySellChecker
from hts.OrderChecker import OrderChecker
from stock.util.TelegramBot import TelegramBot
from stock.analysis.StockStatus import StockStatus
class HTS_Stocks (HTS):
RESOURCE_PATH = None
orderChecker = None
buySellChecker = None
labelChecker = None
bot = None
stockStatus = None
analyzed_day = None
MAX_BUY_PRICE = None
conn_stock = None
cursor_stock = None
def __init__(self, RESOURCE_PATH):
super().__init__(RESOURCE_PATH)
self.bot = TelegramBot()
self.RESOURCE_PATH = RESOURCE_PATH
self.stockStatus = StockStatus(RESOURCE_PATH)
self.buySellChecker = BuySellChecker(RESOURCE_PATH)
self.orderChecker = OrderChecker(self.RESOURCE_PATH, "STOCK")
self.analyzed_day = 120
self.MAX_BUY_PRICE = 300000
return
def connect2StockDB(self):
self.conn_stock = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "stock.db"))
self.cursor_stock = self.conn_stock.cursor()
return
def disconnectStockDB(self):
self.cursor_stock.close()
self.conn_stock.close()
return
def sellStocks(self, stock_code=None):
check = False
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if stock_code is not None:
if code == "A" + stock_code:
if jangoDic[code]['매도가능'] > 0:
if 3.0 < jangoDic[code]['평가손익']:
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
self.bot.sendMsg("Profit {} ({}): {:.2f} ({:.2f}%)".format(jangoDic[code]['종목명'], jangoDic[code]['종목코드'], (jangoDic[code]['현재가']-jangoDic[code]['장부가'])*jangoDic[code]['잔고수량'], jangoDic[code]['평가손익']))
check = True
else:
if 30.0 < jangoDic[code]['평가손익']:
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
self.bot.sendMsg("Profit {} ({}): {:.2f} ({:.2f}%)".format(jangoDic[code]['종목명'], jangoDic[code]['종목코드'], (jangoDic[code]['현재가']-jangoDic[code]['장부가'])*jangoDic[code]['잔고수량'], jangoDic[code]['평가손익']))
check = True
return check
def buyRealTime(self, today, n = 200):
print ("START...")
THIS_TIME = datetime.now()
while datetime.strptime(today + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'):
THIS_TIME = datetime.now()
# 1515 까지만 매수를 시도한다.
if datetime.strptime(today + " 090500", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
today_stock = self.get_today_stock()
if len(today_stock) < 1:
self.sellStocks()
time.sleep(300)
continue
for idx, stock in enumerate(today_stock):
stock_code = stock['code']
filename = stock['filename']
time.sleep(0.1)
stock = self.stockStatus.fetchLastData(self.cursor_stock, stock_code, n)
self.getRealTime_DailyCheck(today, stock_code, stock)
data = self.stockStatus.analyze(stock, self.analyzed_day)
# 매도
if not data['avg60'][-1] < data['avg20'][-1] < data['avg5'][-1]:
self.sellStocks(stock_code)
# 매수
bs_buy_price = data["close"][-1]
if 150000 < bs_buy_price:
buy_count = 1
else:
buy_count = 150000 // bs_buy_price
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price)
self.orderChecker.buy(today, "A" + stock_code, buy_count, bs_buy_price, orderNum)
# bot에 메시지를 보냄
self.bot.sendMsg('BUY {} {} ({})'.format(stock_code, bs_buy_price, buy_count))
arr = os.path.splitext(filename)
os.rename(filename, arr[0]+'.[BUY]'+arr[1])
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, '', bs_buy_price, buy_count)
if int(THIS_TIME.strftime("%M")) in (10, 40):
vm = psutil.virtual_memory()
vm_item = dict()
vm_item['free'] = vm.available // (1024 * 1024)
vm_item['idle'] = vm.available / vm.total * 100
hts.bot.sendMsg("Alive... mem: {:.1f}".format(vm_item['idle']))
time.sleep(100)
return
def updteTodayStock(self, db_filename, stock_code, today_str):
bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str)
self.labelChecker.updateLabel(db_filename, stock_code, bsLine, data, today_str)
return
def get_today_stock(self):
today_stock = []
path = os.path.join(self.RESOURCE_PATH, 'analysis', '종목선택')
file_list = os.listdir(path)
for filename in file_list:
# '20240130_2_daily_최적_타이밍_후보__1162_넥스틸_092790.html'
#pattern = '([0-9]+)_[1-9]_daily_최적_타이밍_후보__[0-9]+_([ㄱ-ㅎ가-힣a-zA-Z0-9]+)_([0-9]+)\.html'
pattern = '([0-9]+)_[1-9]_daily_final_candidate__[0-9]+_.*_([0-9]+)\.html'
info = re.search(pattern, filename)
if info is None:
continue
date_str = datetime.strptime(info.group(1), "%Y%m%d").strftime("%Y%m%d")
if date_str == datetime.today().strftime("%Y%m%d") or date_str == (datetime.today() - timedelta(days=1)).strftime("%Y%m%d"):
stock = {'code': info.group(2), 'filename': os.path.join(path, filename)}
today_stock.append(stock)
return today_stock
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
hts = HTS_Stocks(RESOURCE_PATH)
hts.connect2DB("hts.db")
hts.connect2StockDB()
today_str = today.strftime('%Y%m%d')
hts.buyRealTime(today_str)
hts.disconnectStockDB()
hts.disconnect()
print ("done...")

274
JSDPattern.py Normal file
View File

@@ -0,0 +1,274 @@
# 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

769
JSDPattern_daily.py Normal file
View File

@@ -0,0 +1,769 @@
# 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 numpy as np
from scipy.signal import argrelextrema
np.seterr(divide='ignore', invalid='ignore')
# 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 sklearn.preprocessing import MinMaxScaler
from JSDPattern import JSDPattern
class JSDPattern_daily(JSDPattern):
scaler = None
def __init__(self, RESOURCE_PATH=None):
super().__init__(RESOURCE_PATH)
self.scaler = MinMaxScaler()
return
def get_Support_Resistance(self, df):
n = 5
min_price = df.iloc[argrelextrema(df.values, np.less_equal, order=n)[0]]
max_price = df.iloc[argrelextrema(df.values, np.greater_equal, order=n)[0]]
return min_price.iloc[-1], max_price.iloc[-1]
def analyze_raw(self, result, mins=1440):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
min_price_list = [None for i in range(len(close_df)+51)]
max_price_list = [None for i in range(len(close_df)+51)]
for i in range(len(close_df)):
if 480 < i:
min_price_list[i], max_price_list[i] = self.get_Support_Resistance(close_df[i-120:i+1])
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
# ichimokuCloud
df = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
column_names = ['DATE', 'open', 'close', 'high', 'low', 'volume']
df.columns = column_names
c, b, l, s = 9, 26, 52, 26
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
# 3. 후행스팬 = 현재 close가격의 26일전 반영
laggingSpan = [df.close.values[i + s] for i in range(len(df.close) - s)]
laggingSpan += [None for i in range(s)]
laggingSpan = np.array(laggingSpan)
# 4. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
tmp_leadingSpan1 = (changeLine + baseLine) / 2
""" S: 26일 선행시킴 """
leadingSpan1 = list(tmp_leadingSpan1.values)
for i in range(b - 1):
leadingSpan1.insert(0, None)
""" E: 26일 선행시킴 """
# 5. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
tmp_leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
""" S: 52일 선행시킴 """
leadingSpan2 = list(tmp_leadingSpan2.values)
for i in range(l - 1):
leadingSpan2.insert(0, None)
""" S: 52일 선행시킴 """
baseLine = baseLine.tolist()
changeLine = changeLine.tolist()
laggingSpan = list(laggingSpan)
current_index = len(ymd)
for i in range(51):
if len(ymd) < len(leadingSpan2):
if mins == 1440:
ymd.append(ymd[-1] + timedelta(days=1))
else:
ymd.append(ymd[-1] + timedelta(minutes=1))
if len(open) < len(leadingSpan2):
open.append(None)
if len(close) < len(leadingSpan2):
close.append(None)
if len(high) < len(leadingSpan2):
high.append(None)
if len(low) < len(leadingSpan2):
low.append(None)
if len(volume) < len(leadingSpan2):
volume.append(None)
if len(baseLine) < len(leadingSpan2):
baseLine.append(None)
if len(changeLine) < len(leadingSpan2):
changeLine.append(None)
if len(laggingSpan) < len(leadingSpan2):
laggingSpan.append(None)
for i in range(26):
if len(leadingSpan1) < len(leadingSpan2):
leadingSpan1.append(leadingSpan1[-1])
# 7일 신고가
new_high_7 = [0 for c in range(6)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close[c - 6:c + 1] and max(close[c - 6:c]) < close[c] else 0 for c in range(6, len(close))]
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close[c - 8:c + 1] and max(close[c - 8:c]) < close[c] else 0 for c in range(8, len(close))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (baseLine[c - 1] is not None and baseLine[c] is not None and baseLine[c - 1] < baseLine[c]) and None not in close[c - 8:c + 1] and max(close[c - 25:c]) < close[c] else 0 for c in range(25, len(close))]
# 33일 신고가
new_high_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c - 1] is not None and leadingSpan1[c] is not None and leadingSpan1[c - 1] < leadingSpan1[c]) and None not in close[c - 8:c + 1] and max(close[c - 32:c]) < close[c] else 0 for c in range(32, len(close))]
# 52일 신고가
new_high_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c - 1] is not None and leadingSpan2[c] is not None and leadingSpan2[c - 1] < leadingSpan2[c]) and None not in close[c - 8:c + 1] and max(close[c - 51:c]) < close[c] else 0 for c in range(51, len(close))]
# 7일 신저가
new_low_7 = [0 for c in range(6)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close[c - 6:c + 1] and close[c - 7] < min(close[c - 6:c + 1]) else 0 for c in range(6, len(close))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close[c - 8:c + 1] and close[c - 9] < min(close[c - 8:c + 1]) else 0 for c in range(8, len(close))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (baseLine[c - 1] is not None and baseLine[c] is not None and baseLine[c - 1] < baseLine[c]) and None not in close[c - 8:c + 1] and close[c - 26] < min(close[c - 25:c + 1]) else 0 for c in range(25, len(close))]
# 33일 신저가
new_low_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c - 1] is not None and leadingSpan1[c] is not None and leadingSpan1[c - 1] < leadingSpan1[c]) and None not in close[c - 8:c + 1] and close[c - 33] < min(close[c - 32:c + 1]) else 0 for c in range(32, len(close))]
# 52일 신저가
new_low_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c - 1] is not None and leadingSpan2[c] is not None and leadingSpan2[c - 1] < leadingSpan2[c]) and None not in close[c - 8:c + 1] and close[c - 52] < min(close[c - 51:c + 1]) else 0 for c in range(51, len(close))]
# 이동 평균
close_df = pd.DataFrame(close)
avg5 = list(np.reshape(close_df.ewm(5).mean().values, -1))
avg10 = list(np.reshape(close_df.ewm(10).mean().values, -1))
avg20 = list(np.reshape(close_df.ewm(20).mean().values, -1))
avg60 = list(np.reshape(close_df.ewm(60).mean().values, -1))
avg90 = list(np.reshape(close_df.ewm(90).mean().values, -1))
avg120 = list(np.reshape(close_df.ewm(120).mean().values, -1))
avg240 = list(np.reshape(close_df.ewm(240).mean().values, -1))
avg360 = list(np.reshape(close_df.ewm(360).mean().values, -1))
avg480 = list(np.reshape(close_df.ewm(480).mean().values, -1))
avg720 = list(np.reshape(close_df.ewm(720).mean().values, -1))
avg1440 = list(np.reshape(close_df.ewm(1440).mean().values, -1))
avg2880 = list(np.reshape(close_df.ewm(2880).mean().values, -1))
# 이격도
disparity_avg5_df = (close_df / close_df.ewm(span=5, min_periods=5, adjust=False).mean())
disparity_avg10_df = (close_df / close_df.ewm(span=10, min_periods=10, adjust=False).mean())
disparity_avg20_df = (close_df / close_df.ewm(span=20, min_periods=20, adjust=False).mean())
disparity_avg60_df = (close_df / close_df.ewm(span=60, min_periods=60, adjust=False).mean())
disparity_avg120_df = (close_df / close_df.ewm(span=120, min_periods=120, adjust=False).mean())
disparity_avg240_df = (close_df / close_df.ewm(span=240, min_periods=240, adjust=False).mean())
disparity_avg480_df = (close_df / close_df.ewm(span=480, min_periods=480, adjust=False).mean())
disparity_avg720_df = (close_df / close_df.ewm(span=720, min_periods=720, adjust=False).mean())
disparity_avg1440_df = (close_df / close_df.ewm(span=1440, min_periods=1440, adjust=False).mean())
disparity_480_loc = [0 for i in range(len(close))]
disparity_1440_loc = [0 for i in range(len(close))]
disparity_avg480_list = list(disparity_avg480_df.values.reshape(-1))
disparity_avg1440_list = list(disparity_avg1440_df.values.reshape(-1))
for i in range(0, len(close)):
if 2880 < i:
l = [d for d in disparity_avg480_list[i - 1440:i + 1]]
min_v = np.min(l)
max_v = np.max(l)
disparity_480_loc[i] = (disparity_avg480_list[i] - min_v) / (max_v - min_v)
l = [d for d in disparity_avg1440_list[i - 1440:i + 1]]
min_v = np.min(l)
max_v = np.max(l)
disparity_1440_loc[i] = (disparity_avg1440_list[i] - min_v) / (max_v - min_v)
disparity_480_loc_df = pd.DataFrame(disparity_480_loc)
disparity_1440_loc_df = pd.DataFrame(disparity_1440_loc)
np_high, np_low, np_close = np.array(high, dtype=np.float64), np.array(low, dtype=np.float64), np.array(close, dtype=np.float64)
slowk_5_df, slowd_5_df = talib.STOCH(np_high, np_low, np_close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
slowk_10_df, slowd_10_df = talib.STOCH(np_high, np_low, np_close, fastk_period=10, slowk_period=6, slowk_matype=0, slowd_period=6, slowd_matype=0)
slowk_20_df, slowd_20_df = talib.STOCH(np_high, np_low, np_close, fastk_period=20, slowk_period=12, slowk_matype=0, slowd_period=12, slowd_matype=0)
slowk_60_df, slowd_60_df = talib.STOCH(np_high, np_low, np_close, fastk_period=60, slowk_period=37, slowk_matype=0, slowd_period=37, slowd_matype=0)
slowk_120_df, slowd_120_df = talib.STOCH(np_high, np_low, np_close, fastk_period=120, slowk_period=74, slowk_matype=0, slowd_period=74, slowd_matype=0)
slowk_240_df, slowd_240_df = talib.STOCH(np_high, np_low, np_close, fastk_period=240, slowk_period=148, slowk_matype=0, slowd_period=148, slowd_matype=0)
slowk_480_df, slowd_480_df = talib.STOCH(np_high, np_low, np_close, fastk_period=480, slowk_period=296, slowk_matype=0, slowd_period=296, slowd_matype=0)
# 최고/최저 위치
loc_240 = [None for i in range(len(close))]
for i in range(240, len(close)):
min_v = np.min(result["close"][i - 239:i + 1])
max_v = np.max(result["close"][i - 239:i + 1])
if close[i] is not None:
loc_240[i] = ((close[i] - min_v) / (max_v - min_v))
else:
loc_240[i] = None
loc_240 = pd.DataFrame(loc_240)
loc_240_k = loc_240.to_numpy().reshape(-1)
loc_240_d = loc_240.rolling(20).mean()
loc_240_s = loc_240.rolling(60).mean()
loc_240_d = loc_240_d.to_numpy().reshape(-1)
loc_240_s = loc_240_s.to_numpy().reshape(-1)
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
width_df = (upper_20 - lower_20) / middle_20
width_min = np.min(width_df[0])
width_max = np.max(width_df[0])
bb_width_df = 100 * (width_df - width_min) / (width_max - width_min)
bb_pb_df = 100 * (close_df - lower_20) / (upper_20 - lower_20)
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
disparity_avg5_list = list(disparity_avg5_df.values.reshape(-1))
disparity_avg20_list = list(disparity_avg20_df.values.reshape(-1))
disparity_avg60_list = list(disparity_avg60_df.values.reshape(-1))
disparity_avg120_list = list(disparity_avg120_df.values.reshape(-1))
disparity_avg240_list = list(disparity_avg240_df.values.reshape(-1))
disparity_avg480_list = list(disparity_avg480_df.values.reshape(-1))
disparity_avg720_list = list(disparity_avg720_df.values.reshape(-1))
disparity_avg1440_list = list(disparity_avg1440_df.values.reshape(-1))
disparity_diff_20_5, disparity_diff_20_5_rate = self.getDiff_Rate(disparity_avg20_list, disparity_avg5_list, duration=20)
disparity_diff_60_20, disparity_diff_60_20_rate = self.getDiff_Rate(disparity_avg60_list, disparity_avg5_list, duration=60)
disparity_diff_120_20, disparity_diff_120_20_rate = self.getDiff_Rate(disparity_avg120_list, disparity_avg5_list, duration=120)
disparity_diff_240_20, disparity_diff_240_20_rate = self.getDiff_Rate(disparity_avg240_list, disparity_avg5_list, duration=240)
disparity_diff_480_20, disparity_diff_480_20_rate = self.getDiff_Rate(disparity_avg480_list, disparity_avg5_list, duration=480)
disparity_diff_720_20, disparity_diff_720_20_rate = self.getDiff_Rate(disparity_avg720_list, disparity_avg5_list, duration=720)
disparity_diff_1440_20, disparity_diff_1440_20_rate = self.getDiff_Rate(disparity_avg1440_list, disparity_avg5_list, duration=1440)
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
pd.DataFrame(changeLine), pd.DataFrame(baseLine), pd.DataFrame(laggingSpan), pd.DataFrame(leadingSpan1), pd.DataFrame(leadingSpan2),
pd.DataFrame(disparity_diff_20_5), pd.DataFrame(disparity_diff_20_5_rate),
pd.DataFrame(disparity_diff_60_20), pd.DataFrame(disparity_diff_60_20_rate),
pd.DataFrame(disparity_diff_120_20), pd.DataFrame(disparity_diff_120_20_rate),
pd.DataFrame(disparity_diff_240_20), pd.DataFrame(disparity_diff_240_20_rate),
pd.DataFrame(disparity_diff_480_20), pd.DataFrame(disparity_diff_480_20_rate),
pd.DataFrame(disparity_diff_720_20), pd.DataFrame(disparity_diff_720_20_rate),
pd.DataFrame(disparity_diff_1440_20), pd.DataFrame(disparity_diff_1440_20_rate),
pd.DataFrame(loc_240_k), pd.DataFrame(loc_240_d), pd.DataFrame(loc_240_s),
pd.DataFrame(avg5), pd.DataFrame(avg10), pd.DataFrame(avg20), pd.DataFrame(avg60), pd.DataFrame(avg90), pd.DataFrame(avg120), pd.DataFrame(avg240), pd.DataFrame(avg360), pd.DataFrame(avg480), pd.DataFrame(avg720), pd.DataFrame(avg1440), pd.DataFrame(avg2880),
disparity_avg5_df, disparity_avg10_df, disparity_avg20_df, disparity_avg60_df, disparity_avg120_df, disparity_avg240_df, disparity_avg480_df, disparity_avg720_df, disparity_avg1440_df, disparity_480_loc_df, disparity_1440_loc_df,
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20),
bb_width_df, bb_pb_df,
pd.DataFrame(new_high_7), pd.DataFrame(new_high_9), pd.DataFrame(new_high_26), pd.DataFrame(new_high_33), pd.DataFrame(new_high_52),
pd.DataFrame(new_low_7), pd.DataFrame(new_low_9), pd.DataFrame(new_low_26), pd.DataFrame(new_low_33), pd.DataFrame(new_low_52),
pd.DataFrame(slowk_5_df), pd.DataFrame(slowd_5_df),
pd.DataFrame(slowk_10_df), pd.DataFrame(slowd_10_df),
pd.DataFrame(slowk_20_df), pd.DataFrame(slowd_20_df),
pd.DataFrame(slowk_60_df), pd.DataFrame(slowd_60_df),
pd.DataFrame(slowk_120_df), pd.DataFrame(slowd_120_df),
pd.DataFrame(slowk_240_df), pd.DataFrame(slowd_240_df),
pd.DataFrame(slowk_480_df), pd.DataFrame(slowd_480_df),
pd.DataFrame(min_price_list), pd.DataFrame(max_price_list)
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'changeLine', 'baseLine', 'laggingSpan', 'leadingSpan1', 'leadingSpan2',
'disparity_diff_20_5', 'disparity_diff_20_5_rate',
'disparity_diff_60_20', 'disparity_diff_60_20_rate',
'disparity_diff_120_20', 'disparity_diff_120_20_rate',
'disparity_diff_240_20', 'disparity_diff_240_20_rate',
'disparity_diff_480_20', 'disparity_diff_480_20_rate',
'disparity_diff_720_20', 'disparity_diff_720_20_rate',
'disparity_diff_1440_20', 'disparity_diff_1440_20_rate',
'loc_240_k', 'loc_240_d', 'loc_240_s',
'avg5', 'avg10', 'avg20', 'avg60', 'avg90', 'avg120', 'avg240', 'avg360', 'avg480', 'avg720', 'avg1440', 'avg2880',
'disparity_avg5', 'disparity_avg10', 'disparity_avg20', 'disparity_avg60', 'disparity_avg120', 'disparity_avg240', 'disparity_avg480', 'disparity_avg720', 'disparity_avg1440', 'disparity_480_loc', 'disparity_1440_loc',
'upper_20', 'lower_20', 'middle_20',
'bb_width', 'bb_pb',
'new_high_7', 'new_high_9', 'new_high_26', 'new_high_33', 'new_high_52',
'new_low_7', 'new_low_9', 'new_low_26', 'new_low_33', 'new_low_52',
'slowk_5', 'slowd_5',
'slowk_10', 'slowd_10',
'slowk_20', 'slowd_20',
'slowk_60', 'slowd_60',
'slowk_120', 'slowd_120',
'slowk_240', 'slowd_240',
'slowk_480', 'slowd_480',
'min_price', 'max_price'
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
return data, current_index
def analyze_scale(self, result, mins=1440):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
min_price_list = [None for i in range(len(close_df)+51)]
max_price_list = [None for i in range(len(close_df)+51)]
for i in range(len(close_df)):
if 480 < i:
min_price_list[i], max_price_list[i] = self.get_Support_Resistance(close_df[i-120:i+1])
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
open_scaled = (self.scaler.fit_transform(pd.DataFrame(open))).reshape(1,-1)[0]
open_scaled = [0.0000000001 if c==0 else c for c in open_scaled]
close_scaled = (self.scaler.fit_transform(pd.DataFrame(close))).reshape(1,-1)[0]
close_scaled = [0.0000000001 if c == 0 else c for c in close_scaled]
high_scaled = (self.scaler.fit_transform(pd.DataFrame(high))).reshape(1,-1)[0]
high_scaled = [0.0000000001 if c == 0 else c for c in high_scaled]
low_scaled = (self.scaler.fit_transform(pd.DataFrame(low))).reshape(1,-1)[0]
low_scaled = [0.0000000001 if c == 0 else c for c in low_scaled]
volume_scaled = (self.scaler.fit_transform(pd.DataFrame(volume))).reshape(1, -1)[0]
volume_scaled = [0.0000000001 if c == 0 else c for c in volume_scaled]
if len(close_scaled) < 5:
poly_5 = [0] * len(close_scaled)
else:
poly_5 = [0] * 4 + [np.polyfit(range(5), close_scaled[i - 4: i + 1], 1)[0] for i in range(4, len(close))]
if len(close_scaled) < 10:
poly_10 = [0] * len(close_scaled)
else:
poly_10 = [0] * 9 + [np.polyfit(range(10), close_scaled[i - 9: i + 1], 1)[0] for i in range(9, len(close))]
if len(close_scaled) < 20:
poly_20 = [0] * len(close_scaled)
else:
poly_20 = [0] * 19 + [np.polyfit(range(20), close_scaled[i - 19: i + 1], 1)[0] for i in range(19, len(close))]
if len(poly_5) < 60:
poly_60 = [0] * len(close_scaled)
else:
poly_60 = [0] * 59 + [np.polyfit(range(60), close_scaled[i - 59: i + 1], 1)[0] for i in range(59, len(close))]
if len(close_scaled) < 120:
poly_120 = [0] * len(close_scaled)
else:
poly_120 = [0] * 119 + [np.polyfit(range(120), close_scaled[i - 119: i + 1], 1)[0] for i in range(119, len(close))]
if len(close_scaled) < 240:
poly_240 = [0] * len(close_scaled)
else:
poly_240 = [0] * 239 + [np.polyfit(range(240), close_scaled[i - 239: i + 1], 1)[0] for i in range(239, len(close))]
if len(close_scaled) < 480:
poly_480 = [0] * len(close_scaled)
else:
poly_480 = [0] * 479 + [np.polyfit(range(480), close_scaled[i - 479: i + 1], 1)[0] for i in range(479, len(close))]
# ichimokuCloud
df = pd.concat([pd.DataFrame(ymd), pd.DataFrame(open_scaled), pd.DataFrame(close_scaled), pd.DataFrame(high_scaled), pd.DataFrame(low_scaled), pd.DataFrame(volume_scaled)], axis=1)
column_names = ['DATE', 'open', 'close', 'high', 'low', 'volume']
df.columns = column_names
c, b, l, s = 9, 26, 52, 26
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
# 3. 후행스팬 = 현재 close가격의 26일전 반영
laggingSpan = [df.close.values[i + s] for i in range(len(df.close) - s)]
laggingSpan += [None for i in range(s)]
laggingSpan = np.array(laggingSpan)
# 4. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
tmp_leadingSpan1 = (changeLine + baseLine) / 2
""" S: 26일 선행시킴 """
leadingSpan1 = list(tmp_leadingSpan1.values)
for i in range(b - 1):
leadingSpan1.insert(0, None)
""" E: 26일 선행시킴 """
# 5. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
tmp_leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
""" S: 52일 선행시킴 """
leadingSpan2 = list(tmp_leadingSpan2.values)
for i in range(l - 1):
leadingSpan2.insert(0, None)
""" S: 52일 선행시킴 """
baseLine = baseLine.tolist()
changeLine = changeLine.tolist()
laggingSpan = list(laggingSpan)
current_index = len(ymd)
for i in range(51):
if len(ymd) < len(leadingSpan2):
if mins == 1440:
ymd.append(ymd[-1] + timedelta(days=1))
else:
ymd.append(ymd[-1] + timedelta(minutes=1))
if len(open) < len(leadingSpan2):
open.append(None)
if len(close) < len(leadingSpan2):
close.append(None)
if len(high) < len(leadingSpan2):
high.append(None)
if len(low) < len(leadingSpan2):
low.append(None)
if len(volume) < len(leadingSpan2):
volume.append(None)
if len(baseLine) < len(leadingSpan2):
baseLine.append(None)
if len(changeLine) < len(leadingSpan2):
changeLine.append(None)
if len(laggingSpan) < len(leadingSpan2):
laggingSpan.append(None)
for i in range(26):
if len(leadingSpan1) < len(leadingSpan2):
leadingSpan1.append(leadingSpan1[-1])
# 7일 신고가
new_high_7 = [0 for c in range(6)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close_scaled[c - 6:c + 1] and max(close_scaled[c - 6:c]) < close_scaled[c] else 0 for c in range(6, len(close_scaled))]
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close_scaled[c - 8:c + 1] and max(close_scaled[c - 8:c]) < close_scaled[c] else 0 for c in range(8, len(close_scaled))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (baseLine[c - 1] is not None and baseLine[c] is not None and baseLine[c - 1] < baseLine[c]) and None not in close_scaled[c - 8:c + 1] and max(close_scaled[c - 25:c]) < close_scaled[c] else 0 for c in range(25, len(close_scaled))]
# 33일 신고가
new_high_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c - 1] is not None and leadingSpan1[c] is not None and leadingSpan1[c - 1] < leadingSpan1[c]) and None not in close_scaled[c - 8:c + 1] and max(close_scaled[c - 32:c]) < close_scaled[c] else 0 for c in range(32, len(close_scaled))]
# 52일 신고가
new_high_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c - 1] is not None and leadingSpan2[c] is not None and leadingSpan2[c - 1] < leadingSpan2[c]) and None not in close_scaled[c - 8:c + 1] and max(close_scaled[c - 51:c]) < close_scaled[c] else 0 for c in range(51, len(close_scaled))]
# 7일 신저가
new_low_7 = [0 for c in range(6)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close_scaled[c - 6:c + 1] and close_scaled[c - 7] < min(close_scaled[c - 6:c + 1]) else 0 for c in range(6, len(close_scaled))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (changeLine[c - 1] is not None and changeLine[c] is not None and changeLine[c - 1] < changeLine[c]) and None not in close_scaled[c - 8:c + 1] and close_scaled[c - 9] < min(close_scaled[c - 8:c + 1]) else 0 for c in range(8, len(close_scaled))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (baseLine[c - 1] is not None and baseLine[c] is not None and baseLine[c - 1] < baseLine[c]) and None not in close_scaled[c - 8:c + 1] and close_scaled[c - 26] < min(close_scaled[c - 25:c + 1]) else 0 for c in range(25, len(close_scaled))]
# 33일 신저가
new_low_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c - 1] is not None and leadingSpan1[c] is not None and leadingSpan1[c - 1] < leadingSpan1[c]) and None not in close_scaled[c - 8:c + 1] and close_scaled[c - 33] < min(close_scaled[c - 32:c + 1]) else 0 for c in range(32, len(close_scaled))]
# 52일 신저가
new_low_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c - 1] is not None and leadingSpan2[c] is not None and leadingSpan2[c - 1] < leadingSpan2[c]) and None not in close_scaled[c - 8:c + 1] and close_scaled[c - 52] < min(close_scaled[c - 51:c + 1]) else 0 for c in range(51, len(close_scaled))]
# 이동 평균
close_df = pd.DataFrame(close_scaled)
avg5 = list(np.reshape(close_df.ewm(5).mean().values, -1))
avg10 = list(np.reshape(close_df.ewm(10).mean().values, -1))
avg20 = list(np.reshape(close_df.ewm(20).mean().values, -1))
avg60 = list(np.reshape(close_df.ewm(60).mean().values, -1))
avg90 = list(np.reshape(close_df.ewm(90).mean().values, -1))
avg120 = list(np.reshape(close_df.ewm(120).mean().values, -1))
avg240 = list(np.reshape(close_df.ewm(240).mean().values, -1))
avg360 = list(np.reshape(close_df.ewm(360).mean().values, -1))
avg480 = list(np.reshape(close_df.ewm(480).mean().values, -1))
avg720 = list(np.reshape(close_df.ewm(720).mean().values, -1))
avg1440 = list(np.reshape(close_df.ewm(1440).mean().values, -1))
avg2880 = list(np.reshape(close_df.ewm(2880).mean().values, -1))
# 이격도
disparity_avg5_df = (close_df / close_df.ewm(span=5, min_periods=5, adjust=False).mean())
disparity_avg20_df = (close_df / close_df.ewm(span=20, min_periods=20, adjust=False).mean())
disparity_avg60_df = (close_df / close_df.ewm(span=60, min_periods=60, adjust=False).mean())
disparity_avg120_df = (close_df / close_df.ewm(span=120, min_periods=120, adjust=False).mean())
disparity_avg240_df = (close_df / close_df.ewm(span=240, min_periods=240, adjust=False).mean())
disparity_avg480_df = (close_df / close_df.ewm(span=480, min_periods=480, adjust=False).mean())
disparity_avg1440_df = (close_df / close_df.ewm(span=1440, min_periods=1440, adjust=False).mean())
disparity_480_loc = [0 for i in range(len(close))]
disparity_1440_loc = [0 for i in range(len(close))]
disparity_avg480_list = list(disparity_avg480_df.values.reshape(-1))
disparity_avg1440_list = list(disparity_avg1440_df.values.reshape(-1))
for i in range(0, len(close)):
if 2880 < i:
l = [d for d in disparity_avg480_list[i - 1440:i + 1]]
min_v = np.min(l)
max_v = np.max(l)
disparity_480_loc[i] = (disparity_avg480_list[i] - min_v) / (max_v - min_v)
l = [d for d in disparity_avg1440_list[i - 1440:i + 1]]
min_v = np.min(l)
max_v = np.max(l)
disparity_1440_loc[i] = (disparity_avg1440_list[i] - min_v) / (max_v - min_v)
disparity_480_loc_df = pd.DataFrame(disparity_480_loc)
disparity_1440_loc_df = pd.DataFrame(disparity_1440_loc)
disparity_avg5_list = list(disparity_avg5_df.values.reshape(-1))
disparity_avg20_list = list(disparity_avg20_df.values.reshape(-1))
disparity_avg60_list = list(disparity_avg60_df.values.reshape(-1))
disparity_avg120_list = list(disparity_avg120_df.values.reshape(-1))
disparity_avg240_list = list(disparity_avg240_df.values.reshape(-1))
disparity_avg480_list = list(disparity_avg480_df.values.reshape(-1))
disparity_avg1440_list = list(disparity_avg1440_df.values.reshape(-1))
disparity_diff_20_5, disparity_diff_20_5_rate = self.getDiff_Rate(disparity_avg20_list, disparity_avg5_list, duration=20)
disparity_diff_60_20, disparity_diff_60_20_rate = self.getDiff_Rate(disparity_avg60_list, disparity_avg20_list, duration=60)
disparity_diff_120_20, disparity_diff_120_20_rate = self.getDiff_Rate(disparity_avg120_list, disparity_avg20_list, duration=120)
disparity_diff_240_20, disparity_diff_240_20_rate = self.getDiff_Rate(disparity_avg240_list, disparity_avg20_list, duration=240)
disparity_diff_480_20, disparity_diff_480_20_rate = self.getDiff_Rate(disparity_avg480_list, disparity_avg20_list, duration=480)
disparity_diff_1440_20, disparity_diff_1440_20_rate = self.getDiff_Rate(disparity_avg1440_list, disparity_avg20_list, duration=1440)
np_high, np_low, np_close = np.array(high_scaled, dtype=np.float64), np.array(low_scaled, dtype=np.float64), np.array(close_scaled, dtype=np.float64)
slowk_5_df, slowd_5_df = talib.STOCH(np_high, np_low, np_close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
slowk_10_df, slowd_10_df = talib.STOCH(np_high, np_low, np_close, fastk_period=10, slowk_period=6, slowk_matype=0, slowd_period=6, slowd_matype=0)
slowk_20_df, slowd_20_df = talib.STOCH(np_high, np_low, np_close, fastk_period=20, slowk_period=12, slowk_matype=0, slowd_period=12, slowd_matype=0)
slowk_60_df, slowd_60_df = talib.STOCH(np_high, np_low, np_close, fastk_period=60, slowk_period=37, slowk_matype=0, slowd_period=37, slowd_matype=0)
slowk_120_df, slowd_120_df = talib.STOCH(np_high, np_low, np_close, fastk_period=120, slowk_period=74, slowk_matype=0, slowd_period=74, slowd_matype=0)
slowk_240_df, slowd_240_df = talib.STOCH(np_high, np_low, np_close, fastk_period=240, slowk_period=148, slowk_matype=0, slowd_period=148, slowd_matype=0)
slowk_480_df, slowd_480_df = talib.STOCH(np_high, np_low, np_close, fastk_period=480, slowk_period=296, slowk_matype=0, slowd_period=296, slowd_matype=0)
# 최고/최저 위치
loc_240 = [None for i in range(len(close))]
for i in range(240, len(close)):
min_v = np.min(close_scaled[i - 239:i + 1])
max_v = np.max(close_scaled[i - 239:i + 1])
if close[i] is not None:
loc_240[i] = ((close_scaled[i] - min_v) / (max_v - min_v))
else:
loc_240[i] = None
loc_240 = pd.DataFrame(loc_240)
loc_240_k = loc_240.to_numpy().reshape(-1)
loc_240_d = loc_240.rolling(20).mean()
loc_240_s = loc_240.rolling(60).mean()
loc_240_d = loc_240_d.to_numpy().reshape(-1)
loc_240_s = loc_240_s.to_numpy().reshape(-1)
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
width_df = (upper_20 - lower_20) / middle_20
width_min = np.min(width_df[0])
width_max = np.max(width_df[0])
bb_width_df = 100 * (width_df - width_min) / (width_max - width_min)
bb_pb_df = 100 * (close_df - lower_20) / (upper_20 - lower_20)
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
duration = 1440
if mins == 1440:
duration = 360
laggingSpan_close_diff, laggingSpan_close_diff_rate = self.getDiff_Rate(laggingSpan, close_scaled, duration=duration)
laggingSpan_changeLine_diff, laggingSpan_changeLine_diff_rate = self.getDiff_Rate(laggingSpan, changeLine, duration=duration)
laggingSpan_baseLine_diff, laggingSpan_baseLine_diff_rate = self.getDiff_Rate(laggingSpan, baseLine, duration=duration)
laggingSpan_leadingSpan1_diff, laggingSpan_leadingSpan1_diff_rate = self.getDiff_Rate(laggingSpan, leadingSpan1, duration=duration)
laggingSpan_leadingSpan2_diff, laggingSpan_leadingSpan2_diff_rate = self.getDiff_Rate(laggingSpan, leadingSpan2, duration=duration)
laggingSpan_avg60_diff, laggingSpan_avg60_diff_rate = self.getDiff_Rate(laggingSpan, avg60, duration=duration)
laggingSpan_lower20_diff, laggingSpan_lower20_diff_rate = self.getDiff_Rate(laggingSpan, lower_20, duration=duration)
laggingSpan_middle20_diff, laggingSpan_middle20_diff_rate = self.getDiff_Rate(laggingSpan, middle_20, duration=duration)
laggingSpan_upper20_diff, laggingSpan_upper20_diff_rate = self.getDiff_Rate(laggingSpan, upper_20, duration=duration)
baseLine_close_diff, baseLine_close_diff_rate = self.getDiff_Rate(baseLine, close_scaled, duration=duration)
changeLine_close_diff, changeLine_close_diff_rate = self.getDiff_Rate(changeLine, close_scaled, duration=duration)
changeLine_baseLine_diff, changeLine_baseLine_diff_rate = self.getDiff_Rate(changeLine, baseLine, duration=duration)
changeLine_leadingSpan1_diff, changeLine_leadingSpan1_diff_rate = self.getDiff_Rate(changeLine, leadingSpan1, duration=duration)
leadingSpan1_leadingSpan2_diff, leadingSpan1_leadingSpan2_diff_rate = self.getDiff_Rate(leadingSpan1, leadingSpan2, duration=duration)
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open_scaled), pd.DataFrame(close_scaled), pd.DataFrame(high_scaled), pd.DataFrame(low_scaled), pd.DataFrame(volume_scaled),
pd.DataFrame(changeLine), pd.DataFrame(baseLine), pd.DataFrame(laggingSpan), pd.DataFrame(leadingSpan1), pd.DataFrame(leadingSpan2),
pd.DataFrame(laggingSpan_close_diff),
pd.DataFrame(laggingSpan_changeLine_diff),
pd.DataFrame(laggingSpan_baseLine_diff),
pd.DataFrame(laggingSpan_leadingSpan1_diff),
pd.DataFrame(laggingSpan_leadingSpan2_diff),
pd.DataFrame(laggingSpan_avg60_diff),
pd.DataFrame(laggingSpan_lower20_diff),
pd.DataFrame(laggingSpan_middle20_diff),
pd.DataFrame(laggingSpan_upper20_diff),
pd.DataFrame(baseLine_close_diff),
pd.DataFrame(changeLine_close_diff),
pd.DataFrame(changeLine_baseLine_diff),
pd.DataFrame(changeLine_leadingSpan1_diff),
pd.DataFrame(leadingSpan1_leadingSpan2_diff),
pd.DataFrame(laggingSpan_close_diff_rate),
pd.DataFrame(laggingSpan_changeLine_diff_rate),
pd.DataFrame(laggingSpan_baseLine_diff_rate),
pd.DataFrame(laggingSpan_leadingSpan1_diff_rate),
pd.DataFrame(laggingSpan_leadingSpan2_diff_rate),
pd.DataFrame(laggingSpan_avg60_diff_rate),
pd.DataFrame(laggingSpan_lower20_diff_rate),
pd.DataFrame(laggingSpan_middle20_diff_rate),
pd.DataFrame(laggingSpan_upper20_diff_rate),
pd.DataFrame(baseLine_close_diff_rate),
pd.DataFrame(changeLine_close_diff_rate),
pd.DataFrame(changeLine_baseLine_diff_rate),
pd.DataFrame(changeLine_leadingSpan1_diff_rate),
pd.DataFrame(leadingSpan1_leadingSpan2_diff_rate),
pd.DataFrame(loc_240_k), pd.DataFrame(loc_240_d), pd.DataFrame(loc_240_s),
pd.DataFrame(avg5), pd.DataFrame(avg10), pd.DataFrame(avg20), pd.DataFrame(avg60), pd.DataFrame(avg90), pd.DataFrame(avg120), pd.DataFrame(avg240), pd.DataFrame(avg360), pd.DataFrame(avg480), pd.DataFrame(avg720), pd.DataFrame(avg1440), pd.DataFrame(avg2880),
disparity_avg5_df, disparity_avg20_df, disparity_avg60_df, disparity_avg120_df, disparity_avg240_df, disparity_avg480_df, disparity_avg1440_df, disparity_480_loc_df, disparity_1440_loc_df,
pd.DataFrame(disparity_diff_20_5), pd.DataFrame(disparity_diff_20_5_rate),
pd.DataFrame(disparity_diff_60_20), pd.DataFrame(disparity_diff_60_20_rate),
pd.DataFrame(disparity_diff_120_20), pd.DataFrame(disparity_diff_120_20_rate),
pd.DataFrame(disparity_diff_240_20), pd.DataFrame(disparity_diff_240_20_rate),
pd.DataFrame(disparity_diff_480_20), pd.DataFrame(disparity_diff_480_20_rate),
pd.DataFrame(disparity_diff_1440_20), pd.DataFrame(disparity_diff_1440_20_rate),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20),
bb_width_df, bb_pb_df,
pd.DataFrame(new_high_7), pd.DataFrame(new_high_9), pd.DataFrame(new_high_26), pd.DataFrame(new_high_33), pd.DataFrame(new_high_52),
pd.DataFrame(new_low_7), pd.DataFrame(new_low_9), pd.DataFrame(new_low_26), pd.DataFrame(new_low_33), pd.DataFrame(new_low_52),
pd.DataFrame(slowk_5_df), pd.DataFrame(slowd_5_df),
pd.DataFrame(slowk_10_df), pd.DataFrame(slowd_10_df),
pd.DataFrame(slowk_20_df), pd.DataFrame(slowd_20_df),
pd.DataFrame(slowk_60_df), pd.DataFrame(slowd_60_df),
pd.DataFrame(slowk_120_df), pd.DataFrame(slowd_120_df),
pd.DataFrame(slowk_240_df), pd.DataFrame(slowd_240_df),
pd.DataFrame(slowk_480_df), pd.DataFrame(slowd_480_df),
pd.DataFrame(min_price_list), pd.DataFrame(max_price_list),
pd.DataFrame(poly_5), pd.DataFrame(poly_10), pd.DataFrame(poly_20), pd.DataFrame(poly_60), pd.DataFrame(poly_120), pd.DataFrame(poly_240), pd.DataFrame(poly_480)
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'changeLine', 'baseLine', 'laggingSpan', 'leadingSpan1', 'leadingSpan2',
'laggingSpan_close_diff',
'laggingSpan_changeLine_diff',
'laggingSpan_baseLine_diff',
'laggingSpan_leadingSpan1_diff',
'laggingSpan_leadingSpan2_diff',
'laggingSpan_avg60_diff',
'laggingSpan_lower20_diff',
'laggingSpan_middle20_diff',
'laggingSpan_upper20_diff',
'baseLine_close_diff',
'changeLine_close_diff',
'changeLine_baseLine_diff',
'changeLine_leadingSpan1_diff',
'leadingSpan1_leadingSpan2_diff',
'laggingSpan_close_diff_rate',
'laggingSpan_changeLine_diff_rate',
'laggingSpan_baseLine_diff_rate',
'laggingSpan_leadingSpan1_diff_rate',
'laggingSpan_leadingSpan2_diff_rate',
'laggingSpan_avg60_diff_rate',
'laggingSpan_lower20_diff_rate',
'laggingSpan_middle20_diff_rate',
'laggingSpan_upper20_diff_rate',
'baseLine_close_diff_rate',
'changeLine_close_diff_rate',
'changeLine_baseLine_diff_rate',
'changeLine_leadingSpan1_diff_rate',
'leadingSpan1_leadingSpan2_diff_rate',
'loc_240_k', 'loc_240_d', 'loc_240_s',
'avg5', 'avg10', 'avg20', 'avg60', 'avg90', 'avg120', 'avg240', 'avg360', 'avg480', 'avg720', 'avg1440', 'avg2880',
'disparity_avg5', 'disparity_avg20', 'disparity_avg60', 'disparity_avg120', 'disparity_avg240', 'disparity_avg480', 'disparity_avg1440', 'disparity_480_loc', 'disparity_1440_loc',
'disparity_diff_20_5', 'disparity_diff_20_5_rate',
'disparity_diff_60_20', 'disparity_diff_60_20_rate',
'disparity_diff_120_20', 'disparity_diff_120_20_rate',
'disparity_diff_240_20', 'disparity_diff_240_20_rate',
'disparity_diff_480_20', 'disparity_diff_480_20_rate',
'disparity_diff_1440_20', 'disparity_diff_1440_20_rate',
'upper_20', 'lower_20', 'middle_20',
'bb_width', 'bb_pb',
'new_high_7', 'new_high_9', 'new_high_26', 'new_high_33', 'new_high_52',
'new_low_7', 'new_low_9', 'new_low_26', 'new_low_33', 'new_low_52',
'slowk_5', 'slowd_5',
'slowk_10', 'slowd_10',
'slowk_20', 'slowd_20',
'slowk_60', 'slowd_60',
'slowk_120', 'slowd_120',
'slowk_240', 'slowd_240',
'slowk_480', 'slowd_480',
'min_price', 'max_price',
'poly_5', 'poly_10', 'poly_20', 'poly_60', 'poly_120', 'poly_240', 'poly_480'
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
return data, current_index
def getData(self, ticker, mins=None, ymd=None, get_days=14):
if ymd is None:
result = self.getCoinData(ticker, mins=mins, get_days=get_days)
else:
result = self.getCoinData(ticker, mins=mins, ymd=ymd, get_days=get_days)
if len(result['ymd']) < 1:
return None, None
#result_tic = self.makeTickData(result_m1, mins=minute)
data_scale, ci = self.analyze_scale(result)
data, ci = self.analyze_raw(result)
return data, data_scale, ci

641
JSDPattern_minutely.py Normal file
View File

@@ -0,0 +1,641 @@
# 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 numpy as np
np.seterr(divide='ignore', invalid='ignore')
from scipy.signal import argrelextrema
# 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 sklearn.preprocessing import MinMaxScaler
from JSDPattern import JSDPattern
class JSDPattern_minutely (JSDPattern):
scaler = None
def __init__(self, RESOURCE_PATH=None):
super().__init__(RESOURCE_PATH)
self.scaler = MinMaxScaler()
return
def get_Support_Resistance(self, df):
n = 10
support_df = df.iloc[argrelextrema(df.values, np.less_equal, order=n)[0]]
resistance_df = df.iloc[argrelextrema(df.values, np.greater_equal, order=n)[0]]
support, resistance = np.zeros(len(df)), np.zeros(len(df))
support[0], resistance[0] = df[0].iloc[0], df[0].iloc[0]
s_i, r_i = 0, 0
for i in range(1, len(df)):
if s_i < len(support_df) and df.index[i] == support_df.index[s_i]:
support[i] = support_df[0].iloc[s_i]
s_i += 1
else:
support[i] = support[i-1]
if r_i < len(resistance_df) and df.index[i] == resistance_df.index[r_i]:
resistance[i] = resistance_df[0].iloc[r_i]
r_i += 1
else:
resistance[i] = resistance[i-1]
return support, resistance
def analyze_raw(self, result):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
volume_rate = np.zeros(len(close))
head_rate, body_rate, tail_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
open_low_rate, open_high_rate, open_open_rate, open_close_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
close_low_rate, close_high_rate, close_open_rate, close_close_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
for i in range(len(close)):
length = high[i] - low[i]
if 0 < length:
max_value = max(open[i], close[i])
min_value = min(open[i], close[i])
head_rate[i] = (high[i] - max_value) / length
body_rate[i] = (max_value - min_value) / length
tail_rate[i] = (min_value - low[i]) / length
if 0 < i:
if 0 < volume[i-1]:
volume_rate[i] = volume[i]/volume[i-1]
open_low_rate[i] = (low[i] - open[i-1])/open[i-1]
open_high_rate[i] = (high[i] - open[i-1])/open[i-1]
open_open_rate[i] = (open[i] - open[i-1])/open[i-1]
open_close_rate[i] = (close[i] - open[i-1])/open[i-1]
close_low_rate[i] = (low[i] - close[i-1])/close[i-1]
close_high_rate[i] = (high[i] - close[i-1])/close[i-1]
close_open_rate[i] = (open[i] - close[i-1])/close[i-1]
close_close_rate[i] = (close[i] - close[i-1])/close[i-1]
support, resistance = self.get_Support_Resistance(pd.DataFrame(close))
#z = np.polyfit(df['speed'], df['dist'], 1) # 기울기와 절편 확인
#f = np.poly1d(z) # f(x): f함수
if 5 < len(close):
poly_5 = [0] * 4 + [np.polyfit(range(5), close[i - 4: i + 1], 1)[0] for i in range(4, len(close))]
else:
poly_5 = [0] * len(close)
if 10 < len(close):
poly_10 = [0] * 9 + [np.polyfit(range(10), close[i - 9: i + 1], 1)[0] for i in range(9, len(close))]
else:
poly_10 = [0] * len(close)
if 20 < len(close):
poly_20 = [0] * 19 + [np.polyfit(range(20), close[i - 19: i + 1], 1)[0] for i in range(19, len(close))]
else:
poly_20 = [0] * len(close)
if 60 < len(close):
poly_60 = [0] * 59 + [np.polyfit(range(60), close[i - 59: i + 1], 1)[0] for i in range(59, len(close))]
else:
poly_60 = [0] * len(close)
if 120 < len(close):
poly_120 = [0] * 119 + [np.polyfit(range(120), close[i - 119: i + 1], 1)[0] for i in range(119, len(close))]
else:
poly_120 = [0] * len(close)
if 240 < len(close):
poly_240 = [0] * 239 + [np.polyfit(range(240), close[i - 239: i + 1], 1)[0] for i in range(239, len(close))]
else:
poly_240 = [0] * len(close)
if 480 < len(close):
poly_480 = [0] * 479 + [np.polyfit(range(480), close[i - 479: i + 1], 1)[0] for i in range(479, len(close))]
else:
poly_480 = [0] * len(close)
if 720 < len(close):
poly_720 = [0] * 719 + [np.polyfit(range(720), close[i - 719: i + 1], 1)[0] for i in range(719, len(close))]
else:
poly_720 = [0] * len(close)
if 1440 < len(close):
poly_1440 = [0] * 1439 + [np.polyfit(range(1440), close[i - 1439: i + 1], 1)[0] for i in range(1439, len(close))]
else:
poly_1440 = [0] * len(close)
# 7일 신고가
new_high_7 = [0 for c in range(6)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 6:c + 1] and max(close[c - 6:c]) < close[c] else 0 for c in range(6, len(close))]
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 8:c + 1] and max(close[c - 8:c]) < close[c] else 0 for c in range(8, len(close))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 25:c + 1] and max(close[c - 25:c]) < close[c] else 0 for c in range(25, len(close))]
# 7일 신저가
new_low_7 = [0 for c in range(6)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 6:c + 1] and close[c - 6] < min(close[c - 6:c + 1]) else 0 for c in range(6, len(close))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 8:c + 1] and close[c - 8] < min(close[c - 8:c + 1]) else 0 for c in range(8, len(close))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (close[c - 1] is not None and close[c] is not None and close[c - 1] < close[c]) and None not in close[c - 25:c + 1] and close[c - 25] < min(close[c - 25:c + 1]) else 0 for c in range(25, len(close))]
high_th = [0]
for i in range(1, len(close)):
count = 0
for c in range(i - 1, i - 30, -1):
if c < 0:
break
if close[i] < close[c]:
break
else:
count += 1
high_th.append(count)
# 이동 평균
close_df = pd.DataFrame(close)
avg5_df = close_df.ewm(5).mean()
avg10_df = close_df.ewm(10).mean()
avg20_df = close_df.ewm(20).mean()
avg60_df = close_df.ewm(60).mean()
avg120_df = close_df.ewm(120).mean()
avg240_df = close_df.ewm(240).mean()
avg480_df = close_df.ewm(480).mean()
avg720_df = close_df.ewm(720).mean()
avg1440_df = close_df.ewm(1440).mean()
# 이격도
disparity_avg5_df = (close_df / close_df.ewm(span=5, min_periods=5, adjust=False).mean())
disparity_avg5_df = disparity_avg5_df.replace({None: np.nan})
disparity_avg20_df = (close_df / close_df.ewm(span=20, min_periods=20, adjust=False).mean())
disparity_avg20_df = disparity_avg20_df.replace({None: np.nan})
disparity_avg60_df = (close_df / close_df.ewm(span=60, min_periods=60, adjust=False).mean())
disparity_avg60_df = disparity_avg60_df.replace({None: np.nan})
disparity_avg120_df = (close_df / close_df.ewm(span=120, min_periods=120, adjust=False).mean())
disparity_avg120_df = disparity_avg120_df.replace({None: np.nan})
disparity_avg240_df = (close_df / close_df.ewm(span=240, min_periods=240, adjust=False).mean())
disparity_avg240_df = disparity_avg240_df.replace({None: np.nan})
disparity_avg480_df = (close_df / close_df.ewm(span=480, min_periods=480, adjust=False).mean())
disparity_avg480_df = disparity_avg480_df.replace({None: np.nan})
disparity_avg720_df = (close_df / close_df.ewm(span=720, min_periods=720, adjust=False).mean())
disparity_avg720_df = disparity_avg720_df.replace({None: np.nan})
disparity_avg1440_df = (close_df / close_df.ewm(span=1440, min_periods=1440, adjust=False).mean())
disparity_avg1440_df = disparity_avg1440_df.replace({None: np.nan})
disparity_avg2880_df = (close_df / close_df.ewm(span=2880, min_periods=2880, adjust=False).mean())
disparity_avg2880_df = disparity_avg2880_df.replace({None: np.nan})
""""""
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
width_df = (upper_20 - lower_20) / middle_20
width_min = np.min(width_df[0])
width_max = np.max(width_df[0])
bb_width_df = 100 * (width_df - width_min) / (width_max - width_min)
bb_pb_df = 100 * (close_df - lower_20) / (upper_20 - lower_20)
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
np_high, np_low, np_close = np.array(high, dtype=np.float64), np.array(low, dtype=np.float64), np.array(close, dtype=np.float64)
slowk_5_df, slowd_5_df = talib.STOCH(np_high, np_low, np_close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
slowk_10_df, slowd_10_df = talib.STOCH(np_high, np_low, np_close, fastk_period=10, slowk_period=6, slowk_matype=0, slowd_period=6, slowd_matype=0)
slowk_20_df, slowd_20_df = talib.STOCH(np_high, np_low, np_close, fastk_period=20, slowk_period=12, slowk_matype=0, slowd_period=12, slowd_matype=0)
slowk_60_df, slowd_60_df = talib.STOCH(np_high, np_low, np_close, fastk_period=60, slowk_period=37, slowk_matype=0, slowd_period=37, slowd_matype=0)
slowk_120_df, slowd_120_df = talib.STOCH(np_high, np_low, np_close, fastk_period=120, slowk_period=74, slowk_matype=0, slowd_period=74, slowd_matype=0)
slowk_240_df, slowd_240_df = talib.STOCH(np_high, np_low, np_close, fastk_period=240, slowk_period=148, slowk_matype=0, slowd_period=148, slowd_matype=0)
slowk_480_df, slowd_480_df = talib.STOCH(np_high, np_low, np_close, fastk_period=480, slowk_period=296, slowk_matype=0, slowd_period=296, slowd_matype=0)
slowk_720_df, slowd_720_df = talib.STOCH(np_high, np_low, np_close, fastk_period=720, slowk_period=445, slowk_matype=0, slowd_period=445, slowd_matype=0)
slowk_1440_df, slowd_1440_df = talib.STOCH(np_high, np_low, np_close, fastk_period=1440, slowk_period=890, slowk_matype=0, slowd_period=890, slowd_matype=0)
willr = talib.WILLR(np_high, np_low, np_close, timeperiod=11) + 100
rsi = talib.RSI(np_close, timeperiod=9)
rsi_720 = talib.RSI(np_close, timeperiod=720)
rsi_1440 = talib.RSI(np_close, timeperiod=1440)
macd, macds, macdo = talib.MACD(np_close, fastperiod=24, slowperiod=52, signalperiod=18)
macd_720, macds_720, macdo_720 = talib.MACD(np_close, fastperiod=332, slowperiod=720, signalperiod=250)
macd_1440, macds_1440, macdo_1440 = talib.MACD(np_close, fastperiod=665, slowperiod=1440, signalperiod=498)
"""
"""
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
pd.DataFrame(volume_rate), pd.DataFrame(head_rate), pd.DataFrame(body_rate), pd.DataFrame(tail_rate),
pd.DataFrame(open_low_rate), pd.DataFrame(open_high_rate), pd.DataFrame(open_open_rate), pd.DataFrame(open_close_rate), pd.DataFrame(close_low_rate), pd.DataFrame(close_high_rate), pd.DataFrame(close_open_rate), pd.DataFrame(close_close_rate),
pd.DataFrame(list(support)), pd.DataFrame(list(resistance)),
pd.DataFrame(poly_5), pd.DataFrame(poly_10), pd.DataFrame(poly_20), pd.DataFrame(poly_60), pd.DataFrame(poly_120), pd.DataFrame(poly_240), pd.DataFrame(poly_480), pd.DataFrame(poly_720), pd.DataFrame(poly_1440),
avg5_df, avg10_df, avg20_df, avg60_df, avg120_df, avg240_df, avg480_df, avg720_df, avg1440_df,
disparity_avg5_df, disparity_avg20_df, disparity_avg60_df, disparity_avg120_df, disparity_avg240_df, disparity_avg480_df, disparity_avg720_df, disparity_avg1440_df, disparity_avg2880_df,
pd.DataFrame(new_high_7), pd.DataFrame(new_high_9), pd.DataFrame(new_high_26), pd.DataFrame(new_low_7), pd.DataFrame(new_low_9), pd.DataFrame(new_low_26), pd.DataFrame(high_th),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20), bb_width_df, bb_pb_df, pd.DataFrame(willr),
pd.DataFrame(slowk_5_df), pd.DataFrame(slowd_5_df),
pd.DataFrame(slowk_10_df), pd.DataFrame(slowd_10_df),
pd.DataFrame(slowk_20_df), pd.DataFrame(slowd_20_df),
pd.DataFrame(slowk_60_df), pd.DataFrame(slowd_60_df),
pd.DataFrame(slowk_120_df), pd.DataFrame(slowd_120_df),
pd.DataFrame(slowk_240_df), pd.DataFrame(slowd_240_df),
pd.DataFrame(slowk_480_df), pd.DataFrame(slowd_480_df),
pd.DataFrame(slowk_720_df), pd.DataFrame(slowd_720_df),
pd.DataFrame(slowk_1440_df), pd.DataFrame(slowd_1440_df),
pd.DataFrame(rsi), pd.DataFrame(rsi_720), pd.DataFrame(rsi_1440),
pd.DataFrame(macd), pd.DataFrame(macds), pd.DataFrame(macdo),
pd.DataFrame(macd_720), pd.DataFrame(macds_720), pd.DataFrame(macdo_720),
pd.DataFrame(macd_1440), pd.DataFrame(macds_1440), pd.DataFrame(macdo_1440),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'volume_rate', 'head_rate', 'body_rate', 'tail_rate',
'open_low_rate', 'open_high_rate', 'open_open_rate', 'open_close_rate', 'close_low_rate', 'close_high_rate', 'close_open_rate', 'close_close_rate',
'support', 'resistance',
'poly_5', 'poly_10', 'poly_20', 'poly_60', 'poly_120', 'poly_240', 'poly_480', 'poly_720', 'poly_1440',
'avg5', 'avg10', 'avg20', 'avg60', 'avg120', 'avg240', 'avg480', 'avg720', 'avg1440',
'disparity_avg5', 'disparity_avg20', 'disparity_avg60', 'disparity_avg120', 'disparity_avg240', 'disparity_avg480', 'disparity_avg720', 'disparity_avg1440', 'disparity_avg2880',
'new_high_7', 'new_high_9', 'new_high_26', 'new_low_7', 'new_low_9', 'new_low_26', 'high_th',
'upper_20', 'lower_20', 'middle_20', 'bb_width', 'bb_pb', 'willr',
'slowk_5', 'slowd_5',
'slowk_10', 'slowd_10',
'slowk_20', 'slowd_20',
'slowk_60', 'slowd_60',
'slowk_120', 'slowd_120',
'slowk_240', 'slowd_240',
'slowk_480', 'slowd_480',
'slowk_720', 'slowd_720',
'slowk_1440', 'slowd_1440',
'rsi', 'rsi_720', 'rsi_1440',
'macd', 'macds', 'macdo',
'macd_720', 'macds_720', 'macdo_720',
'macd_1440', 'macds_1440', 'macdo_1440',
'open_raw', 'close_raw', 'high_raw', 'low_raw', 'volume_raw'
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
#data = data.dropna(axis=0)
return data, len(data)
def analyze_scale(self, result):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
open_scaled = (self.scaler.fit_transform(pd.DataFrame(open))).reshape(1,-1)[0]
open_scaled = [0.0000000001 if c==0 else c for c in open_scaled]
close_scaled = (self.scaler.fit_transform(pd.DataFrame(close))).reshape(1,-1)[0]
close_scaled = [0.0000000001 if c == 0 else c for c in close_scaled]
high_scaled = (self.scaler.fit_transform(pd.DataFrame(high))).reshape(1,-1)[0]
high_scaled = [0.0000000001 if c == 0 else c for c in high_scaled]
low_scaled = (self.scaler.fit_transform(pd.DataFrame(low))).reshape(1,-1)[0]
low_scaled = [0.0000000001 if c == 0 else c for c in low_scaled]
volume_scaled = (self.scaler.fit_transform(pd.DataFrame(volume))).reshape(1, -1)[0]
volume_scaled = [0.0000000001 if c == 0 else c for c in volume_scaled]
volume_rate = np.zeros(len(close))
head_rate, body_rate, tail_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
open_low_rate, open_high_rate, open_open_rate, open_close_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
close_low_rate, close_high_rate, close_open_rate, close_close_rate = np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close)), np.zeros(len(close))
for i in range(len(close)):
length = high_scaled[i] - low_scaled[i]
if 0 < length:
max_value = max(open_scaled[i], close_scaled[i])
min_value = min(open_scaled[i], close_scaled[i])
head_rate[i] = (high_scaled[i] - max_value) / length
body_rate[i] = (max_value - min_value) / length
tail_rate[i] = (min_value - low_scaled[i]) / length
if 0 < i:
if 0 < volume[i-1]:
volume_rate[i] = volume_scaled[i]/volume_scaled[i-1]
open_low_rate[i] = (low_scaled[i] - open_scaled[i-1])/open_scaled[i-1]
open_high_rate[i] = (high_scaled[i] - open_scaled[i-1])/open_scaled[i-1]
open_open_rate[i] = (open_scaled[i] - open_scaled[i-1])/open_scaled[i-1]
open_close_rate[i] = (close_scaled[i] - open_scaled[i-1])/open_scaled[i-1]
close_low_rate[i] = (low_scaled[i] - close_scaled[i-1])/close_scaled[i-1]
close_high_rate[i] = (high_scaled[i] - close_scaled[i-1])/close_scaled[i-1]
close_open_rate[i] = (open_scaled[i] - close_scaled[i-1])/close_scaled[i-1]
close_close_rate[i] = (close_scaled[i] - close_scaled[i-1])/close_scaled[i-1]
support, resistance = self.get_Support_Resistance(pd.DataFrame(close_scaled))
#z = np.polyfit(df['speed'], df['dist'], 1) # 기울기와 절편 확인
#f = np.poly1d(z) # f(x): f함수
if 5 < len(close):
poly_5 = [0] * 4 + [np.polyfit(range(5), close[i - 4: i + 1], 1)[0] for i in range(4, len(close))]
else:
poly_5 = [0] * len(close)
if 10 < len(close):
poly_10 = [0] * 9 + [np.polyfit(range(10), close[i - 9: i + 1], 1)[0] for i in range(9, len(close))]
else:
poly_10 = [0] * len(close)
if 20 < len(close):
poly_20 = [0] * 19 + [np.polyfit(range(20), close[i - 19: i + 1], 1)[0] for i in range(19, len(close))]
else:
poly_20 = [0] * len(close)
if 60 < len(close):
poly_60 = [0] * 59 + [np.polyfit(range(60), close[i - 59: i + 1], 1)[0] for i in range(59, len(close))]
else:
poly_60 = [0] * len(close)
if 120 < len(close):
poly_120 = [0] * 119 + [np.polyfit(range(120), close[i - 119: i + 1], 1)[0] for i in range(119, len(close))]
else:
poly_120 = [0] * len(close)
if 240 < len(close):
poly_240 = [0] * 239 + [np.polyfit(range(240), close[i - 239: i + 1], 1)[0] for i in range(239, len(close))]
else:
poly_240 = [0] * len(close)
if 480 < len(close):
poly_480 = [0] * 479 + [np.polyfit(range(480), close[i - 479: i + 1], 1)[0] for i in range(479, len(close))]
else:
poly_480 = [0] * len(close)
if 720 < len(close):
poly_720 = [0] * 719 + [np.polyfit(range(720), close[i - 719: i + 1], 1)[0] for i in range(719, len(close))]
else:
poly_720 = [0] * len(close)
if 1440 < len(close):
poly_1440 = [0] * 1439 + [np.polyfit(range(1440), close[i - 1439: i + 1], 1)[0] for i in range(1439, len(close))]
else:
poly_1440 = [0] * len(close)
# 7일 신고가
new_high_7 = [0 for c in range(6)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 6:c + 1] and max(close_scaled[c - 6:c]) < close_scaled[c] else 0 for c in range(6, len(close_scaled))]
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 8:c + 1] and max(close_scaled[c - 8:c]) < close_scaled[c] else 0 for c in range(8, len(close_scaled))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 25:c + 1] and max(close_scaled[c - 25:c]) < close_scaled[c] else 0 for c in range(25, len(close_scaled))]
# 7일 신저가
new_low_7 = [0 for c in range(6)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 6:c + 1] and close_scaled[c - 6] < min(close_scaled[c - 6:c + 1]) else 0 for c in range(6, len(close_scaled))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 8:c + 1] and close_scaled[c - 8] < min(close_scaled[c - 8:c + 1]) else 0 for c in range(8, len(close_scaled))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (close_scaled[c - 1] is not None and close_scaled[c] is not None and close_scaled[c - 1] < close_scaled[c]) and None not in close_scaled[c - 25:c + 1] and close_scaled[c - 25] < min(close_scaled[c - 25:c + 1]) else 0 for c in range(25, len(close_scaled))]
high_th = [0]
for i in range(1, len(close_scaled)):
count = 0
for c in range(i-1,i-30,-1):
if c < 0:
break
if close_scaled[i] < close_scaled[c]:
break
else:
count += 1
high_th.append(count)
# 이동 평균
close_df = pd.DataFrame(close_scaled)
avg5_df = close_df.ewm(5).mean()
avg10_df = close_df.ewm(10).mean()
avg20_df = close_df.ewm(20).mean()
avg60_df = close_df.ewm(60).mean()
avg120_df = close_df.ewm(120).mean()
avg240_df = close_df.ewm(240).mean()
avg480_df = close_df.ewm(480).mean()
avg720_df = close_df.ewm(720).mean()
avg1440_df = close_df.ewm(1440).mean()
# 이격도
disparity_avg5_df = (close_df / close_df.ewm(span=5, min_periods=5, adjust=False).mean())
disparity_avg5_df = disparity_avg5_df.replace({None: np.nan})
disparity_avg20_df = (close_df / close_df.ewm(span=20, min_periods=20, adjust=False).mean())
disparity_avg20_df = disparity_avg20_df.replace({None: np.nan})
disparity_avg60_df = (close_df / close_df.ewm(span=60, min_periods=60, adjust=False).mean())
disparity_avg60_df = disparity_avg60_df.replace({None: np.nan})
disparity_avg120_df = (close_df / close_df.ewm(span=120, min_periods=120, adjust=False).mean())
disparity_avg120_df = disparity_avg120_df.replace({None: np.nan})
disparity_avg240_df = (close_df / close_df.ewm(span=240, min_periods=240, adjust=False).mean())
disparity_avg240_df = disparity_avg240_df.replace({None: np.nan})
disparity_avg480_df = (close_df / close_df.ewm(span=480, min_periods=480, adjust=False).mean())
disparity_avg480_df = disparity_avg480_df.replace({None: np.nan})
disparity_avg720_df = (close_df / close_df.ewm(span=720, min_periods=720, adjust=False).mean())
disparity_avg720_df = disparity_avg720_df.replace({None: np.nan})
disparity_avg1440_df = (close_df / close_df.ewm(span=1440, min_periods=1440, adjust=False).mean())
disparity_avg1440_df = disparity_avg1440_df.replace({None: np.nan})
disparity_avg2880_df = (close_df / close_df.ewm(span=2880, min_periods=2880, adjust=False).mean())
disparity_avg2880_df = disparity_avg2880_df.replace({None: np.nan})
disparity_avg5_list = list(disparity_avg5_df.values.reshape(-1))
disparity_avg20_list = list(disparity_avg20_df.values.reshape(-1))
disparity_avg60_list = list(disparity_avg60_df.values.reshape(-1))
disparity_avg120_list = list(disparity_avg120_df.values.reshape(-1))
disparity_avg240_list = list(disparity_avg240_df.values.reshape(-1))
disparity_avg480_list = list(disparity_avg480_df.values.reshape(-1))
disparity_avg720_list = list(disparity_avg720_df.values.reshape(-1))
disparity_avg1440_list = list(disparity_avg1440_df.values.reshape(-1))
disparity_diff_20_5, disparity_diff_20_5_rate = self.getDiff_Rate(disparity_avg20_list, disparity_avg5_list, duration=20)
disparity_diff_60_20, disparity_diff_60_20_rate = self.getDiff_Rate(disparity_avg60_list, disparity_avg20_list, duration=60)
disparity_diff_120_20, disparity_diff_120_20_rate = self.getDiff_Rate(disparity_avg120_list, disparity_avg20_list, duration=120)
disparity_diff_240_20, disparity_diff_240_20_rate = self.getDiff_Rate(disparity_avg240_list, disparity_avg20_list, duration=240)
disparity_diff_480_20, disparity_diff_480_20_rate = self.getDiff_Rate(disparity_avg480_list, disparity_avg20_list, duration=480)
disparity_diff_720_20, disparity_diff_720_20_rate = self.getDiff_Rate(disparity_avg720_list, disparity_avg20_list, duration=720)
disparity_diff_1440_20, disparity_diff_1440_20_rate = self.getDiff_Rate(disparity_avg1440_list, disparity_avg20_list, duration=1440)
""""""
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
width_df = (upper_20 - lower_20) / middle_20
width_min = np.min(width_df[0])
width_max = np.max(width_df[0])
bb_width_df = 100 * (width_df - width_min) / (width_max - width_min)
bb_pb_df = 100 * (close_df - lower_20) / (upper_20 - lower_20)
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
np_high, np_low, np_close = np.array(high_scaled, dtype=np.float64), np.array(low_scaled, dtype=np.float64), np.array(close_scaled, dtype=np.float64)
slowk_5_df, slowd_5_df = talib.STOCH(np_high, np_low, np_close, fastk_period=5, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0)
slowk_10_df, slowd_10_df = talib.STOCH(np_high, np_low, np_close, fastk_period=10, slowk_period=6, slowk_matype=0, slowd_period=6, slowd_matype=0)
slowk_20_df, slowd_20_df = talib.STOCH(np_high, np_low, np_close, fastk_period=20, slowk_period=12, slowk_matype=0, slowd_period=12, slowd_matype=0)
slowk_60_df, slowd_60_df = talib.STOCH(np_high, np_low, np_close, fastk_period=60, slowk_period=37, slowk_matype=0, slowd_period=37, slowd_matype=0)
slowk_120_df, slowd_120_df = talib.STOCH(np_high, np_low, np_close, fastk_period=120, slowk_period=74, slowk_matype=0, slowd_period=74, slowd_matype=0)
slowk_240_df, slowd_240_df = talib.STOCH(np_high, np_low, np_close, fastk_period=240, slowk_period=148, slowk_matype=0, slowd_period=148, slowd_matype=0)
slowk_480_df, slowd_480_df = talib.STOCH(np_high, np_low, np_close, fastk_period=480, slowk_period=296, slowk_matype=0, slowd_period=296, slowd_matype=0)
slowk_720_df, slowd_720_df = talib.STOCH(np_high, np_low, np_close, fastk_period=720, slowk_period=445, slowk_matype=0, slowd_period=445, slowd_matype=0)
slowk_1440_df, slowd_1440_df = talib.STOCH(np_high, np_low, np_close, fastk_period=1440, slowk_period=890, slowk_matype=0, slowd_period=890, slowd_matype=0)
willr = talib.WILLR(np_high, np_low, np_close, timeperiod=11) + 100
rsi = talib.RSI(np_close, timeperiod=9)
rsi_720 = talib.RSI(np_close, timeperiod=720)
rsi_1440 = talib.RSI(np_close, timeperiod=1440)
macd, macds, macdo = talib.MACD(np_close, fastperiod=24, slowperiod=52, signalperiod=18)
macd_720, macds_720, macdo_720 = talib.MACD(np_close, fastperiod=332, slowperiod=720, signalperiod=250)
macd_1440, macds_1440, macdo_1440 = talib.MACD(np_close, fastperiod=665, slowperiod=1440, signalperiod=498)
"""
"""
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open_scaled), pd.DataFrame(close_scaled), pd.DataFrame(high_scaled), pd.DataFrame(low_scaled), pd.DataFrame(volume_scaled),
pd.DataFrame(volume_rate), pd.DataFrame(head_rate), pd.DataFrame(body_rate), pd.DataFrame(tail_rate),
pd.DataFrame(open_low_rate), pd.DataFrame(open_high_rate), pd.DataFrame(open_open_rate), pd.DataFrame(open_close_rate), pd.DataFrame(close_low_rate), pd.DataFrame(close_high_rate), pd.DataFrame(close_open_rate), pd.DataFrame(close_close_rate),
pd.DataFrame(list(support)), pd.DataFrame(list(resistance)),
pd.DataFrame(poly_5), pd.DataFrame(poly_10), pd.DataFrame(poly_20), pd.DataFrame(poly_60), pd.DataFrame(poly_120), pd.DataFrame(poly_240), pd.DataFrame(poly_480), pd.DataFrame(poly_720), pd.DataFrame(poly_1440),
avg5_df, avg10_df, avg20_df, avg60_df, avg120_df, avg240_df, avg480_df, avg720_df, avg1440_df,
disparity_avg5_df, disparity_avg20_df, disparity_avg60_df, disparity_avg120_df, disparity_avg240_df, disparity_avg480_df, disparity_avg720_df, disparity_avg1440_df, disparity_avg2880_df,
pd.DataFrame(disparity_diff_20_5), pd.DataFrame(disparity_diff_20_5_rate),
pd.DataFrame(disparity_diff_60_20), pd.DataFrame(disparity_diff_60_20_rate),
pd.DataFrame(disparity_diff_120_20), pd.DataFrame(disparity_diff_120_20_rate),
pd.DataFrame(disparity_diff_240_20), pd.DataFrame(disparity_diff_240_20_rate),
pd.DataFrame(disparity_diff_480_20), pd.DataFrame(disparity_diff_480_20_rate),
pd.DataFrame(disparity_diff_720_20), pd.DataFrame(disparity_diff_720_20_rate),
pd.DataFrame(disparity_diff_1440_20), pd.DataFrame(disparity_diff_1440_20_rate),
pd.DataFrame(new_high_7), pd.DataFrame(new_high_9), pd.DataFrame(new_high_26), pd.DataFrame(new_low_7), pd.DataFrame(new_low_9), pd.DataFrame(new_low_26), pd.DataFrame(high_th),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20), bb_width_df, bb_pb_df, pd.DataFrame(willr),
pd.DataFrame(slowk_5_df), pd.DataFrame(slowd_5_df),
pd.DataFrame(slowk_10_df), pd.DataFrame(slowd_10_df),
pd.DataFrame(slowk_20_df), pd.DataFrame(slowd_20_df),
pd.DataFrame(slowk_60_df), pd.DataFrame(slowd_60_df),
pd.DataFrame(slowk_120_df), pd.DataFrame(slowd_120_df),
pd.DataFrame(slowk_240_df), pd.DataFrame(slowd_240_df),
pd.DataFrame(slowk_480_df), pd.DataFrame(slowd_480_df),
pd.DataFrame(slowk_720_df), pd.DataFrame(slowd_720_df),
pd.DataFrame(slowk_1440_df), pd.DataFrame(slowd_1440_df),
pd.DataFrame(rsi), pd.DataFrame(rsi_720), pd.DataFrame(rsi_1440),
pd.DataFrame(macd), pd.DataFrame(macds), pd.DataFrame(macdo),
pd.DataFrame(macd_720), pd.DataFrame(macds_720), pd.DataFrame(macdo_720),
pd.DataFrame(macd_1440), pd.DataFrame(macds_1440), pd.DataFrame(macdo_1440),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume)
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'volume_rate', 'head_rate', 'body_rate', 'tail_rate',
'open_low_rate', 'open_high_rate', 'open_open_rate', 'open_close_rate', 'close_low_rate', 'close_high_rate', 'close_open_rate', 'close_close_rate',
'support', 'resistance',
'poly_5', 'poly_10', 'poly_20', 'poly_60', 'poly_120', 'poly_240', 'poly_480', 'poly_720', 'poly_1440',
'avg5', 'avg10', 'avg20', 'avg60', 'avg120', 'avg240', 'avg480', 'avg720', 'avg1440',
'disparity_avg5', 'disparity_avg20', 'disparity_avg60', 'disparity_avg120', 'disparity_avg240', 'disparity_avg480', 'disparity_avg720', 'disparity_avg1440', 'disparity_avg2880',
'disparity_diff_20_5', 'disparity_diff_20_5_rate',
'disparity_diff_60_20', 'disparity_diff_60_20_rate',
'disparity_diff_120_20', 'disparity_diff_120_20_rate',
'disparity_diff_240_20', 'disparity_diff_240_20_rate',
'disparity_diff_480_20', 'disparity_diff_480_20_rate',
'disparity_diff_720_20', 'disparity_diff_720_20_rate',
'disparity_diff_1440_20', 'disparity_diff_1440_20_rate',
'new_high_7', 'new_high_9', 'new_high_26', 'new_low_7', 'new_low_9', 'new_low_26', 'high_th',
'upper_20', 'lower_20', 'middle_20', 'bb_width', 'bb_pb', 'willr',
'slowk_5', 'slowd_5',
'slowk_10', 'slowd_10',
'slowk_20', 'slowd_20',
'slowk_60', 'slowd_60',
'slowk_120', 'slowd_120',
'slowk_240', 'slowd_240',
'slowk_480', 'slowd_480',
'slowk_720', 'slowd_720',
'slowk_1440', 'slowd_1440',
'rsi', 'rsi_720', 'rsi_1440',
'macd', 'macds', 'macdo',
'macd_720', 'macds_720', 'macdo_720',
'macd_1440', 'macds_1440', 'macdo_1440',
'open_raw', 'close_raw', 'high_raw', 'low_raw', 'volume_raw'
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
#data = data.dropna(axis=0)
return data, len(data)
def getData(self, ticker, mins=None, ymd=None, get_days=14):
if ymd is None:
result = self.getCoinData(ticker, mins=mins, get_days=get_days)
else:
result = self.getCoinData(ticker, mins=mins, ymd=ymd, get_days=get_days)
if len(result['ymd']) < 1:
return None, None, None
#result_tic = self.makeTickData(result_m1, mins=minute)
data_scale, ci = self.analyze_scale(result)
data, ci = self.analyze_raw(result)
ticker['disparity_low_min'] = self.getDisparity_low_min(ticker, min='minutely')
return data, data_scale, ci

View File

@@ -1,130 +0,0 @@
import os
import logging
logging.basicConfig(level=logging.INFO)
from stock.util.LabelChecker import LabelChecker
class LabelMaker:
db_filename = None
labelChecker = None
def __init__(self, RESOURCE_PATH):
self.labelChecker = LabelChecker(RESOURCE_PATH)
self.db_filename = os.path.join(RESOURCE_PATH, "hts.db")
return
def clearLabel(self, stock_code, ymd):
self.labelChecker.clearLabel(self.db_filename, stock_code, ymd)
return
def showLabels(self, stock_code, ymd):
self.labelChecker.showLabels(stock_code, ymd)
return
def update(self, stock_code, ymd, hms, label):
self.labelChecker.makeLabel(self.db_filename, stock_code, ymd, hms, label)
return
def write(self, stock_code, ymd, outFp):
logging.info(stock_code + " / " + ymd)
self.labelChecker.showLabels(stock_code, ymd, outFp)
return
def check(self, stock_codes):
# 종목에 대해서 주어진 일자에 대해서 통계치 추출하기
for stock_code in stock_codes:
ymds = self.labelChecker.getDate(stock_code)
for ymd in ymds:
logging.info(stock_code + " / " + ymd)
bsLine, data = self.labelChecker.makeCandidate(stock_code, ymd)
self.labelChecker.updateLabel(self.db_filename, stock_code, bsLine, data, ymd)
return
if __name__ == "__main__":
PROJECT_HOME = os.path.join(os.path.dirname(__file__))
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
labelMaker = LabelMaker(RESOURCE_PATH)
MODE = "WRITE"
if MODE == "UPDATE":
# 매일 입력하면서 정답 셋 만들기
stock_code = "252670"
ymd = '20220531'
labelMaker.clearLabel(stock_code, ymd)
labelMaker.update(stock_code, ymd, "0901", 2)
labelMaker.update(stock_code, ymd, "0902", 2)
labelMaker.update(stock_code, ymd, "0903", 2)
labelMaker.update(stock_code, ymd, "1429", 2)
labelMaker.update(stock_code, ymd, "1430", 2)
labelMaker.update(stock_code, ymd, "1431", 2)
labelMaker.update(stock_code, ymd, "1432", 2)
labelMaker.update(stock_code, ymd, "1433", 2)
labelMaker.update(stock_code, ymd, "1434", 2)
labelMaker.update(stock_code, ymd, "1435", 2)
labelMaker.update(stock_code, ymd, "1436", 2)
labelMaker.update(stock_code, ymd, "1437", 2)
labelMaker.update(stock_code, ymd, "1438", 2)
labelMaker.update(stock_code, ymd, "1439", 2)
labelMaker.update(stock_code, ymd, "1440", 2)
labelMaker.update(stock_code, ymd, "1441", 2)
labelMaker.update(stock_code, ymd, "1442", 2)
labelMaker.update(stock_code, ymd, "1443", 2)
labelMaker.update(stock_code, ymd, "1444", 2)
labelMaker.update(stock_code, ymd, "1445", 2)
labelMaker.update(stock_code, ymd, "1446", 2)
labelMaker.update(stock_code, ymd, "1447", 2)
labelMaker.update(stock_code, ymd, "0930", 1)
labelMaker.update(stock_code, ymd, "0931", 1)
labelMaker.update(stock_code, ymd, "0932", 1)
labelMaker.update(stock_code, ymd, "0933", 1)
labelMaker.update(stock_code, ymd, "0934", 1)
labelMaker.update(stock_code, ymd, "0935", 1)
labelMaker.update(stock_code, ymd, "1516", 1)
labelMaker.update(stock_code, ymd, "1517", 1)
labelMaker.update(stock_code, ymd, "1518", 1)
labelMaker.update(stock_code, ymd, "1519", 1)
labelMaker.showLabels(stock_code, ymd)
else:
stock_codes = {
"252670": [
'20220502', '20220503', '20220504', '20220506', '20220509',
'20220510', '20220511', '20220512', '20220513', '20220516',
'20220517', '20220518', '20220519', '20220520', '20220523',
'20220524', '20220525', '20220526', '20220527', '20220530',
'20220531', '20220602', '20220603', '20220607', '20220608',
'20220609', '20220610', '20220613', '20220614', '20220615',
'20220616', '20220617', '20220620', '20220621', '20220622',
'20220623', '20220624', '20220627', '20220628', '20220629',
'20220630', '20220624', '20220627', '20220628', '20220629',
'20220701', '20220704', '20220705', '20220706', '20220707',
'20220708', '20220711', '20220712', '20220713', '20220714',
'20220715', '20220718', '20220719', '20220720', '20220721',
'20220722', '20220725', '20220726', '20220727', '20220728',
'20220729', '20220801', '20220802', '20220803', '20220804',
'20220805', '20220808', '20220809', '20220810', '20220811',
'20220812', '20220816', '20220817', '20220818', '20220819'],
"122630": ['20220701', '20220704', '20220705', '20220706', '20220707',
'20220708', '20220711', '20220712', '20220713', '20220714',
'20220715', '20220718', '20220719', '20220720', '20220721',
'20220722', '20220725', '20220726', '20220727', '20220728',
'20220729', '20220801', '20220802', '20220803', '20220804',
'20220805', '20220808', '20220809', '20220810', '20220811',
'20220812', '20220816', '20220817'],
}
if MODE == "WRITE":
for stock_code in stock_codes:
fileName = os.path.join(RESOURCE_PATH, "tmp", "check_"+stock_code+".txt")
outFp = open(fileName, "w")
for ymd in stock_codes[stock_code]:
labelMaker.write(stock_code, ymd, outFp)
outFp.close()
else:
labelMaker.check(stock_codes)

View File

@@ -1,273 +0,0 @@
from math import nan
import pandas as pd
import plotly.graph_objects as go
from plotly import subplots
import os
import sqlite3
from hts.HTS import HTS
from stock.util.Stock2Vector import Stock2Vector
from stock.util.LabelChecker import LabelChecker
from hts.BuySellChecker import BuySellChecker
class Simulation (HTS):
stock2Vector = None
buySellChecker = None
def __init__(self, RESOURCE_PATH):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.buySellChecker = BuySellChecker()
try:
self.stock2Vector = Stock2Vector(RESOURCE_PATH)
self.labelChecker = LabelChecker(RESOURCE_PATH)
except:
pass
#self.connect()
return
def draw(self, stock_code, given_day, data, bsLine):
if bsLine is None:
return
# 어제 데이터는 지운다.
data = data.loc[pd.DatetimeIndex(data.index).day == int(given_day[6:])]
buy_line = bsLine['buy'][len(bsLine['buy'])-len(data):]
buy_weight_line = bsLine['buy_weight'][len(bsLine['buy'])-len(data):]
sell_line = bsLine['sell'][len(bsLine['buy'])-len(data):]
# 그래프 설정을 위한 변수를 생성한다.
data = data.astype({'open': 'int', 'high': 'int', 'low': 'int', 'close': 'int', 'volume': 'int',
'avg5': 'float', 'avg20': 'float', 'avg60': 'float', 'avg120': 'float', 'avg200': 'float',
'disparity_avg5': 'float', 'disparity_avg20': 'float', 'disparity_avg60': 'float', 'disparity_avg120': 'float', 'disparity_avg200': 'float',
'fast_k': 'float', 'slow_k': 'float', 'slow_d': 'float',
'macd': 'float', 'macds': 'float', 'macdo': 'float',
'rsi': 'float', 'rsis': 'float'
})
buy_size = []
buy_colors = []
for i in range(len(buy_line)):
if buy_line[i] < 0:
buy_colors.append("#ffffff")
buy_line[i] = nan
buy_size.append(0)
else:
buy_colors.append("#0C752E")
buy_size.append(10 + (5 * buy_weight_line[i]))
sell_colors = []
for i in range(len(sell_line)):
if sell_line[i] < 0:
sell_colors.append("#ffffff")
sell_line[i] = nan
else:
sell_colors.append("#00ced1")
volume_colors = []
for i in range(len(buy_line)):
if data['open'][i] > data['close'][i]:
volume_colors.append("#0000FF")
elif data['open'][i] < data['close'][i]:
volume_colors.append("#FF0000")
else:
volume_colors.append("#000000")
# 그래프를 설정한다.
buy_check = go.Scatter(x=data['date'], y=buy_line, mode='markers', name="buy", marker=dict(size=buy_size, color=buy_colors, line_width=0))
sell_check = go.Scatter(x=data['date'], y=sell_line, mode='markers', name="sell", marker=dict(size=14, color=sell_colors, line_width=0))
#volume_line = go.Scatter(x=data['date'], y=data["volume"], mode='lines', name='volume')
volume_line = go.Bar(x=data['date'], y=data["volume"], marker_color=volume_colors, name='volume')
disparity_avg5 = go.Scatter(x=data['date'], y=data["disparity_avg5"], name="disparity_avg5", line_color='#F81191')
disparity_avg20 = go.Scatter(x=data['date'], y=data["disparity_avg20"], name="disparity_avg20", line_color='#097F19')
disparity_avg30 = go.Scatter(x=data['date'], y=data["disparity_avg30"], name="disparity_avg30", line_color='#097F19')
disparity_avg60 = go.Scatter(x=data['date'], y=data["disparity_avg60"], name="disparity_avg60", line_color='#671BEA')
disparity_avg120 = go.Scatter(x=data['date'], y=data["disparity_avg120"], name="disparity_avg120", line_color='#DFB809')
disparity_avg200 = go.Scatter(x=data['date'], y=data["disparity_avg200"], name="disparity_avg200", line_color='#000000')
macd_line = go.Scatter(x=data['date'], y=data["macd"], line=dict(color='red', width=2), name='macd')
macd_s_line = go.Scatter(x=data['date'], y=data["macds"], line=dict(dash='dashdot', color='black', width=2), name='macds')
macd_o_line = go.Bar(x=data['date'], y=data["macdo"], marker_color='purple', name='macdo')
# fast_k_line = go.Scatter(x=hts['date'], y=hts["fast_k"], mode='lines', name='fast_k')
slow_k_line = go.Scatter(x=data['date'], y=data["slow_k"], line=dict(color='red', width=2), name='slow_k')
slow_d_line = go.Scatter(x=data['date'], y=data["slow_d"], line=dict(dash='dashdot', color='black', width=2), name='slow_d')
rsi_line = go.Scatter(x=data['date'], y=data["rsi"], line=dict(color='red', width=2), name='rsi')
rsis_line = go.Scatter(x=data['date'], y=data["rsis"], line=dict(dash='dashdot', color='black', width=2), name='rsis')
upper = go.Scatter(x=data['date'], y=data["upper"], name="upper", line_color='#000000')
lower = go.Scatter(x=data['date'], y=data["lower"], name="lower", line_color='#000000')
avg5 = go.Scatter(x=data['date'], y=data["avg5"], name="avg5", line_color='#F81191')
avg20 = go.Scatter(x=data['date'], y=data["avg20"], name="avg20", line_color='#097F19')
avg30 = go.Scatter(x=data['date'], y=data["avg30"], name="avg30", line_color='#097F19')
avg60 = go.Scatter(x=data['date'], y=data["avg60"], name="avg60", line_color='#671BEA')
avg120 = go.Scatter(x=data['date'], y=data["avg120"], name="avg120", line_color='#DFB809')
avg200 = go.Scatter(x=data['date'], y=data["avg200"], name="avg200", line_color='#000000')
changeLine = go.Scatter(x=data['date'], y=data["changeLine"], name='changeLine', line_color='#14A200') #CF6E0D
baseLine = go.Scatter(x=data['date'], y=data["baseLine"], name='baseLine', line_color='orange')
laggingSpan = go.Scatter(x=data['date'], y=data["laggingSpan"], name='laggingSpan', line_color='#B50ABB')
leadingSpan1 = go.Scatter(x=data['date'], y=data["leadingSpan1"], name='leadingSpan1', line_color='black')
leadingSpan2 = go.Scatter(x=data['date'], y=data["leadingSpan2"], name='leadingSpan2', line_color='black')
text_list = []
for i in range(len(data['macd'])):
text = "{}<br><br>open: {}<br>close: {}<br>high: {}<br>low: {}<br>volume: {}<br><br>avg5: {:.2f}<br>avg20: {:.2f}<br>avg60: {:.2f}<br>avg200: {:.2f}<br><br>d_avg5: {:.6f}<br>d_avg20: {:.6f}<br>d_avg60: {:.6f}<br>d_avg200: {:.6f}<br>d_avg5_60: {:.6f}<br>d_avg5_200: {:.6f}<br>d_avg200-5: {:.6f}<br><br>macd: {:.2f}<br>slow_k: {:.2f}<br>rsi: {:.2f}".format(
data['date'][i],
data['open'][i],data['close'][i],data['high'][i],data['low'][i],data['volume'][i],
data['avg5'][i],data['avg20'][i],data['avg60'][i],data['avg200'][i],
data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity_avg200'][i],
max(data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i]) - min(data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i]),
max(data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity_avg200'][i]) - min(data['disparity_avg5'][i], data['disparity_avg20'][i], data['disparity_avg60'][i], data['disparity_avg200'][i]),
abs(data['disparity_avg200'][i] - data['disparity_avg5'][i]),
data['macd'][i],data['slow_k'][i],data['rsi'][i]
)
text_list.append(text)
candle_stick = go.Candlestick(x=data['date'],
open=data['open'],
high=data['high'],
low=data['low'],
close=data['close'],
increasing_line_color='red',
decreasing_line_color='blue',
showlegend=False,
text=text_list,
hoverinfo="text"
)
# candle_data = [avg5, avg20, avg30, avg60, avg120, avg200, buy_check, sell_check, laggingSpan, changeLine, baseLine, upper, lower, candle_stick]
# candle_data = [avg5, avg20, avg30, avg60, avg200, buy_check, sell_check, upper, lower, candle_stick]
# candle_data = [buy_check, sell_check, changeLine, baseLine, changeLine, laggingSpan, candle_stick]
candle_data = [avg5, avg200, buy_check, sell_check, candle_stick]
volume_data = [volume_line]
disparity_data = [disparity_avg5, disparity_avg20, disparity_avg30, disparity_avg60, disparity_avg120, disparity_avg200]
macd_data = [macd_line, macd_s_line, macd_o_line]
stochastic_data = [slow_k_line, slow_d_line]
rsi_data = [rsi_line, rsis_line]
# 그래프를 그린다.
"""
fig = go.Figure(data=candle_data)
fig.update_layout(title=stock_code + "_" + given_day)
fig.show()
"""
fig = subplots.make_subplots(
rows=6, cols=1,
subplot_titles=("거래량", "이격도", "스토캐스틱", "RSI", "MACD", '캔들'),
#specs=[[{}], [{}], [{}], [{}], [{}], [{}]],
shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01,
row_heights=[200, 200, 200, 200, 200, 700]
)
for trace in volume_data:
fig.append_trace(trace, 1, 1)
for trace in disparity_data:
fig.append_trace(trace, 2, 1)
for trace in stochastic_data:
fig.append_trace(trace, 3, 1)
for trace in rsi_data:
fig.append_trace(trace, 4, 1)
for trace in macd_data:
fig.append_trace(trace, 5, 1)
for trace in candle_data:
fig.append_trace(trace, 6, 1)
#fig.update_xaxes(nticks=5)
#fig.update_layout(height=1800, title=stock_code + "_" + given_day, xaxis_rangeslider_visible=False)
df = pd.DataFrame(bsLine)
df = df.fillna(-1)
buy_count = len(df.loc[df["buy"] > 0])
sell_count = len(df.loc[df["sell"] > 0])
fig.update_layout(height=1700, title=stock_code + "_" + given_day + "_" + str(buy_count)+","+str(sell_count))
#fig.update_layout(title=stock_code + "_" + given_day + "_" + str(buy_count) + "," + str(sell_count))
fig.show()
return
def makeTickData(self, data, mins=30):
result = {"check": set(),
"time": [],
"open": [],
"close": [],
"high": [],
"low": [],
"vol": [],
"label": []}
for i in range(mins, len(data['time'])+1):
result["check"].add(data['time'][i-1])
result["time"].append(data['time'][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["vol"].append(sum(data['vol'][i - mins: i]))
return result
def simulate(self, stock, analyzed_day=1000):
stock_code = stock['code']
for ymd in stock['ymd']:
LAST_DATA = self.stock2Vector.getLastData(stock_code, ymd)
# 1분봉
result = self.stock2Vector.getRealTime(stock_code, ymd, LAST_DATA)
# 5분봉
#result = self.makeTickData(result, mins=5)
# 30분봉
#result = self.makeTickData(result, mins=30)
data = self.buySellChecker.analyze(result)
data.drop(data.index[:len(data) - analyzed_day], inplace=True)
# 이동평균, RSI, MACD, 일목균형, 볼린저밴드 상/하단을 계산한다.
#data_5 = self.buySellChecker.analyze(result_5)
# 분석일 데이터만 활용한다 (이전 데이터는 제거)
#data_5.drop(data_5.index[:len(data_5) - analyzed_day], inplace=True)
#data_30 = self.buySellChecker.analyze(result_30)
# 분석일 데이터만 활용한다 (이전 데이터는 제거)
#data_30.drop(data_30.index[:len(data_30) - analyzed_day], inplace=True)
# 사야 할 시점과 팔아야 할 시점을 체크한다.
#bsLine = self.buySellChecker.checkTransaction(stock_code, data, data_5, data_30, isRealTime=False)
# 어제 데이터는 지운다.
#data = data.loc[pd.DatetimeIndex(data.index).day == int(given_day[6:])]
bsLine = self.buySellChecker.checkTransaction(data, isRealTime=False)
# 그래프를 그린다.
self.draw(stock_code, ymd, data, bsLine)
return
if __name__ == "__main__":
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
#day_list = ['20231016', '20231017', '20231018', '20231019', '20231020', '20231023', '20231024', '20231025', '20231026', '20231027', '20231030', '20231031', '20231101', '20231102']
day_list = ['20231113']
stocks = [
{'code': '252670', 'name': 'KODEX 200선물인버스2X', 'ymd': day_list},
{'code': '122630', 'name': 'KODEX 레버리지', 'ymd': day_list},
{'code': '233740', 'name': 'KODEX 코스닥150레버리지', 'ymd': day_list},
{'code': '251340', 'name': 'KODEX 코스닥150선물인버스', 'ymd': day_list}
]
for stock in stocks:
simulation = Simulation(RESOURCE_PATH)
simulation.simulate(stock)
print ("done...")

View File

@@ -1,15 +1,10 @@
import os
import re
import sys
import shutil
import time
import sqlite3
from datetime import datetime
from dateutil.relativedelta import relativedelta
from stock.crawler.FnGuideCrawler import FnGuideCrawler
from stock.crawler.MetaCrawler import MetaCrawler
from stock.crawler.StockCrawler import StockCrawler
from stock.analysis.AnalyzerSqlite import AnalyzerSqlite
class StockCrawlerDaily:
@@ -113,27 +108,6 @@ class StockCrawlerDaily:
print("\n[US 종목 수집]")
stockCrawler.crawl_special_stocks(stockFileName)
analyzerSqlite = AnalyzerSqlite(RESOURCE_PATH)
print("\n[종목 결정]")
# HTML 출력
outPath = os.path.join(self.PROJECT_HOME, "resources", "analysis")
if not os.path.isdir(outPath):
os.mkdir(outPath)
day = datetime.today().strftime("%Y%m%d")
before_7_day = datetime.today() + relativedelta(days=-7)
dayList = os.listdir(outPath)
for dayDir in dayList:
if dayDir[0] != '.' and dayDir < before_7_day.strftime("%Y%m%d"):
if os.path.exists(os.path.join(outPath, dayDir)) and os.path.isdir(os.path.join(outPath, dayDir)):
shutil.rmtree(os.path.join(outPath, dayDir))
outPath = os.path.join(outPath, day)
if os.path.isdir(outPath):
shutil.rmtree(outPath)
os.mkdir(outPath)
analyzerSqlite.findCandidates(outPath)
return

View File

@@ -1,7 +0,0 @@
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}

View File

@@ -1,65 +0,0 @@
import os
import keras
import numpy as np
import tensorflow as tf
from stock.util.Stock2Vector import Stock2Vector
from classification_models.keras import Classifiers
class StockTrainer:
RESOURCE_PATH = None
stock2Vector = None
def __init__(self, RESOURCE_PATH):
self.RESOURCE_PATH = RESOURCE_PATH
self.stock2Vector = Stock2Vector(RESOURCE_PATH)
return
def train(self, stock_code):
#X, Y = self.stock2Vector.getDataset3D(stock_code)
X, Y = self.stock2Vector.getDataset2D(stock_code)
# build model
n_classes = 3
Inceptionresnetv2, preprocess_input = Classifiers.get('inceptionresnetv2')
X = preprocess_input(X)
# train
checkpoint_filename = os.path.join(self.RESOURCE_PATH, "model", "stock.ckpt")
base_model = Inceptionresnetv2(input_shape=(299, 299, 3), include_top=False)
x = tf.keras.layers.GlobalAveragePooling2D()(base_model.output)
output = tf.keras.layers.Dense(n_classes, activation='softmax')(x)
model = keras.models.Model(inputs=[base_model.input], outputs=[output])
model.compile(optimizer='SGD', loss='categorical_crossentropy', metrics=['accuracy'])
chekpoint = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_filename, save_weights_only=True, verbose=1)
earlystop = tf.keras.callbacks.EarlyStopping(monitor='loss', patience=5, mode="auto")
if os.path.isfile(checkpoint_filename):
model.load_weights(checkpoint_filename)
model.fit(x=X,
y=Y,
batch_size=10000,
epochs=10000,
callbacks=[chekpoint, earlystop])
return
if __name__ == "__main__":
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
stock_codes = {
# 252670
# 122630
"252670": ['20220729'],
}
for stock_code in stock_codes:
stockTrainer = StockTrainer(RESOURCE_PATH)
stockTrainer.train(stock_code)
print ("done...")

View File

@@ -1,240 +0,0 @@
# tensor - numpy - PILImage 변환 (https://qlsenddl-lab.tistory.com/37)
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'
import random
import numpy as np
import torch
from datasets import Dataset, load_metric, ClassLabel
from datasets import load_metric
from transformers import ViTConfig, TrainingArguments, Trainer, ViTForImageClassification
from torch.utils.data import DataLoader
import torchvision.transforms as transforms
from transformers import ViTFeatureExtractor
from torchvision.transforms import (CenterCrop, Compose, Normalize, RandomHorizontalFlip, RandomResizedCrop, Resize, ToTensor)
from stock.util.Stock2Vector import Stock2Vector
class VitTrainer:
RESOURCE_PATH = None
stock2Vector = None
num_labels = None
id2label = None
label2id = None
args = None
_train_transforms = None
_val_transforms = None
def __init__(self, RESOURCE_PATH):
self.set_seed(42)
self.RESOURCE_PATH = RESOURCE_PATH
self.stock2Vector = Stock2Vector(RESOURCE_PATH)
self.num_labels = 3
self.id2label = {0: 'none', 1: 'sell', 2: 'buy'}
self.label2id = {'none': 0, 'sell': 1, 'buy': 2}
self.args = TrainingArguments(
os.path.join(self.RESOURCE_PATH, 'model', f"stock_vit_predictor"),
save_strategy="epoch",
evaluation_strategy="epoch",
learning_rate=2e-5,
per_device_train_batch_size=128,
per_device_eval_batch_size=128,
weight_decay=0.01,
load_best_model_at_end=True,
metric_for_best_model="accuracy",
logging_dir=os.path.join(self.RESOURCE_PATH, 'model', 'logs'),
remove_unused_columns=False,
num_train_epochs=24,
)
return
def set_seed(self, seed=42, n_gpu=0):
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
if n_gpu > 0:
torch.cuda.manual_seed_all(seed)
def train_transforms(self, examples):
examples['pixel_values'] = [self._train_transforms(image.convert("RGB")) for image in examples['img']]
return examples
def val_transforms(self, examples):
examples['pixel_values'] = [self._val_transforms(image.convert("RGB")) for image in examples['img']]
return examples
def collate_fn(self, examples):
pixel_values = torch.stack([example["pixel_values"] for example in examples])
labels = torch.tensor([example["label"] for example in examples])
return {"pixel_values": pixel_values, "labels": labels}
def compute_metrics(self, eval_pred):
predictions, labels = eval_pred
predictions = np.argmax(predictions, axis=1)
metric = load_metric("accuracy")
return metric.compute(predictions=predictions, references=labels)
def getFeature(self, model_path=None):
if model_path == None:
self.feature_extractor = ViTFeatureExtractor.from_pretrained("google/vit-base-patch16-224-in21k")
#self.feature_extractor = ViTFeatureExtractor()
else:
#self.feature_extractor = ViTFeatureExtractor.from_pretrained("google/vit-base-patch16-224-in21k")
self.feature_extractor = ViTFeatureExtractor.from_pretrained(model_path)
normalize = Normalize(mean=self.feature_extractor.image_mean, std=self.feature_extractor.image_std)
self._train_transforms = Compose(
[
RandomResizedCrop(self.feature_extractor.size),
RandomHorizontalFlip(),
ToTensor(),
normalize,
]
)
self._val_transforms = Compose(
[
Resize(self.feature_extractor.size),
CenterCrop(self.feature_extractor.size),
ToTensor(),
normalize,
]
)
return
def train(self, train_ds, val_ds, model_path):
self.getFeature()
# Set the transforms
train_ds.set_transform(self.train_transforms)
val_ds.set_transform(self.val_transforms)
train_dataloader = DataLoader(train_ds, collate_fn=self.collate_fn, batch_size=32)
batch = next(iter(train_dataloader))
for k,v in batch.items():
if isinstance(v, torch.Tensor):
print(k, v.shape)
"""
model = ViTForImageClassification.from_pretrained('google/vit-base-patch16-224-in21k',
num_labels=self.num_labels,
id2label=self.id2label,
label2id=self.label2id)
"""
configuration = ViTConfig(num_labels=self.num_labels,
id2label=self.id2label,
label2id=self.label2id)
model = ViTForImageClassification(configuration)
trainer = Trainer(
model,
self.args,
train_dataset=train_ds,
eval_dataset=val_ds,
data_collator=self.collate_fn,
compute_metrics=self.compute_metrics,
tokenizer=self.feature_extractor
)
trainer.train()
# save trained model
model_to_save = (model.module if hasattr(model, "module") else model) # Take care of distributed/parallel training
model_to_save.save_pretrained(model_path)
self.feature_extractor.save_pretrained(model_path)
torch.save(self.args, os.path.join(RESOURCE_PATH, "model", "training_args.bin"))
return
def finetunning(self, train_ds, val_ds, model_path):
self.getFeature(model_path)
# Set the transforms
train_ds.set_transform(self.train_transforms)
val_ds.set_transform(self.val_transforms)
train_dataloader = DataLoader(train_ds, collate_fn=self.collate_fn, batch_size=32)
batch = next(iter(train_dataloader))
for k,v in batch.items():
if isinstance(v, torch.Tensor):
print(k, v.shape)
model = ViTForImageClassification.from_pretrained(model_path,
num_labels=self.num_labels,
id2label=self.id2label,
label2id=self.label2id)
trainer = Trainer(
model,
self.args,
train_dataset=train_ds,
eval_dataset=val_ds,
data_collator=self.collate_fn,
compute_metrics=self.compute_metrics,
tokenizer=self.feature_extractor
)
trainer.train()
# save trained model
model_to_save = (model.module if hasattr(model, "module") else model) # Take care of distributed/parallel training
model_to_save.save_pretrained(model_path)
self.feature_extractor.save_pretrained(model_path)
torch.save(self.args, os.path.join(RESOURCE_PATH, "model", "training_args.bin"))
return
def getData(self, stock_code, sDate, eDate):
# Instance Normalization를 NumPy 및 PyTorch로 구현하는 방법! (https://ndb796.tistory.com/653)
data = self.stock2Vector.getTrainData(stock_code, sDate, eDate)
#X, Y = self.stock2Vector.getDataset2D(data)
X, Y = self.stock2Vector.getVectorData(data)
print("Data count: ", len(X))
trans = transforms.ToPILImage()
#X = [trans(torch.tensor([x])) for x in X]
X = [trans(torch.tensor(x)) for x in X]
split_point1 = int(len(X) * 0.9)
train_X = X[:split_point1]
train_Y = Y[:split_point1]
valid_X = X[split_point1:]
valid_Y = Y[split_point1:]
# load cifar10 (only small portion for demonstration purposes)
train_data = {'img': train_X, 'label': train_Y}
val_dsta = {'img': valid_X, 'label': valid_Y}
train_ds = Dataset.from_dict(train_data)
val_ds = Dataset.from_dict(val_dsta)
features = train_ds.features.copy()
features["label"] = ClassLabel(num_classes=self.num_labels, names=["none", "sell", "buy"])
def adjust_labels(batch):
batch["label"] = [lbl for lbl in batch["label"]]
return batch
train_ds = train_ds.map(adjust_labels, batched=True, features=features)
val_ds = train_ds.map(adjust_labels, batched=True, features=features)
return train_ds, val_ds
if __name__ == "__main__":
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
model_path = os.path.join(RESOURCE_PATH, "model")
stock_code = "252670"
vitTrainer = VitTrainer(RESOURCE_PATH)
train_ds, val_ds = vitTrainer.getData(stock_code, sDate="20220501", eDate="20220819")
vitTrainer.train(train_ds, val_ds, model_path)

View File

@@ -1,594 +0,0 @@
import os
import time
import shutil
import matplotlib.pyplot as plt
import datetime
import sqlite3
import math
from math import nan
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from matplotlib import rc
import pandas as pd
import numpy as np
from stock.analysis.JSDPattern_simulation import JSDPattern_simulation
from hts.BuySell_Daily import BuySell_Daily
rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
import plotly.graph_objs as go
from plotly import subplots
import plotly.io as po
from stock.analysis.Common import Common
from stock.util.TelegramBot import TelegramBot
class AnalyzerSqlite:
jSDPattern = None
buySell_Daily = None
topCompany = None
fnguide = None
bot = None
common = None
stockFileName = None
analyzedFileName = None
moving_avg = None
def __init__(self, RESOURCE_PATH):
self.common = Common()
self.stockFileName = os.path.join(RESOURCE_PATH, 'stock.db')
self.jSDPattern = JSDPattern_simulation(self.stockFileName)
self.buySell_Daily = BuySell_Daily()
self.stockFileName = self.stockFileName
self.topCompany = self.getTopCompany(self.stockFileName, 2000)
self.fnguide = self.readFnguide(self.stockFileName)
self.bot = TelegramBot()
return
def getTopCompany(self, fnguideFileName, top):
conn = sqlite3.connect(fnguideFileName)
cursor = conn.cursor()
sql = "select DISTINCT CODE, NAME from fnguide order by total_ownership_interest desc limit " + str(top)
cursor.execute(sql)
result = cursor.fetchall()
top_company = {}
for idx, item in enumerate(result):
top_company[item[0]] = (idx+1, item[1])
cursor.close()
conn.close()
return top_company
def readFnguide(self, fnguideFileName):
conn = sqlite3.connect(fnguideFileName)
cursor = conn.cursor()
today = datetime.today()
year1 = str(today.year - 1) + ".12.01"
year2 = str(today.year - 2) + ".12.01"
year3 = str(today.year - 3) + ".12.01"
sql = "SELECT CODE, NAME, ymd, business_profits, business_profits_ratio, debt_ratio, ROA, ROE, EPS, BPS, DPS, PER, PBR FROM fnguide "
sql += " WHERE (ymd=? or ymd=? or ymd=?) and type=''"
sql += " order by code, ymd desc"
cursor.execute(sql, (year1,year2,year3))
result = cursor.fetchall()
fnguide = {}
for item in result:
if item[0] not in fnguide:
fnguide[item[0]] = []
fnguide[item[0]].append(
{'NAME': item[1],
'ymd': item[2],
'business_profits': item[3],
'business_profits_ratio': item[4],
'debt_ratio': item[5],
'ROA': item[6],
'ROE': item[7],
'EPS': item[8],
'BPS': item[9],
'DPS': item[10],
'PER': item[11],
'PBR': item[12]})
cursor.close()
conn.close()
return fnguide
def cz(self, value):
if value is None or math.isnan(value):
return 0
return value
def clear_BSLINE(self, BUY_LIST, sell_type=None):
if sell_type is None or sell_type == '':
BUY_LIST['avg_buy_price'] = 0
BUY_LIST['buy_count'] = 0
BUY_LIST['buy_list'].clear()
else:
BUY_LIST['avg_buy_price'] = 0
BUY_LIST['buy_count'] = 0
tmp_sell_type = sell_type.split(',')
for i, buy_list in reversed(list(enumerate(BUY_LIST['buy_list']))):
for t_sell_type in tmp_sell_type:
if buy_list['buy_type'].strip() == t_sell_type.strip():
del BUY_LIST['buy_list'][i]
break
return
def draw(self, stock_code, data, bsLine=None):
# 어제 데이터는 지운다.
#data = data.loc[pd.DatetimeIndex(data.index).day == int(given_day[6:])]
buy_price_line, buy_count_line, buy_type, buy_count_line, sell_price_line, sell_count_line, sell_type = [], [], [], [], [], [], []
buy_sell_size, buy_colors, sell_colors, buy_colors = [], [], [], []
if bsLine is not None:
buy_price_line = bsLine['buy_price']
buy_count_line = bsLine['buy_count']
sell_price_line = bsLine['sell_price']
sell_count_line = bsLine['sell_count']
buy_type = bsLine['buy_type']
sell_type = bsLine['sell_type']
for i in range(len(data)):
if buy_price_line[i] < 1:
buy_colors.append("#ffffff")
buy_price_line[i] = nan
buy_sell_size.append(0)
else:
buy_colors.append("#0C752E")
buy_sell_size.append(14)
for i in range(len(data)):
if sell_price_line[i] < 1:
sell_colors.append("#ffffff")
sell_price_line[i] = nan
else:
sell_colors.append("#00ced1")
volume_colors = []
for i in range(len(data)):
if data['open'][i] > data['close'][i]:
volume_colors.append("#FF0000")
elif data['open'][i] < data['close'][i]:
volume_colors.append("#FF0000")
else:
volume_colors.append("#000000")
# 그래프를 설정한다.
if bsLine is not None:
buy_text_list, sell_text_list = [], []
for i in range(len(data['ymd'])):
buy_text_list.append(
"{}, {}, {} ({:,.2f})<br><br>"
"avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}<br>"
"avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}<br><br>"
"loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}<br><br>"
"laggingSpan_close_diff: {:.4f} ({:.4f})<br>"
"laggingSpan_avg60_diff: {:.4f} ({:.4f})<br>"
"leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})<br>"
.format(data['ymd'][i].strftime('%Y-%m-%d %H:%M'), buy_type[i], self.cz(buy_price_line[i]), self.cz(buy_price_line[i])*self.cz(buy_count_line[i]),
self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]),
self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]),
self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]),
self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]),
self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i])
))
sell_text_list.append(
"{}, {}, {} ({:,.2f})<br><br>"
"avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}<br>"
"avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}<br><br>"
"loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}<br><br>"
"laggingSpan_close_diff: {:.4f} ({:.4f})<br>"
"laggingSpan_avg60_diff: {:.4f} ({:.4f})<br>"
"leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})<br>"
.format(
data['ymd'][i].strftime('%Y-%m-%d %H:%M'), sell_type[i], self.cz(sell_price_line[i]), self.cz(sell_price_line[i])*self.cz(sell_count_line[i]),
self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]),
self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]),
self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]),
self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]),
self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i])
))
buy_check = go.Scatter(x=data['ymd'], y=buy_price_line, mode='markers', name="buy_price", marker=dict(size=buy_sell_size, color=buy_colors, line_width=0), text=buy_text_list, hoverinfo="text")
sell_check = go.Scatter(x=data['ymd'], y=sell_price_line, mode='markers', name="sell_price", marker=dict(size=14, color=sell_colors, line_width=0), text=sell_text_list, hoverinfo="text")
volume_line = go.Bar(x=data['ymd'], y=data["volume"], marker_color=volume_colors, name='volume')
avg5 = go.Scatter(x=data['ymd'], y=data["avg5"], name="avg5", line_color='#079118')
avg10 = go.Scatter(x=data['ymd'], y=data["avg10"], name="avg10", line_color='grey')
avg20 = go.Scatter(x=data['ymd'], y=data["avg20"], name="avg20", line_color='#d755e8')
avg60 = go.Scatter(x=data['ymd'], y=data["avg60"], name="avg60", line_color='#099B92')
avg90 = go.Scatter(x=data['ymd'], y=data["avg90"], name="avg90", line_color='#2a9c0c')
avg120 = go.Scatter(x=data['ymd'], y=data["avg120"], name="avg120", line_color='#079118')
avg240 = go.Scatter(x=data['ymd'], y=data["avg240"], name="avg240", line_color='#e68456')
avg360 = go.Scatter(x=data['ymd'], y=data["avg360"], name="avg360", line_color='#e6b55c')
avg480 = go.Scatter(x=data['ymd'], y=data["avg480"], name="avg480", line_color='#2a9c0c')
avg720 = go.Scatter(x=data['ymd'], y=data["avg720"], name="avg720", line_color='#e75d53')
avg1440 = go.Scatter(x=data['ymd'], y=data["avg1440"], name="avg1440", line_color='#2a9c0c')
avg2880 = go.Scatter(x=data['ymd'], y=data["avg2880"], name="avg2880", line_color='#46406c')
laggingSpan_0_8_limit = [0.8 for i in data['ymd']]
laggingSpan_0_2_limit = [0.2 for i in data['ymd']]
laggingSpan_0_limit = [0 for i in data['ymd']]
laggingSpan__0_2_limit = [-0.2 for i in data['ymd']]
laggingSpan__0_8_limit = [-0.8 for i in data['ymd']]
laggingSpan_0_8_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_8_limit, line=dict(color='grey', width=1), name='laggingSpan_0_8_limit')
laggingSpan_0_2_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_2_limit, line=dict(color='grey', width=1), name='laggingSpan_0_2_limit')
laggingSpan_0_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan_0_limit, line=dict(color='grey', width=1), name='laggingSpan_0_limit')
laggingSpan__0_2_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan__0_2_limit, line=dict(color='grey', width=1), name='laggingSpan__0_2_limit')
laggingSpan__0_8_limit_line = go.Scatter(x=data['ymd'], y=laggingSpan__0_8_limit, line=dict(color='grey', width=1), name='laggingSpan__0_8_limit')
laggingSpan_close_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_close_diff"], name="laggingSpan_close_diff", line_color='#079118')
laggingSpan_avg60_diff = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff"], name="laggingSpan_avg60_diff", line_color='#d755e8')
leadingSpan1_leadingSpan2_diff = go.Scatter(x=data['ymd'], y=data["leadingSpan1_leadingSpan2_diff"], name="leadingSpan1_leadingSpan2_diff", line_color='#d755e8')
laggingSpan_close_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_close_diff_rate"], name="laggingSpan_close_diff_rate", line_color='#d755e8')
laggingSpan_avg60_diff_rate = go.Scatter(x=data['ymd'], y=data["laggingSpan_avg60_diff_rate"], name="laggingSpan_avg60_diff_rate", line_color='#d755e8')
leadingSpan1_leadingSpan2_diff_rate = go.Scatter(x=data['ymd'], y=data["leadingSpan1_leadingSpan2_diff_rate"], name="leadingSpan1_leadingSpan2_diff_rate", line_color='#d755e8')
changeLine = go.Scatter(x=data['ymd'], y=data["changeLine"], name="changeLine", line_color='#0196ff')
baseLine = go.Scatter(x=data['ymd'], y=data["baseLine"], name="baseLine", line_color='#991515')
laggingSpan = go.Scatter(x=data['ymd'], y=data["laggingSpan"], name="laggingSpan", line_color='#12A524')
leadingSpan1 = go.Scatter(x=data['ymd'], y=data["leadingSpan1"], name="leadingSpan1", line_color='#008001')
leadingSpan2 = go.Scatter(x=data['ymd'], y=data["leadingSpan2"], name="leadingSpan2", line_color='#830fd4')
upper_10_Line = go.Scatter(x=data['ymd'], y=data["upper_10"], name="upper_10", line_color='#0196ff')
lower_10_Line = go.Scatter(x=data['ymd'], y=data["lower_10"], name="lower_10", line_color='#991515')
middle_10_line = go.Scatter(x=data['ymd'], y=data["middle_10"], name="middle_10", line_color='#12A524')
upper_20_Line = go.Scatter(x=data['ymd'], y=data["upper_20"], name="upper_20", line_color='#0196ff')
lower_20_Line = go.Scatter(x=data['ymd'], y=data["lower_20"], name="lower_20", line_color='#991515')
middle_20_line = go.Scatter(x=data['ymd'], y=data["middle_20"], name="middle_20", line_color='#12A524')
loc_240_k = go.Scatter(x=data['ymd'], y=data["loc_240_k"], name="loc_240_k", line_color='#0196ff')
loc_240_d = go.Scatter(x=data['ymd'], y=data["loc_240_d"], name="loc_240_d", line_color='#991515')
loc_240_s = go.Scatter(x=data['ymd'], y=data["loc_240_s"], name="loc_240_s", line_color='#12A524')
new_high_9 = go.Scatter(x=data['ymd'], y=data["new_high_9"], name="new_high_9", line_color='#0196ff')
new_high_26 = go.Scatter(x=data['ymd'], y=data["new_high_26"], name="new_high_26", line_color='#991515')
new_low_9 = go.Scatter(x=data['ymd'], y=data["new_low_9"], name="new_low_9", line_color='#0196ff')
new_low_26 = go.Scatter(x=data['ymd'], y=data["new_low_26"], name="new_low_26", line_color='#991515')
slowk_up_limit = [80 for i in data['ymd']]
slowk_middle_limit = [50 for i in data['ymd']]
slowk_down_limit = [20 for i in data['ymd']]
slowk_up_limit = go.Scatter(x=data['ymd'], y=slowk_up_limit, line=dict(color='grey', width=1), name='slowk_up_limit')
slowk_middle_limit = go.Scatter(x=data['ymd'], y=slowk_middle_limit, line=dict(color='grey', width=1), name='slowk_middle_limit')
slowk_down_limit = go.Scatter(x=data['ymd'], y=slowk_down_limit, line=dict(color='grey', width=1), name='slowk_down_limit')
slowk_12 = go.Scatter(x=data['ymd'], y=data["slowk_12"], line=dict(color='#079118', width=2), name='slowk_12')
slowd_12 = go.Scatter(x=data['ymd'], y=data["slowd_12"], line=dict(dash='dashdot', color='#079118', width=2), name='slowd_12')
slowk_26 = go.Scatter(x=data['ymd'], y=data["slowk_26"], line=dict(color='grey', width=2), name='slowk_26')
slowd_26 = go.Scatter(x=data['ymd'], y=data["slowd_26"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_26')
slowk_52 = go.Scatter(x=data['ymd'], y=data["slowk_52"], line=dict(color='#d755e8', width=2), name='slowk_52')
slowd_52 = go.Scatter(x=data['ymd'], y=data["slowd_52"], line=dict(dash='dashdot', color='#d755e8', width=2), name='slowd_52')
text_list = []
for i in range(len(data['ymd'])):
text_list.append(
"{}<br><br>"
"avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}<br>"
"avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}<br><br>"
"loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}<br><br>"
"laggingSpan_close_diff: {:.4f} ({:.4f})<br>"
"laggingSpan_avg60_diff: {:.4f} ({:.4f})<br>"
"leadingSpan1_leadingSpan2_diff: {:.4f} ({:.4f})<br>"
.format(
data['ymd'][i].strftime('%Y-%m-%d %H:%M'),
self.cz(data["avg5"][i]), self.cz(data["avg10"][i]), self.cz(data["avg20"][i]), self.cz(data["avg60"][i]), self.cz(data["avg90"][i]), self.cz(data["avg120"][i]), self.cz(data["avg240"][i]), self.cz(data["avg360"][i]), self.cz(data["avg480"][i]), self.cz(data["avg720"][i]), self.cz(data["avg1440"][i]), self.cz(data["avg2880"][i]),
self.cz(data['loc_240_k'][i]), self.cz(data['loc_240_d'][i]), self.cz(data['loc_240_s'][i]),
self.cz(data['laggingSpan_close_diff'][i]), self.cz(data['laggingSpan_close_diff_rate'][i]),
self.cz(data['laggingSpan_avg60_diff'][i]), self.cz(data['laggingSpan_avg60_diff_rate'][i]),
self.cz(data['leadingSpan1_leadingSpan2_diff'][i]), self.cz(data['leadingSpan1_leadingSpan2_diff_rate'][i])
))
candle_stick = go.Candlestick(x=data['ymd'],
open=data['open'], high=data['high'], low=data['low'], close=data['close'],
increasing_line_color='red', decreasing_line_color='blue',
name='candle', text=text_list, hoverinfo="text"
)
if bsLine is not None:
candle_data = [avg5, avg10, avg20, avg60, avg90, avg120, avg240, avg360, avg480, avg720, avg1440, avg2880, buy_check, sell_check, candle_stick, changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2, upper_10_Line, lower_10_Line, middle_10_line, upper_20_Line, lower_20_Line, middle_20_line]
else:
candle_data = [avg5, avg10, avg20, avg60, avg90, avg120, avg240, avg360, avg480, avg720, avg1440, avg2880, candle_stick,changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2]
volume_data = [volume_line]
disparity_data = [laggingSpan_close_diff, laggingSpan_avg60_diff, leadingSpan1_leadingSpan2_diff]
loc_disparity_data = [laggingSpan_0_8_limit_line, laggingSpan_0_2_limit_line, laggingSpan_0_limit_line, laggingSpan__0_2_limit_line, laggingSpan__0_8_limit_line,
laggingSpan_close_diff_rate, laggingSpan_avg60_diff_rate, leadingSpan1_leadingSpan2_diff_rate,
loc_240_k, loc_240_d, loc_240_s,
new_high_9 ,new_high_26, new_low_9 ,new_low_26]
stochastic_data = [
slowk_up_limit, slowk_middle_limit, slowk_down_limit,
slowk_12, slowd_12,
slowk_26, slowd_26,
slowk_52, slowd_52
]
# 그래프를 그린다.
"""
fig = go.Figure(data=candle_data)
fig.update_layout(title=stock_code)
fig.show()
"""
fig = subplots.make_subplots(
rows=5, cols=1,
subplot_titles=("이격도", "이격도 위치", "캔들", "slowkd", "거래량"),
shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01,
row_heights=[200, 200, 700, 200, 200]
)
for trace in disparity_data:
fig.append_trace(trace, 1, 1)
for trace in loc_disparity_data:
fig.append_trace(trace, 2, 1)
for trace in candle_data:
fig.append_trace(trace, 3, 1)
for trace in stochastic_data:
fig.append_trace(trace, 4, 1)
for trace in volume_data:
fig.append_trace(trace, 5, 1)
#fig.update_xaxes(nticks=5)
#fig.update_layout(height=2400, title=stock_code, xaxis_rangeslider_visible=False)
df = pd.DataFrame(bsLine)
df = df.fillna(-1)
buy_count = 0
if bsLine is not None:
buy_count = len(df.loc[df["buy_price"] > 0])
fig.update_layout(height=1400,
title="{}, buy: {}".format(stock_code, buy_count),
xaxis_rangeslider_visible=False,
xaxis2_rangeslider_visible=False,
xaxis3_rangeslider_visible=False,
xaxis4_rangeslider_visible=False
)
# 화면으로 출력함
return fig
def getPositionalEnergy(self, close):
# 260 (= 52 * 5)일 중 가장 찾은 금액과 가장 높았던 금액 중 현재가의 위치 계산
top = close[0]
bottom = close[0]
for i in range(1, 260):
if i >= len(close):
break
if top < close[i]:
top = close[i]
if bottom > close[i]:
bottom = close[i]
if top-close[0] == 0:
energy1 = 100.0
else:
energy1 = round((close[0]-bottom) / (top-close[0]), 2)
energy2 = round((close[0] / top), 2)
return energy1, energy2
def writeSummary(self, param):
bull = list(param['bull'])
bear = list(param['bear'])
even = list(param['even'])
ymd = [i for i in range(len(bull))]
bull_line = go.Scatter(x=ymd, y=bull, name="bull", line_color='#FF33A2')
bear_line = go.Scatter(x=ymd, y=bear, name="bear", line_color='#1469F4')
even_line = go.Scatter(x=ymd, y=even, name="even", line_color='#8B4513')
line_data = [bull_line, bear_line, even_line]
fig = subplots.make_subplots(
rows=1, cols=1,
subplot_titles=("주식 상황"),
shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01,
row_heights=[800]
)
for trace in line_data:
fig.append_trace(trace, 1, 1)
fig.update_layout(height=810, xaxis_rangeslider_visible=False)
sum = param['bull'][0] + param['bear'][0] + param['even'][0]
title = "[Summary] bull: %d (%.2f), bear: %d (%.2f), even: %d (%.2f)" % (param['bull'][0], param['bull'][0]/sum, param['bear'][0], param['bear'][0]/sum, param['even'][0], param['even'][0]/sum)
fig['layout'].update(title=title)
#fileName = "%s/summary.html" % (self.outPath)
#po.write_html(fig, file=fileName, auto_open=False)
return
def writeFile(self, outPath, CODE, NAME, top, stock, bsLine):
# 3년 이내 한번이라도 영업이익이 났는지 체크를 함
fnguide = None
if CODE in self.fnguide:
fnguide = self.fnguide[CODE]
check = True
if fnguide:
check = False
for item in fnguide:
if item['business_profits'] > 0:
check = True
if check:
fig = self.draw(CODE, stock, bsLine)
title = "%s (%s), 차트 (<a href=\"https://alphasquare.co.kr/home/stock/financial-information?code=%s\">URL1</a>, <a href=\"https://www.tradingview.com/chart/jJ8zOXz0/?symbol=KRX:%s\">URL2</a>, <a href=\"https://www.investing.com/search/?q=%s\">URL3</a>)" % (NAME, CODE, CODE, CODE, CODE)
fig['layout'].update(title=title)
fileName = outPath + "/%s_%s_%s_%s.html" % (datetime.today().strftime("%Y%m%d"), top, NAME.replace(" ", ""), CODE)
po.write_html(fig, file=fileName, auto_open=False)
return
def checkVolume(self, p_volume, volume):
if 0 < p_volume <= 10000 and p_volume * 700 < volume:
return True
if 10000 < p_volume <= 50000 and p_volume * 40 < volume:
return True
if 50000 < p_volume <= 100000 and p_volume * 25 < volume:
return True
if 100000 < p_volume <= 200000 and p_volume * 15 < volume:
return True
if 200000 < p_volume <= 700000 and p_volume * 13 < volume:
return True
if 700000 < p_volume <= 1000000 and p_volume * 10 < volume:
return True
if 5000000 < p_volume <= 5000000 and p_volume * 5 < volume:
return True
if 5000000 < p_volume and p_volume * 4 < volume:
return True
return False
def getStockData(self, CODE):
data_daily, ci_daily = self.jSDPattern.getData(CODE, ymd=(datetime.now()+timedelta(days=1)).strftime('%Y%m%d'), get_days=1500)
return data_daily, ci_daily
def makeDir(self, dir_name):
if os.path.isdir(self.outPath + "/" + dir_name):
os.rmdir(self.outPath + "/" + dir_name)
os.mkdir(self.outPath + "/" + dir_name)
return
def checkTransaction(self, ticker, data, ci):
# 어제 오늘 데이터로 분석
bsLine = {}
if data is not None and 'close' in data.columns:
size = len(data["close"])
bsLine['buy_ymd'] = [None for i in range(size)]
bsLine['buy_price'] = [0 for i in range(size)]
bsLine['buy_count'] = [0 for i in range(size)]
bsLine['buy_type'] = ['' for i in range(size)]
bsLine['buy_cut'] = [None for i in range(size)]
bsLine['sell_price'] = [0 for i in range(size)]
bsLine['sell_count'] = [0 for i in range(size)]
bsLine['sell_type'] = ['' for i in range(size)]
bsLine['sell_cut'] = [0 for i in range(size)]
size = ci
start = 0
for i in range(start, size):
# 매도 확인
sell_price, sell_count, sell_type = self.buySell_Daily.getSellPrice(ticker, data, i, bsLine)
bsLine['sell_price'][i] = sell_price
bsLine['sell_count'][i] = sell_count
bsLine['sell_type'][i] = sell_type
bsLine['sell_cut'][i] = 0
if sell_price < 1:
buy_ymd, buy_price, buy_count, buy_type, buy_cut = self.buySell_Daily.getBuyPrice(ticker, data, i, bsLine)
bsLine['buy_ymd'][i] = buy_ymd
bsLine['buy_price'][i] = buy_price
bsLine['buy_count'][i] = buy_count
bsLine['buy_type'][i] = buy_type
bsLine['buy_cut'][i] = buy_cut
return bsLine
# 후보 찾기
def findCandidates(self, outPath):
buy_stock_list = []
stockTableName = 'stock'
fnguideTableName = 'fnguide'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
#cursor.execute('select CODE, NAME, max(ymd) as ymd from ' + fnguideTableName + ' where type != "E" group by 1 order by total_assets desc')
items = cursor.fetchall()
cursor.close()
conn.close()
for idx, item in enumerate(items):
CODE = item[0]
NAME = item[1]
ticker = {'ticker_code': CODE, 'ticker_name': NAME, 'unit': 0, 'MAX_BUY': 10000, 'BUY_INFO': {'buy_list': []}}
print("#", idx, ", CODE: ", CODE, ", NAME: ", NAME)
stock_daily, ci = self.getStockData(CODE)
bsLine = self.checkTransaction(ticker, stock_daily, ci)
if bsLine['buy_ymd'][ci-1] is not None:
top = "0"
if CODE in self.topCompany:
top = str(self.topCompany[CODE][0])
# 거래량이 10만 이상이고, 종가가 1천원 이상인지 체크 (https://happpy-rich.tistory.com/94)
if stock_daily['volume'][ci-1] > 100000 and stock_daily['close'][ci-1] > 1000:
# 종목 상태 체크 분석
self.writeFile(outPath, CODE, NAME, top, stock_daily, bsLine)
buy_stock_list.append({'CODE': CODE, 'NAME': NAME})
buy_stock_str = ''
for i, item in enumerate(buy_stock_list):
buy_stock_str += str(i + 1) + ". " + item['CODE'] + "(" + item['NAME'] + ")\n"
self.bot.sendMsg("{}".format(buy_stock_str))
return
if __name__ == "__main__":
start = time.time()
PROJECT_HOME = os.path.join(os.path.dirname(os.path.join(os.path.dirname(os.path.join(os.path.dirname(__file__))))))
RESOURCE_PATH = os.path.join(PROJECT_HOME, 'resources')
analyzerSqlite = AnalyzerSqlite(RESOURCE_PATH)
# HTML 출력
outPath = os.path.join(PROJECT_HOME, "resources", "analysis")
if not os.path.isdir(outPath):
os.mkdir(outPath)
day = datetime.today().strftime("%Y%m%d")
before_7_day = datetime.today() + relativedelta(days=-7)
dayList = os.listdir(outPath)
for dayDir in dayList:
if dayDir[0] != '.' and dayDir < before_7_day.strftime("%Y%m%d"):
if os.path.exists(os.path.join(outPath, dayDir)) and os.path.isdir(os.path.join(outPath, dayDir)):
shutil.rmtree(os.path.join(outPath, dayDir))
outPath = os.path.join(outPath, day)
if os.path.isdir(outPath):
shutil.rmtree(outPath)
os.mkdir(outPath)
print("print to Html...")
analyzerSqlite.findCandidates(outPath)
print("time : %6.2f" % (time.time() - start))
print("done...")

View File

@@ -1,571 +0,0 @@
# 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 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
from sklearn.preprocessing import StandardScaler
class JSDPattern:
stockFileName = None
ichimokuCloud = None
scaler = None
def __init__(self, stockFileName=None):
self.stockFileName = stockFileName
self.ichimokuCloud = IchimokuCloud()
self.scaler = StandardScaler()
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'][i])
data['close'].append(df['close'][i])
data['high'].append(df['high'][i])
data['low'].append(df['low'][i])
data['volume'].append(df['volume'][i])
return data
def getDBData(self, stock_code, day, get_days=14):
table = 'stock'
conn = sqlite3.connect(self.stockFileName)
cursor = conn.cursor()
result = {"ymd": [], "open": [], "close": [], "high": [], "low": [], "volume": []}
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, open, high, low, close, volume FROM ' + table + ' WHERE CODE=? and ymd=? order by ymd', (stock_code, this_day,))
db_result = cursor.fetchall()
for rows in db_result:
ymd = datetime.strptime(rows[0], '%Y.%m.%d') # hts.날짜
open = rows[1] # hts.시가
high = rows[2] # hts.고가
low = rows[3] # hts.저가
close = rows[4] # hts.종가
vol = rows[5] # hts.거래량
result["ymd"].append(ymd)
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, ymd=None, get_days=14):
result = self.getDBData(ticker, ymd, 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 price2[i] is not None:
diff[i] = price1[i] - price2[i]
else:
diff[i] = None
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:
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] = None
return diff, diff_rate
def analyze(self, result, mins=1):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
# ichimokuCloud
df = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
column_names = ['DATE', 'open', 'close', 'high', 'low', 'volume']
df.columns = column_names
c, b, l, s = 9, 26, 52, 26
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
# 3. 후행스팬 = 현재 close가격의 26일전 반영
laggingSpan = [df.close.values[i + s] for i in range(len(df.close) - s)]
laggingSpan += [None for i in range(s)]
laggingSpan = np.array(laggingSpan)
# 4. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
tmp_leadingSpan1 = (changeLine + baseLine) / 2
""" S: 26일 선행시킴 """
leadingSpan1 = list(tmp_leadingSpan1.values)
for i in range(b - 1):
leadingSpan1.insert(0, None)
""" E: 26일 선행시킴 """
# 5. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
tmp_leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
""" S: 52일 선행시킴 """
leadingSpan2 = list(tmp_leadingSpan2.values)
for i in range(l - 1):
leadingSpan2.insert(0, None)
""" S: 52일 선행시킴 """
baseLine = baseLine.tolist()
changeLine = changeLine.tolist()
laggingSpan = list(laggingSpan)
current_index = len(ymd)
for i in range(51):
if len(ymd) < len(leadingSpan2):
if mins==1440:
ymd.append(ymd[-1] + timedelta(days=1))
else:
ymd.append(ymd[-1] + timedelta(minutes=1))
if len(open) < len(leadingSpan2):
open.append(None)
if len(close) < len(leadingSpan2):
close.append(None)
if len(high) < len(leadingSpan2):
high.append(None)
if len(low) < len(leadingSpan2):
low.append(None)
if len(volume) < len(leadingSpan2):
volume.append(None)
if len(baseLine) < len(leadingSpan2):
baseLine.append(None)
if len(changeLine) < len(leadingSpan2):
changeLine.append(None)
if len(laggingSpan) < len(leadingSpan2):
laggingSpan.append(None)
for i in range(26):
if len(leadingSpan1) < len(leadingSpan2):
leadingSpan1.append(leadingSpan1[-1])
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and max(close[c-8:c]) < close[c] else 0 for c in range(8, len(close))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and max(close[c-25:c]) < close[c] else 0 for c in range(25, len(close))]
# 33일 신고가
new_high_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c-1] is not None and leadingSpan1[c] is not None and leadingSpan1[c-1] < leadingSpan1[c]) and None not in close[c-8:c+1] and max(close[c-32:c]) < close[c] else 0 for c in range(32, len(close))]
# 52일 신고가
new_high_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c-1] is not None and leadingSpan2[c] is not None and leadingSpan2[c-1] < leadingSpan2[c]) and None not in close[c-8:c+1] and max(close[c-51:c]) < close[c] else 0 for c in range(51, len(close))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and close[c-9] < min(close[c-8:c+1]) else 0 for c in range(8, len(close))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and close[c-26] < min(close[c-25:c+1]) else 0 for c in range(25, len(close))]
# 33일 신저가
new_low_33 = [0 for c in range(32)] + [1 if (leadingSpan1[c-1] is not None and leadingSpan1[c] is not None and leadingSpan1[c-1] < leadingSpan1[c]) and None not in close[c-8:c+1] and close[c-33] < min(close[c-32:c+1]) else 0 for c in range(32, len(close))]
# 52일 신저가
new_low_52 = [0 for c in range(51)] + [1 if (leadingSpan2[c-1] is not None and leadingSpan2[c] is not None and leadingSpan2[c-1] < leadingSpan2[c]) and None not in close[c-8:c+1] and close[c-52] < min(close[c-51:c+1]) else 0 for c in range(51, len(close))]
# 이동 평균
close_df = pd.DataFrame(close)
avg5 = list(np.reshape(close_df.ewm(5).mean().values, -1))
avg10 = list(np.reshape(close_df.ewm(10).mean().values, -1))
avg20 = list(np.reshape(close_df.ewm(20).mean().values, -1))
avg60 = list(np.reshape(close_df.ewm(60).mean().values, -1))
avg90 = list(np.reshape(close_df.ewm(90).mean().values, -1))
avg120 = list(np.reshape(close_df.ewm(120).mean().values, -1))
avg240 = list(np.reshape(close_df.ewm(240).mean().values, -1))
avg360 = list(np.reshape(close_df.ewm(360).mean().values, -1))
avg480 = list(np.reshape(close_df.ewm(480).mean().values, -1))
avg720 = list(np.reshape(close_df.ewm(720).mean().values, -1))
avg1440 = list(np.reshape(close_df.ewm(1440).mean().values, -1))
avg2880 = list(np.reshape(close_df.ewm(2880).mean().values, -1))
np_high, np_low, np_close = np.array(high, dtype=np.float64), np.array(low, dtype=np.float64), np.array(close, dtype=np.float64)
slowk_12_df, slowd_12_df = talib.STOCH(np_high, np_low, np_close, fastk_period=12, slowk_period=5, slowk_matype=0, slowd_period=5, slowd_matype=0)
slowk_26_df, slowd_26_df = talib.STOCH(np_high, np_low, np_close, fastk_period=26, slowk_period=16, slowk_matype=0, slowd_period=16, slowd_matype=0)
slowk_52_df, slowd_52_df = talib.STOCH(np_high, np_low, np_close, fastk_period=52, slowk_period=32, slowk_matype=0, slowd_period=32, slowd_matype=0)
# 최고/최저 위치
loc_240 = [None for i in range(len(close))]
for i in range(240, len(close)):
min_v = np.min(result["close"][i-239:i+1])
max_v = np.max(result["close"][i-239:i+1])
if close[i] is not None:
loc_240[i] = ((close[i] - min_v) / (max_v - min_v))
else:
loc_240[i] = None
loc_240 = pd.DataFrame(loc_240)
loc_240_k = loc_240.to_numpy().reshape(-1)
loc_240_d = loc_240.rolling(20).mean()
loc_240_s = loc_240.rolling(60).mean()
loc_240_d = loc_240_d.to_numpy().reshape(-1)
loc_240_s = loc_240_s.to_numpy().reshape(-1)
# 볼린저 밴드
n, t = 10, 2
max_10 = close_df.rolling(window=n).mean()
stddev_10 = close_df.rolling(window=n).std()
upper_10 = max_10 + (stddev_10 * t) # 상단 볼리저 밴드
lower_10 = max_10 - (stddev_10 * t) # 하단 볼리저 밴드
middle_10 = (upper_10 + lower_10) / 2
upper_10 = list(np.reshape(upper_10.values, -1))
lower_10 = list(np.reshape(lower_10.values, -1))
middle_10 = list(np.reshape(middle_10.values, -1))
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
duration = 1440
if mins == 1440:
duration = 360
laggingSpan_close_diff, laggingSpan_close_diff_rate = self.getDiff_Rate(laggingSpan, close, duration=duration)
laggingSpan_changeLine_diff, laggingSpan_changeLine_diff_rate = self.getDiff_Rate(laggingSpan, changeLine, duration=duration)
laggingSpan_baseLine_diff, laggingSpan_baseLine_diff_rate = self.getDiff_Rate(laggingSpan, baseLine, duration=duration)
laggingSpan_leadingSpan1_diff, laggingSpan_leadingSpan1_diff_rate = self.getDiff_Rate(laggingSpan, leadingSpan1, duration=duration)
laggingSpan_leadingSpan2_diff, laggingSpan_leadingSpan2_diff_rate = self.getDiff_Rate(laggingSpan, leadingSpan2, duration=duration)
laggingSpan_avg60_diff, laggingSpan_avg60_diff_rate = self.getDiff_Rate(laggingSpan, avg60, duration=duration)
laggingSpan_lower10_diff, laggingSpan_lower10_diff_rate = self.getDiff_Rate(laggingSpan, lower_10, duration=duration)
laggingSpan_middle10_diff, laggingSpan_middle10_diff_rate = self.getDiff_Rate(laggingSpan, middle_10, duration=duration)
laggingSpan_upper10_diff, laggingSpan_upper10_diff_rate = self.getDiff_Rate(laggingSpan, upper_10, duration=duration)
laggingSpan_lower20_diff, laggingSpan_lower20_diff_rate = self.getDiff_Rate(laggingSpan, lower_20, duration=duration)
laggingSpan_middle20_diff, laggingSpan_middle20_diff_rate = self.getDiff_Rate(laggingSpan, middle_20, duration=duration)
laggingSpan_upper20_diff, laggingSpan_upper20_diff_rate = self.getDiff_Rate(laggingSpan, upper_20, duration=duration)
baseLine_close_diff, baseLine_close_diff_rate = self.getDiff_Rate(baseLine, close, duration=duration)
changeLine_close_diff, changeLine_close_diff_rate = self.getDiff_Rate(changeLine, close, duration=duration)
changeLine_baseLine_diff, changeLine_baseLine_diff_rate = self.getDiff_Rate(changeLine, baseLine, duration=duration)
changeLine_leadingSpan1_diff, changeLine_leadingSpan1_diff_rate = self.getDiff_Rate(changeLine, leadingSpan1, duration=duration)
leadingSpan1_leadingSpan2_diff, leadingSpan1_leadingSpan2_diff_rate = self.getDiff_Rate(leadingSpan1, leadingSpan2, duration=duration)
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
pd.DataFrame(changeLine), pd.DataFrame(baseLine), pd.DataFrame(laggingSpan), pd.DataFrame(leadingSpan1), pd.DataFrame(leadingSpan2),
pd.DataFrame(laggingSpan_close_diff),
pd.DataFrame(laggingSpan_changeLine_diff),
pd.DataFrame(laggingSpan_baseLine_diff),
pd.DataFrame(laggingSpan_leadingSpan1_diff),
pd.DataFrame(laggingSpan_leadingSpan2_diff),
pd.DataFrame(laggingSpan_avg60_diff),
pd.DataFrame(laggingSpan_lower10_diff),
pd.DataFrame(laggingSpan_middle10_diff),
pd.DataFrame(laggingSpan_upper10_diff),
pd.DataFrame(laggingSpan_lower20_diff),
pd.DataFrame(laggingSpan_middle20_diff),
pd.DataFrame(laggingSpan_upper20_diff),
pd.DataFrame(baseLine_close_diff),
pd.DataFrame(changeLine_close_diff),
pd.DataFrame(changeLine_baseLine_diff),
pd.DataFrame(changeLine_leadingSpan1_diff),
pd.DataFrame(leadingSpan1_leadingSpan2_diff),
pd.DataFrame(laggingSpan_close_diff_rate),
pd.DataFrame(laggingSpan_changeLine_diff_rate),
pd.DataFrame(laggingSpan_baseLine_diff_rate),
pd.DataFrame(laggingSpan_leadingSpan1_diff_rate),
pd.DataFrame(laggingSpan_leadingSpan2_diff_rate),
pd.DataFrame(laggingSpan_avg60_diff_rate),
pd.DataFrame(laggingSpan_lower10_diff_rate),
pd.DataFrame(laggingSpan_middle10_diff_rate),
pd.DataFrame(laggingSpan_upper10_diff_rate),
pd.DataFrame(laggingSpan_lower20_diff_rate),
pd.DataFrame(laggingSpan_middle20_diff_rate),
pd.DataFrame(laggingSpan_upper20_diff_rate),
pd.DataFrame(baseLine_close_diff_rate),
pd.DataFrame(changeLine_close_diff_rate),
pd.DataFrame(changeLine_baseLine_diff_rate),
pd.DataFrame(changeLine_leadingSpan1_diff_rate),
pd.DataFrame(leadingSpan1_leadingSpan2_diff_rate),
pd.DataFrame(loc_240_k), pd.DataFrame(loc_240_d), pd.DataFrame(loc_240_s),
pd.DataFrame(avg5), pd.DataFrame(avg10), pd.DataFrame(avg20), pd.DataFrame(avg60), pd.DataFrame(avg90), pd.DataFrame(avg120), pd.DataFrame(avg240), pd.DataFrame(avg360), pd.DataFrame(avg480), pd.DataFrame(avg720), pd.DataFrame(avg1440), pd.DataFrame(avg2880),
pd.DataFrame(upper_10), pd.DataFrame(lower_10), pd.DataFrame(middle_10),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20),
pd.DataFrame(new_high_9), pd.DataFrame(new_high_26), pd.DataFrame(new_high_33), pd.DataFrame(new_high_52),
pd.DataFrame(new_low_9), pd.DataFrame(new_low_26), pd.DataFrame(new_low_33), pd.DataFrame(new_low_52),
pd.DataFrame(slowk_12_df), pd.DataFrame(slowd_12_df),
pd.DataFrame(slowk_26_df), pd.DataFrame(slowd_26_df),
pd.DataFrame(slowk_52_df), pd.DataFrame(slowd_52_df),
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'changeLine', 'baseLine', 'laggingSpan', 'leadingSpan1', 'leadingSpan2',
'laggingSpan_close_diff',
'laggingSpan_changeLine_diff',
'laggingSpan_baseLine_diff',
'laggingSpan_leadingSpan1_diff',
'laggingSpan_leadingSpan2_diff',
'laggingSpan_avg60_diff',
'laggingSpan_lower10_diff',
'laggingSpan_middle10_diff',
'laggingSpan_upper10_diff',
'laggingSpan_lower20_diff',
'laggingSpan_middle20_diff',
'laggingSpan_upper20_diff',
'baseLine_close_diff',
'changeLine_close_diff',
'changeLine_baseLine_diff',
'changeLine_leadingSpan1_diff',
'leadingSpan1_leadingSpan2_diff',
'laggingSpan_close_diff_rate',
'laggingSpan_changeLine_diff_rate',
'laggingSpan_baseLine_diff_rate',
'laggingSpan_leadingSpan1_diff_rate',
'laggingSpan_leadingSpan2_diff_rate',
'laggingSpan_avg60_diff_rate',
'laggingSpan_lower10_diff_rate',
'laggingSpan_middle10_diff_rate',
'laggingSpan_upper10_diff_rate',
'laggingSpan_lower20_diff_rate',
'laggingSpan_middle20_diff_rate',
'laggingSpan_upper20_diff_rate',
'baseLine_close_diff_rate',
'changeLine_close_diff_rate',
'changeLine_baseLine_diff_rate',
'changeLine_leadingSpan1_diff_rate',
'leadingSpan1_leadingSpan2_diff_rate',
'loc_240_k', 'loc_240_d', 'loc_240_s',
'avg5', 'avg10', 'avg20', 'avg60', 'avg90', 'avg120', 'avg240', 'avg360', 'avg480', 'avg720', 'avg1440', 'avg2880',
'upper_10', 'lower_10', 'middle_10',
'upper_20', 'lower_20', 'middle_20',
'new_high_9', 'new_high_26', 'new_high_33', 'new_high_52',
'new_low_9', 'new_low_26', 'new_low_33', 'new_low_52',
'slowk_12', 'slowd_12',
'slowk_26', 'slowd_26',
'slowk_52', 'slowd_52',
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
return data, current_index
def getData(self, ticker, mins=None, ymd=None, get_days=14):
if ymd is None:
result = self.getCoinData(ticker, mins=mins, get_days=get_days)
else:
result = self.getCoinData(ticker, mins=mins, ymd=ymd, get_days=get_days)
if len(result['ymd']) < 1:
return None, None
#result_tic = self.makeTickData(result_m1, mins=minute)
data, current_index = self.analyze(result, mins=mins)
return data, current_index
def analyzePattern(self, data):
# jSDPattern.analyzePattern(data)
data = data[['open', 'high', 'low', 'close', 'volume']].astype(float)
pattern_names = talib.get_function_groups()['Pattern Recognition']
pattern_results = {}
for pattern in pattern_names:
pattern_function = getattr(talib, pattern)
result = pattern_function(data['open'].values, data['high'].values, data['low'].values, data['close'].values)
if result[-1] != 0:
pattern_results[pattern] = result[-1]
if len(pattern_results) > 0:
for pattern, result in pattern_results.items():
if result > 0:
direction = "상승"
else:
direction = "하락"
print(f"{pattern}: {direction}")
else:
print("인식된 차트 패턴이 없습니다.")
return
if __name__ == "__main__":
def min_max_normalize(data):
min_val = min(data)
max_val = max(data)
normalized_data = [(x - min_val) / (max_val - min_val) for x in data]
return normalized_data
# 예시 데이터
original_data = [-4, -3, -2, -1, 0]
normalized_data = min_max_normalize(original_data)
print(np.asarray(normalized_data)-1)
original_data = [0, 2,4,6,8,10]
normalized_data = min_max_normalize(original_data)
print(normalized_data)

View File

@@ -1,255 +0,0 @@
# 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
from scipy.signal import savgol_filter
import numpy as np
np.seterr(divide='ignore', invalid='ignore')
# 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.JSDPattern import JSDPattern
class JSDPattern_realtime (JSDPattern):
def __init__(self, stockFileName=None):
super().__init__(stockFileName)
return
def analyze(self, result):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
# ichimokuCloud
df = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
column_names = ['DATE', 'open', 'close', 'high', 'low', 'volume']
df.columns = column_names
c, b, l, s = 9, 26, 52, 26
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
# 3. 후행스팬 = 현재 close가격의 26일전 반영
laggingSpan = [df.close.values[i + s] for i in range(len(df.close) - s)]
laggingSpan += [None for i in range(s)]
laggingSpan = np.array(laggingSpan)
# 4. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
tmp_leadingSpan1 = (changeLine + baseLine) / 2
""" S: 26일 선행시킴 """
leadingSpan1 = list(tmp_leadingSpan1.values)
for i in range(b - 1):
leadingSpan1.insert(0, None)
""" E: 26일 선행시킴 """
# 5. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
tmp_leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
""" S: 52일 선행시킴 """
leadingSpan2 = list(tmp_leadingSpan2.values)
for i in range(l - 1):
leadingSpan2.insert(0, None)
""" S: 52일 선행시킴 """
baseLine = baseLine.tolist()
changeLine = changeLine.tolist()
laggingSpan = list(laggingSpan)
current_index = len(ymd)
for i in range(51):
if len(ymd) < len(leadingSpan2):
ymd.append(ymd[-1] + timedelta(days=1))
if len(open) < len(leadingSpan2):
open.append(None)
if len(close) < len(leadingSpan2):
close.append(None)
if len(high) < len(leadingSpan2):
high.append(None)
if len(low) < len(leadingSpan2):
low.append(None)
if len(volume) < len(leadingSpan2):
volume.append(None)
if len(baseLine) < len(leadingSpan2):
baseLine.append(None)
if len(changeLine) < len(leadingSpan2):
changeLine.append(None)
if len(laggingSpan) < len(leadingSpan2):
laggingSpan.append(None)
for i in range(26):
if len(leadingSpan1) < len(leadingSpan2):
leadingSpan1.append(leadingSpan1[-1])
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and max(close[c-8:c]) < close[c] else 0 for c in range(8, len(close))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and max(close[c-25:c]) < close[c] else 0 for c in range(25, len(close))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and close[c-9] < min(close[c-8:c+1]) else 0 for c in range(8, len(close))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and close[c-26] < min(close[c-25:c+1]) else 0 for c in range(25, len(close))]
# 이동 평균
close_df = pd.DataFrame(close)
avg5 = list(np.reshape(close_df.ewm(5).mean().values, -1))
avg10 = list(np.reshape(close_df.ewm(10).mean().values, -1))
avg20 = list(np.reshape(close_df.ewm(20).mean().values, -1))
avg60 = list(np.reshape(close_df.ewm(60).mean().values, -1))
avg90 = list(np.reshape(close_df.ewm(90).mean().values, -1))
avg120 = list(np.reshape(close_df.ewm(120).mean().values, -1))
avg240 = list(np.reshape(close_df.ewm(240).mean().values, -1))
avg360 = list(np.reshape(close_df.ewm(360).mean().values, -1))
avg480 = list(np.reshape(close_df.ewm(480).mean().values, -1))
np_high, np_low, np_close = np.array(high, dtype=np.float64), np.array(low, dtype=np.float64), np.array(close, dtype=np.float64)
slowk_12_df, slowd_12_df = talib.STOCH(np_high, np_low, np_close, fastk_period=12, slowk_period=5, slowk_matype=0, slowd_period=5, slowd_matype=0)
slowk_26_df, slowd_26_df = talib.STOCH(np_high, np_low, np_close, fastk_period=26, slowk_period=16, slowk_matype=0, slowd_period=16, slowd_matype=0)
slowk_52_df, slowd_52_df = talib.STOCH(np_high, np_low, np_close, fastk_period=52, slowk_period=32, slowk_matype=0, slowd_period=32, slowd_matype=0)
# 볼린저 밴드
n, t = 10, 2
max_10 = close_df.rolling(window=n).mean()
stddev_10 = close_df.rolling(window=n).std()
upper_10 = max_10 + (stddev_10 * t) # 상단 볼리저 밴드
lower_10 = max_10 - (stddev_10 * t) # 하단 볼리저 밴드
middle_10 = (upper_10 + lower_10) / 2
upper_10 = list(np.reshape(upper_10.values, -1))
lower_10 = list(np.reshape(lower_10.values, -1))
middle_10 = list(np.reshape(middle_10.values, -1))
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
duration = 360
laggingSpan_close_diff, laggingSpan_close_diff_rate = self.getDiff_Rate(laggingSpan, close, duration=duration)
laggingSpan_avg60_diff, laggingSpan_avg60_diff_rate = self.getDiff_Rate(laggingSpan, avg60, duration=duration)
leadingSpan1_leadingSpan2_diff, leadingSpan1_leadingSpan2_diff_rate = self.getDiff_Rate(leadingSpan1, leadingSpan2, duration=duration)
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
pd.DataFrame(changeLine), pd.DataFrame(baseLine), pd.DataFrame(laggingSpan), pd.DataFrame(leadingSpan1), pd.DataFrame(leadingSpan2),
pd.DataFrame(laggingSpan_close_diff),
pd.DataFrame(laggingSpan_avg60_diff),
pd.DataFrame(leadingSpan1_leadingSpan2_diff),
pd.DataFrame(laggingSpan_close_diff_rate),
pd.DataFrame(laggingSpan_avg60_diff_rate),
pd.DataFrame(leadingSpan1_leadingSpan2_diff_rate),
pd.DataFrame(avg5), pd.DataFrame(avg10), pd.DataFrame(avg20), pd.DataFrame(avg60), pd.DataFrame(avg90), pd.DataFrame(avg120), pd.DataFrame(avg240), pd.DataFrame(avg360), pd.DataFrame(avg480),
pd.DataFrame(upper_10), pd.DataFrame(lower_10), pd.DataFrame(middle_10),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20),
pd.DataFrame(new_high_9), pd.DataFrame(new_high_26),
pd.DataFrame(new_low_9), pd.DataFrame(new_low_26),
pd.DataFrame(slowk_12_df), pd.DataFrame(slowd_12_df),
pd.DataFrame(slowk_26_df), pd.DataFrame(slowd_26_df),
pd.DataFrame(slowk_52_df), pd.DataFrame(slowd_52_df),
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'changeLine', 'baseLine', 'laggingSpan', 'leadingSpan1', 'leadingSpan2',
'laggingSpan_close_diff',
'laggingSpan_avg60_diff',
'leadingSpan1_leadingSpan2_diff',
'laggingSpan_close_diff_rate',
'laggingSpan_avg60_diff_rate',
'leadingSpan1_leadingSpan2_diff_rate',
'avg5', 'avg10', 'avg20', 'avg60', 'avg90', 'avg120', 'avg240', 'avg360', 'avg480',
'upper_10', 'lower_10', 'middle_10',
'upper_20', 'lower_20', 'middle_20',
'new_high_9', 'new_high_26',
'new_low_9', 'new_low_26',
'slowk_12', 'slowd_12',
'slowk_26', 'slowd_26',
'slowk_52', 'slowd_52',
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
return data, current_index
def getData(self, ticker, ymd=None, get_days=14):
if ymd is None:
result = self.getCoinData(ticker, get_days=get_days)
else:
result = self.getCoinData(ticker, ymd=ymd, get_days=get_days)
if len(result['ymd']) < 1:
return None, None
#result_tic = self.makeTickData(result_m1, mins=minute)
data, current_index = self.analyze(result)
return data, current_index
if __name__ == "__main__":
def min_max_normalize(data):
min_val = min(data)
max_val = max(data)
normalized_data = [(x - min_val) / (max_val - min_val) for x in data]
return normalized_data
# 예시 데이터
original_data = [-4, -3, -2, -1, 0]
normalized_data = min_max_normalize(original_data)
print(np.asarray(normalized_data)-1)
original_data = [0, 2,4,6,8,10]
normalized_data = min_max_normalize(original_data)
print(normalized_data)

View File

@@ -1,288 +0,0 @@
# 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
from scipy.signal import savgol_filter
import numpy as np
np.seterr(divide='ignore', invalid='ignore')
# 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
from sklearn.preprocessing import StandardScaler
from stock.analysis.JSDPattern import JSDPattern
class JSDPattern_simulation (JSDPattern):
def __init__(self, RESOURCE_PATH=None):
super().__init__(RESOURCE_PATH)
return
def analyze(self, result, mins=1440):
result["volume"] = [result["volume"][i] if 0 < result["volume"][i] else 1 for i in range(len(result["volume"]))]
# 기본 캔들 정보
open_df = pd.DataFrame(result["open"])
close_df = pd.DataFrame(result["close"])
high_df = pd.DataFrame(result["high"])
low_df = pd.DataFrame(result["low"])
volume_df = pd.DataFrame(result["volume"])
# 중복 제거
ymd_df = pd.DataFrame(result["ymd"])
data_dup = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
data_dup.columns = ["ymd", "open", "close", "high", "low", "volume"]
data_dup.index = pd.DatetimeIndex(result["ymd"])
data_dup_sorted = data_dup.sort_index(ascending=True)
data_dup_sorted = data_dup_sorted.drop_duplicates()
ymd_df = data_dup_sorted["ymd"]
open_df = data_dup_sorted["open"]
close_df = data_dup_sorted["close"]
high_df = data_dup_sorted["high"]
low_df = data_dup_sorted["low"]
volume_df = data_dup_sorted["volume"]
ymd = ymd_df.tolist()
open = open_df.tolist()
close = close_df.tolist()
high = high_df.tolist()
low = low_df.tolist()
volume = volume_df.tolist()
# ichimokuCloud
df = pd.concat([ymd_df, open_df, close_df, high_df, low_df, volume_df], axis=1)
column_names = ['DATE', 'open', 'close', 'high', 'low', 'volume']
df.columns = column_names
c, b, l, s = 9, 26, 52, 26
# 1. 전환선 = (과거 9일 동안 최고가 + 최저가) / 2
# 당일을 포함한 9일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
changeLine = (df.high.rolling(c).max() + df.low.rolling(c).min()) / 2
# 2. 기준선 = 과거 26일 동안 최고가 + 최저가) / 2
# 당일을 포함한 26일 동안의 최고가와 최저가의 중간 값을 평균으로 나타낸다.
baseLine = (df.high.rolling(b).max() + df.low.rolling(b).min()) / 2
# 3. 후행스팬 = 현재 close가격의 26일전 반영
laggingSpan = [df.close.values[i + s] for i in range(len(df.close) - s)]
laggingSpan += [None for i in range(s)]
laggingSpan = np.array(laggingSpan)
# 4. 선행스팬 1 = ((기준선 + 전환선) / 2)를 26일 선행하여 배치
# 전환선과 기준선의 평균값을 구해 당일 포함 26일 앞으로 이동시킨 선 (중-단기 구간의 힘을 보여줌)
tmp_leadingSpan1 = (changeLine + baseLine) / 2
""" S: 26일 선행시킴 """
leadingSpan1 = list(tmp_leadingSpan1.values)
for i in range(b - 1):
leadingSpan1.insert(0, None)
""" E: 26일 선행시킴 """
# 5. 선행스팬 2 = ((최근 52일 동안 최고가 + 최저가) / 2)를 26일 선행하여 배치
# 당일을 포함한 52일 동안의 최고가와 최저가의 평균을 26일 앞으로 이동시킨 선 (장기으로 형성된 선이기 때문에 가장 느리게 변함)
tmp_leadingSpan2 = (df.high.rolling(l).max() + df.low.rolling(l).min()) / 2
""" S: 52일 선행시킴 """
leadingSpan2 = list(tmp_leadingSpan2.values)
for i in range(l - 1):
leadingSpan2.insert(0, None)
""" S: 52일 선행시킴 """
baseLine = baseLine.tolist()
changeLine = changeLine.tolist()
laggingSpan = list(laggingSpan)
current_index = len(ymd)
for i in range(51):
if len(ymd) < len(leadingSpan2):
if mins==1440:
ymd.append(ymd[-1] + timedelta(days=1))
else:
ymd.append(ymd[-1] + timedelta(minutes=1))
if len(open) < len(leadingSpan2):
open.append(None)
if len(close) < len(leadingSpan2):
close.append(None)
if len(high) < len(leadingSpan2):
high.append(None)
if len(low) < len(leadingSpan2):
low.append(None)
if len(volume) < len(leadingSpan2):
volume.append(None)
if len(baseLine) < len(leadingSpan2):
baseLine.append(None)
if len(changeLine) < len(leadingSpan2):
changeLine.append(None)
if len(laggingSpan) < len(leadingSpan2):
laggingSpan.append(None)
for i in range(26):
if len(leadingSpan1) < len(leadingSpan2):
leadingSpan1.append(leadingSpan1[-1])
# 9일 신고가
new_high_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and max(close[c-8:c]) < close[c] else 0 for c in range(8, len(close))]
# 26일 신고가
new_high_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and max(close[c-25:c]) < close[c] else 0 for c in range(25, len(close))]
# 9일 신저가
new_low_9 = [0 for c in range(8)] + [1 if (changeLine[c-1] is not None and changeLine[c] is not None and changeLine[c-1] < changeLine[c]) and None not in close[c-8:c+1] and close[c-9] < min(close[c-8:c+1]) else 0 for c in range(8, len(close))]
# 26일 신저가
new_low_26 = [0 for c in range(25)] + [1 if (baseLine[c-1] is not None and baseLine[c] is not None and baseLine[c-1] < baseLine[c]) and None not in close[c-8:c+1] and close[c-26] < min(close[c-25:c+1]) else 0 for c in range(25, len(close))]
# 이동 평균
close_df = pd.DataFrame(close)
avg5 = list(np.reshape(close_df.ewm(5).mean().values, -1))
avg10 = list(np.reshape(close_df.ewm(10).mean().values, -1))
avg20 = list(np.reshape(close_df.ewm(20).mean().values, -1))
avg60 = list(np.reshape(close_df.ewm(60).mean().values, -1))
avg90 = list(np.reshape(close_df.ewm(90).mean().values, -1))
avg120 = list(np.reshape(close_df.ewm(120).mean().values, -1))
avg240 = list(np.reshape(close_df.ewm(240).mean().values, -1))
avg360 = list(np.reshape(close_df.ewm(360).mean().values, -1))
avg480 = list(np.reshape(close_df.ewm(480).mean().values, -1))
avg720 = list(np.reshape(close_df.ewm(720).mean().values, -1))
avg1440 = list(np.reshape(close_df.ewm(1440).mean().values, -1))
avg2880 = list(np.reshape(close_df.ewm(2880).mean().values, -1))
np_high, np_low, np_close = np.array(high, dtype=np.float64), np.array(low, dtype=np.float64), np.array(close, dtype=np.float64)
slowk_12_df, slowd_12_df = talib.STOCH(np_high, np_low, np_close, fastk_period=12, slowk_period=5, slowk_matype=0, slowd_period=5, slowd_matype=0)
slowk_26_df, slowd_26_df = talib.STOCH(np_high, np_low, np_close, fastk_period=26, slowk_period=16, slowk_matype=0, slowd_period=16, slowd_matype=0)
slowk_52_df, slowd_52_df = talib.STOCH(np_high, np_low, np_close, fastk_period=52, slowk_period=32, slowk_matype=0, slowd_period=32, slowd_matype=0)
# 최고/최저 위치
loc_240 = [None for i in range(len(close))]
for i in range(240, len(close)):
min_v = np.min(result["close"][i-239:i+1])
max_v = np.max(result["close"][i-239:i+1])
if close[i] is not None:
loc_240[i] = ((close[i] - min_v) / (max_v - min_v))
else:
loc_240[i] = None
loc_240 = pd.DataFrame(loc_240)
loc_240_k = loc_240.to_numpy().reshape(-1)
loc_240_d = loc_240.rolling(20).mean()
loc_240_s = loc_240.rolling(60).mean()
loc_240_d = loc_240_d.to_numpy().reshape(-1)
loc_240_s = loc_240_s.to_numpy().reshape(-1)
# 볼린저 밴드
n, t = 10, 2
max_10 = close_df.rolling(window=n).mean()
stddev_10 = close_df.rolling(window=n).std()
upper_10 = max_10 + (stddev_10 * t) # 상단 볼리저 밴드
lower_10 = max_10 - (stddev_10 * t) # 하단 볼리저 밴드
middle_10 = (upper_10 + lower_10) / 2
upper_10 = list(np.reshape(upper_10.values, -1))
lower_10 = list(np.reshape(lower_10.values, -1))
middle_10 = list(np.reshape(middle_10.values, -1))
n, t = 20, 2
max_20 = close_df.rolling(window=n).mean()
stddev_20 = close_df.rolling(window=n).std()
upper_20 = max_20 + (stddev_20 * t) # 상단 볼리저 밴드
lower_20 = max_20 - (stddev_20 * t) # 하단 볼리저 밴드
middle_20 = (upper_20 + lower_20) / 2
upper_20 = list(np.reshape(upper_20.values, -1))
lower_20 = list(np.reshape(lower_20.values, -1))
middle_20 = list(np.reshape(middle_20.values, -1))
duration = 1440
if mins == 1440:
duration = 360
laggingSpan_close_diff, laggingSpan_close_diff_rate = self.getDiff_Rate(laggingSpan, close, duration=duration)
laggingSpan_avg60_diff, laggingSpan_avg60_diff_rate = self.getDiff_Rate(laggingSpan, avg60, duration=duration)
leadingSpan1_leadingSpan2_diff, leadingSpan1_leadingSpan2_diff_rate = self.getDiff_Rate(leadingSpan1, leadingSpan2, duration=duration)
df_list = [
pd.DataFrame(ymd),
pd.DataFrame(open), pd.DataFrame(close), pd.DataFrame(high), pd.DataFrame(low), pd.DataFrame(volume),
pd.DataFrame(changeLine), pd.DataFrame(baseLine), pd.DataFrame(laggingSpan), pd.DataFrame(leadingSpan1), pd.DataFrame(leadingSpan2),
pd.DataFrame(laggingSpan_close_diff),
pd.DataFrame(laggingSpan_avg60_diff),
pd.DataFrame(leadingSpan1_leadingSpan2_diff),
pd.DataFrame(laggingSpan_close_diff_rate),
pd.DataFrame(laggingSpan_avg60_diff_rate),
pd.DataFrame(leadingSpan1_leadingSpan2_diff_rate),
pd.DataFrame(loc_240_k), pd.DataFrame(loc_240_d), pd.DataFrame(loc_240_s),
pd.DataFrame(avg5), pd.DataFrame(avg10), pd.DataFrame(avg20), pd.DataFrame(avg60), pd.DataFrame(avg90), pd.DataFrame(avg120), pd.DataFrame(avg240), pd.DataFrame(avg360), pd.DataFrame(avg480), pd.DataFrame(avg720), pd.DataFrame(avg1440), pd.DataFrame(avg2880),
pd.DataFrame(upper_10), pd.DataFrame(lower_10), pd.DataFrame(middle_10),
pd.DataFrame(upper_20), pd.DataFrame(lower_20), pd.DataFrame(middle_20),
pd.DataFrame(new_high_9), pd.DataFrame(new_high_26),
pd.DataFrame(new_low_9), pd.DataFrame(new_low_26),
pd.DataFrame(slowk_12_df), pd.DataFrame(slowd_12_df),
pd.DataFrame(slowk_26_df), pd.DataFrame(slowd_26_df),
pd.DataFrame(slowk_52_df), pd.DataFrame(slowd_52_df),
]
data = pd.concat(df_list, axis=1)
column_names = [
'ymd',
'open', 'close', 'high', 'low', 'volume',
'changeLine', 'baseLine', 'laggingSpan', 'leadingSpan1', 'leadingSpan2',
'laggingSpan_close_diff',
'laggingSpan_avg60_diff',
'leadingSpan1_leadingSpan2_diff',
'laggingSpan_close_diff_rate',
'laggingSpan_avg60_diff_rate',
'leadingSpan1_leadingSpan2_diff_rate',
'loc_240_k', 'loc_240_d', 'loc_240_s',
'avg5', 'avg10', 'avg20', 'avg60', 'avg90', 'avg120', 'avg240', 'avg360', 'avg480', 'avg720', 'avg1440', 'avg2880',
'upper_10', 'lower_10', 'middle_10',
'upper_20', 'lower_20', 'middle_20',
'new_high_9', 'new_high_26',
'new_low_9', 'new_low_26',
'slowk_12', 'slowd_12',
'slowk_26', 'slowd_26',
'slowk_52', 'slowd_52',
]
data.columns = column_names
data.index = pd.DatetimeIndex(ymd)
return data, current_index
def getData(self, ticker, ymd=None, get_days=14):
if ymd is None:
result = self.getCoinData(ticker, get_days=get_days)
else:
result = self.getCoinData(ticker, ymd=ymd, get_days=get_days)
if len(result['ymd']) < 1:
return None, None
#result_tic = self.makeTickData(result_m1, mins=minute)
data, current_index = self.analyze(result)
return data, current_index
if __name__ == "__main__":
def min_max_normalize(data):
min_val = min(data)
max_val = max(data)
normalized_data = [(x - min_val) / (max_val - min_val) for x in data]
return normalized_data
# 예시 데이터
original_data = [-4, -3, -2, -1, 0]
normalized_data = min_max_normalize(original_data)
print(np.asarray(normalized_data)-1)
original_data = [0, 2,4,6,8,10]
normalized_data = min_max_normalize(original_data)
print(normalized_data)

View File

@@ -121,7 +121,7 @@ class FnGuideCrawler:
item_code = item[1]
idx += 1
print(idx, item_code, item_name, 'http://comp.fnguide.com/SVO2/ASP/SVD_main.asp?pGB=1&gicode=A%s'%(item_code.strip()))
print("{}. {} ({}) {}".format(idx, item_code, item_name, 'http://comp.fnguide.com/SVO2/ASP/SVD_main.asp?pGB=1&gicode=A%s'%(item_code.strip())))
fnGuideData = self.get_fnguide_table(item_code)

View File

@@ -46,8 +46,8 @@ class MetaCrawler:
inputs.append({'NAME': 'RUB', 'CODE': 'FX_RUBKRW', 'URL': 'http://finance.naver.com/marketindex/exchangeDailyQuote.nhn?marketindexCd=FX_RUBKRW'}) # 러시아 RUB
inputs.append({'NAME': 'TWD', 'CODE': 'FX_TWDKRW', 'URL': 'http://finance.naver.com/marketindex/exchangeDailyQuote.nhn?marketindexCd=FX_TWDKRW'}) # 대만 TWD
for i in range(len(inputs)):
input = inputs[i]
for idx in range(len(inputs)):
input = inputs[idx]
NAME = input['NAME']
CODE = input['CODE']
@@ -100,7 +100,7 @@ class MetaCrawler:
finish = True
break
print(CODE, NAME, ymd)
print("{}. {} {} ({})".format(idx, ymd, CODE, NAME))
if finish:
break
@@ -191,7 +191,7 @@ class MetaCrawler:
finish = True
break
print ("20"+item[0])
print ("Trading_Trend 20{}".format(item[0]))
previousDay = html[0].values[2][0]
if finish:
break
@@ -271,7 +271,7 @@ class MetaCrawler:
finish = True
break
print("20"+item[0])
print("crawl_money_trend 20{}".format(item[0]))
if finish:
break
previousDay = html[0].values[2][0]
@@ -301,8 +301,8 @@ class MetaCrawler:
inputs.append({'NAME': '국고채(3년)', 'CODE': 'IRR_GOVT03Y', 'URL': 'http://finance.naver.com/marketindex/interestDailyQuote.nhn?marketindexCd=IRR_GOVT03Y'})
inputs.append({'NAME': '회사채(3년)', 'CODE': 'IRR_CORP03Y', 'URL': 'http://finance.naver.com/marketindex/interestDailyQuote.nhn?marketindexCd=IRR_CORP03Y'})
for i in range(len(inputs)):
input = inputs[i]
for idx in range(len(inputs)):
input = inputs[idx]
NAME = input['NAME']
CODE = input['CODE']
@@ -357,7 +357,7 @@ class MetaCrawler:
if finish:
break
print(NAME + " / " + ymd)
print("{} {}".format(ymd, NAME))
conn.commit()
cursor.close()
@@ -393,8 +393,8 @@ class MetaCrawler:
inputs.append({'NAME': 'PLATINUM', 'CODE': 'CMDT_PL','URL': 'http://finance.naver.com/marketindex/worldDailyQuote.nhn?marketindexCd=CMDT_PL&fdtc=2'}) # 국제 백금
inputs.append({'NAME': 'PALADIUM', 'CODE': 'CMDT_PA','URL': 'http://finance.naver.com/marketindex/worldDailyQuote.nhn?marketindexCd=CMDT_PA&fdtc=2'}) # 국제 팔라듐
for i in range(len(inputs)):
input = inputs[i]
for idx in range(len(inputs)):
input = inputs[idx]
NAME = input['NAME']
CODE = input['CODE']
@@ -444,7 +444,7 @@ class MetaCrawler:
finish = True
break
print(CODE, NAME, ymd)
print("{}. {} {} ({})".format(idx, ymd, CODE, NAME))
if finish:
break

View File

@@ -132,10 +132,7 @@ class StockCrawler:
stocks.append({"NAME": 'KODEX 은행', "CODE": "091170"})
stocks.append({"NAME": 'TIGER 탄소효율그린뉴딜', "CODE": "376410"})
start_time = time.time()
for i, stock in enumerate(stocks):
print (i, stock["NAME"], stock["CODE"], (time.time()-start_time), "s")
start_time = time.time()
cursor.execute('SELECT ymd FROM ' + tableName + ' WHERE CODE=? order by ymd desc', (stock["CODE"],))
result = cursor.fetchone()
ymd = self.START_DATE
@@ -153,6 +150,7 @@ class StockCrawler:
#else:
# cursor.execute("UPDATE " + tableName + " SET close=?, diff=?, open=?, high=?, low=?, volume=? WHERE CODE=? and ymd=?", (item['close'], item['diff'], item['open'], item['high'], item['low'], item['volume'], stock["CODE"], item['ymd']))
print("{}. {} ({})".format(i, stock["CODE"], stock["NAME"]))
sleep(0.5)
conn.commit()
cursor.close()
@@ -178,7 +176,6 @@ class StockCrawler:
code_df = self.getStockInfo()
items = code_df.values
start_time = time.time()
idx = 0
for item in items:
idx += 1
@@ -211,9 +208,7 @@ class StockCrawler:
conn.commit()
cursor.close()
conn.close()
print(idx, item_name, item_code, (time.time() - start_time), "s")
start_time = time.time()
print("{}. {} ({})".format(idx, item_code, item_name))
sleep(0.3)
return
@@ -234,8 +229,6 @@ class StockCrawler:
cursor.close()
conn.close()
start_time = time.time()
pd.options.display.float_format = '{:.4f}'.format
pd.set_option('display.max_columns', None)
@@ -372,9 +365,8 @@ class StockCrawler:
conn.commit()
cursor.close()
conn.close()
print(idx, item_code, special_stocks[item_code], (time.time() - start_time), "s")
start_time = time.time()
print("{}. {} ({})".format(idx, item_code, special_stocks[item_code]))
sleep(0.05)
return