Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -10,17 +10,13 @@ from stock.crawler.FnGuideCrawler import FnGuideCrawler
|
||||
from stock.crawler.MetaCrawler import MetaCrawler
|
||||
from stock.crawler.StockCrawler import StockCrawler
|
||||
from stock.analysis.AnalyzerSqlite import AnalyzerSqlite
|
||||
from stock.util.TelegramBot import TelegramBot
|
||||
|
||||
|
||||
class StockCrawlerDaily:
|
||||
|
||||
PROJECT_HOME = None
|
||||
bot = None
|
||||
|
||||
def __init__(self, PROJECT_HOME):
|
||||
self.PROJECT_HOME = PROJECT_HOME
|
||||
self.bot = TelegramBot()
|
||||
|
||||
return
|
||||
|
||||
@@ -136,11 +132,7 @@ class StockCrawlerDaily:
|
||||
shutil.rmtree(outPath)
|
||||
os.mkdir(outPath)
|
||||
|
||||
buy_stock_list = analyzerSqlite.findCandidates(outPath)
|
||||
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))
|
||||
analyzerSqlite.findCandidates(outPath)
|
||||
|
||||
return
|
||||
|
||||
|
||||
@@ -10,26 +10,50 @@ class BuySell_Daily:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def getBuyPrice(self, data, i, BS=None):
|
||||
def getBuyPrice(self, ticker, data, i, BS=None):
|
||||
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
|
||||
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_changeLine(data, i, BS)
|
||||
point = None
|
||||
for c in range(i-1, 0, -1):
|
||||
if data['close'][c] < data['changeLine'][c]:
|
||||
point = c
|
||||
break
|
||||
if point is not None:
|
||||
if 3 < sum([1 if 0 < BS['buy_price'][k] else 0 for k in range(point, i)]):
|
||||
return buy_ymd, 0, 0, '', None
|
||||
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_changeLine(ticker, data, i, BS)
|
||||
if 0 < tmp_buy_count:
|
||||
buy_ymd = tmp_buy_ymd; buy_price = tmp_buy_price; buy_count = tmp_buy_count; buy_type = tmp_buy_type; buy_cut = tmp_buy_cut
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_baseLine(data, i, BS)
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_baseLine(ticker, data, i, BS)
|
||||
if 0 < tmp_buy_count:
|
||||
buy_ymd = tmp_buy_ymd; buy_price = tmp_buy_price; buy_count = tmp_buy_count; buy_type = tmp_buy_type; buy_cut = tmp_buy_cut
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_laggingSpan(data, i, BS)
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_laggingSpan(ticker, data, i, BS)
|
||||
if 0 < tmp_buy_count:
|
||||
buy_ymd = tmp_buy_ymd; buy_price = tmp_buy_price; buy_count = tmp_buy_count; buy_type = tmp_buy_type; buy_cut = tmp_buy_cut
|
||||
tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_ichimok_avg(ticker, data, i, BS)
|
||||
if 0 < tmp_buy_count:
|
||||
buy_ymd = tmp_buy_ymd; buy_price = tmp_buy_price; buy_count = tmp_buy_count; buy_type = tmp_buy_type; buy_cut = tmp_buy_cut
|
||||
|
||||
if 0 < len(ticker['BUY_INFO']['buy_list']):
|
||||
diff = (datetime.strptime(str(data['ymd'][i]), '%Y-%m-%d %H:%M:%S') - ticker['BUY_INFO']['buy_list'][-1]['buy_ymd'])
|
||||
d = diff.days
|
||||
s = diff.seconds
|
||||
|
||||
# 해당 종목에 대해서 1분 이내 매수 금지
|
||||
if s < 3 * 60:
|
||||
return buy_ymd, 0, 0, '', None
|
||||
|
||||
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
|
||||
|
||||
def getSellPrice(self, data, i, BS=None):
|
||||
def getSellPrice(self, ticker, data, i, BS=None):
|
||||
sell_price, sell_count, sell_type = 0, 1, ''
|
||||
sell_type_list = []
|
||||
|
||||
tmp_sell_price, tmp_sell_type_list = self.getSellPrice_ichimok_baseLine(data, i, BS)
|
||||
tmp_sell_price, tmp_sell_type_list = self.getSellPrice_ichimok_baseLine(ticker, data, i, BS)
|
||||
sell_type_list += tmp_sell_type_list
|
||||
|
||||
tmp_sell_price, tmp_sell_type_list = self.getSellPrice_candle(ticker, data, i, BS)
|
||||
sell_type_list += tmp_sell_type_list
|
||||
|
||||
sell_price = tmp_sell_price
|
||||
@@ -39,7 +63,7 @@ class BuySell_Daily:
|
||||
|
||||
return sell_price, sell_count, sell_type
|
||||
|
||||
def getBuyPrice_ichimok_changeLine(self, data, i, BS=None):
|
||||
def getBuyPrice_ichimok_changeLine(self, ticker, data, i, BS=None):
|
||||
|
||||
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
|
||||
|
||||
@@ -81,8 +105,8 @@ class BuySell_Daily:
|
||||
|
||||
if check:
|
||||
buy_ymd = data['ymd'][i]
|
||||
buy_price = data['close'][i]
|
||||
buy_count = buy_weight
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
|
||||
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
|
||||
|
||||
@@ -90,7 +114,7 @@ class BuySell_Daily:
|
||||
""""""""""""""""""
|
||||
""""""""""""""""""
|
||||
|
||||
def getBuyPrice_ichimok_baseLine(self, data, i, BS=None):
|
||||
def getBuyPrice_ichimok_baseLine(self, ticker, data, i, BS=None):
|
||||
|
||||
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
|
||||
|
||||
@@ -120,15 +144,15 @@ class BuySell_Daily:
|
||||
|
||||
if check:
|
||||
buy_ymd = data['ymd'][i]
|
||||
buy_price = data['close'][i]
|
||||
buy_count = buy_weight
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
|
||||
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
|
||||
|
||||
""""""""""""""""""
|
||||
""""""""""""""""""
|
||||
|
||||
def getBuyPrice_ichimok_laggingSpan(self, data, i, BS):
|
||||
def getBuyPrice_ichimok_laggingSpan(self, ticker, data, i, BS):
|
||||
|
||||
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
|
||||
|
||||
@@ -138,28 +162,29 @@ class BuySell_Daily:
|
||||
|
||||
if data['laggingSpan_close_diff_rate'][i-1] <= 0 and 0 < data['laggingSpan_close_diff_rate'][i]:
|
||||
check = True
|
||||
buy_price = data['close'][i]
|
||||
buy_count = buy_weight
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
buy_weight = 2
|
||||
buy_type = 'laggingSpan1'
|
||||
|
||||
if 0 <= data['laggingSpan_avg60_diff_rate'][i-1] and data['laggingSpan_avg60_diff_rate'][i] < 0:
|
||||
check = True
|
||||
buy_price = data['close'][i]
|
||||
buy_count = buy_weight
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
buy_weight = 2
|
||||
buy_type = 'laggingSpan2'
|
||||
|
||||
if check:
|
||||
buy_price = data['close'][i]
|
||||
buy_count = buy_weight
|
||||
buy_ymd = data['ymd'][i]
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
|
||||
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
|
||||
|
||||
""""""""""""""""""
|
||||
""""""""""""""""""
|
||||
|
||||
def getSellPrice_ichimok_baseLine(self, data, i, BS=None):
|
||||
def getSellPrice_ichimok_baseLine(self, ticker, data, i, BS=None):
|
||||
sell_price = 0
|
||||
sell_type_list = []
|
||||
|
||||
@@ -173,6 +198,61 @@ class BuySell_Daily:
|
||||
sell_type_list.append('ichimok_baseLine')
|
||||
|
||||
if check:
|
||||
sell_price = data['close'][i]
|
||||
sell_price = data['close'][i] + 2 * ticker['unit']
|
||||
|
||||
return sell_price, sell_type_list
|
||||
|
||||
""""""""""""""""""
|
||||
""""""""""""""""""
|
||||
|
||||
def getBuyPrice_ichimok_avg(self, ticker, data, i, BS):
|
||||
|
||||
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
|
||||
|
||||
check = False
|
||||
|
||||
if 5 < i:
|
||||
|
||||
if data['avg5'][i] < data['avg20'][i] < data['baseLine'][i] < data['changeLine'][i] < data['close'][i]:
|
||||
if data['avg5'][i-1]<data['avg5'][i] and data['avg20'][i-1]<data['avg20'][i] and data['baseLine'][i-1]<=data['baseLine'][i] and data['changeLine'][i-1]<data['changeLine'][i]:
|
||||
check = True
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
buy_weight = 2
|
||||
buy_type = 'ichimok_avg1'
|
||||
|
||||
if data['avg20'][i] < data['baseLine'][i] < data['changeLine'][i] < data['avg5'][i] < data['close'][i]:
|
||||
if data['avg20'][i-1]<data['avg20'][i] and data['baseLine'][i]<data['baseLine'][i-1] and data['changeLine'][i-1]<data['changeLine'][i] and data['avg5'][i-1]<data['avg5'][i]:
|
||||
check = True
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
buy_weight = 2
|
||||
buy_type = 'ichimok_avg2'
|
||||
|
||||
if check:
|
||||
buy_ymd = data['ymd'][i]
|
||||
buy_price = data['close'][i] - 2 * ticker['unit']
|
||||
buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
|
||||
|
||||
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
|
||||
|
||||
|
||||
""""""""""""""""""
|
||||
""""""""""""""""""
|
||||
|
||||
def getSellPrice_candle(self, ticker, data, i, BS=None):
|
||||
sell_price = 0
|
||||
sell_type_list = []
|
||||
|
||||
check = False
|
||||
|
||||
high = max(data['close'][i], data['open'][i])
|
||||
low = min(data['close'][i], data['open'][i])
|
||||
if low - data['low'][i] < data['high'][i] - high:
|
||||
check = True
|
||||
sell_type_list.append('candle_tail')
|
||||
|
||||
if check:
|
||||
sell_price = data['close'][i] + 2 * ticker['unit']
|
||||
|
||||
return sell_price, sell_type_list
|
||||
@@ -22,3 +22,4 @@ pybithumb
|
||||
ccxt
|
||||
slack-sdk
|
||||
scikit-learn
|
||||
python-telegram-bot
|
||||
@@ -22,6 +22,7 @@ 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
|
||||
@@ -29,6 +30,8 @@ class AnalyzerSqlite:
|
||||
topCompany = None
|
||||
fnguide = None
|
||||
|
||||
bot = None
|
||||
|
||||
common = None
|
||||
stockFileName = None
|
||||
analyzedFileName = None
|
||||
@@ -45,6 +48,8 @@ class AnalyzerSqlite:
|
||||
self.topCompany = self.getTopCompany(self.stockFileName, 2000)
|
||||
self.fnguide = self.readFnguide(self.stockFileName)
|
||||
|
||||
self.bot = TelegramBot()
|
||||
|
||||
return
|
||||
|
||||
def getTopCompany(self, fnguideFileName, top):
|
||||
@@ -522,8 +527,8 @@ class AnalyzerSqlite:
|
||||
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)
|
||||
#fileName = "%s/summary.html" % (self.outPath)
|
||||
#po.write_html(fig, file=fileName, auto_open=False)
|
||||
|
||||
return
|
||||
|
||||
@@ -580,7 +585,6 @@ class AnalyzerSqlite:
|
||||
return
|
||||
|
||||
def checkTransaction(self, ticker, data, ci):
|
||||
|
||||
# 어제 오늘 데이터로 분석
|
||||
bsLine = {}
|
||||
|
||||
@@ -601,14 +605,14 @@ class AnalyzerSqlite:
|
||||
for i in range(start, size):
|
||||
|
||||
# 매도 확인
|
||||
sell_price, sell_count, sell_type = self.buySell_Daily.getSellPrice(data, i, bsLine)
|
||||
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(data, i, bsLine)
|
||||
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
|
||||
@@ -640,11 +644,12 @@ class AnalyzerSqlite:
|
||||
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)
|
||||
CODE = item[0]
|
||||
|
||||
stock_daily, ci = self.getStockData(CODE)
|
||||
|
||||
bsLine = self.checkTransaction(CODE, stock_daily, ci)
|
||||
bsLine = self.checkTransaction(ticker, stock_daily, ci)
|
||||
|
||||
if bsLine['buy_ymd'][ci-1] is not None:
|
||||
top = "0"
|
||||
@@ -658,7 +663,12 @@ class AnalyzerSqlite:
|
||||
self.writeFile(outPath, CODE, NAME, top, stock_daily, bsLine)
|
||||
buy_stock_list.append({'CODE': CODE, 'NAME': NAME})
|
||||
|
||||
return buy_stock_list
|
||||
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__":
|
||||
@@ -667,7 +677,7 @@ if __name__ == "__main__":
|
||||
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')
|
||||
analyzer = AnalyzerSqlite(RESOURCE_PATH)
|
||||
analyzerSqlite = AnalyzerSqlite(RESOURCE_PATH)
|
||||
|
||||
|
||||
# HTML 출력
|
||||
@@ -688,8 +698,8 @@ if __name__ == "__main__":
|
||||
shutil.rmtree(outPath)
|
||||
os.mkdir(outPath)
|
||||
print("print to Html...")
|
||||
analyzer.findCandidates(outPath)
|
||||
|
||||
analyzerSqlite.findCandidates(outPath)
|
||||
|
||||
print("time : %6.2f 초" % (time.time() - start))
|
||||
print("done...")
|
||||
|
||||
@@ -23,7 +23,7 @@ class JSDPattern_simulation (JSDPattern):
|
||||
super().__init__(RESOURCE_PATH)
|
||||
return
|
||||
|
||||
def analyze(self, result, mins=1):
|
||||
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"])
|
||||
|
||||
Reference in New Issue
Block a user