diff --git a/HTS_etf.py b/HTS_etf.py
index 62d3bba..b3c0dcd 100644
--- a/HTS_etf.py
+++ b/HTS_etf.py
@@ -16,7 +16,6 @@ from stock.analysis.Stochastic import Stochastic
from stock.analysis.RSI import RSI
from stock.analysis.MACD import MACD
from stock.analysis.IchimokuCloud import IchimokuCloud
-from statsmodels.tsa.seasonal import seasonal_decompose
from hts.BuySellChecker import BuySellChecker
from stock.analysis.MovingAverage import MovingAverage
diff --git a/JSDPattern.py b/JSDPattern.py
index 95082a0..284f852 100644
--- a/JSDPattern.py
+++ b/JSDPattern.py
@@ -88,26 +88,9 @@ class JSDPattern:
return data
- def getDBData(self, stock_code, day, mins, get_days=14):
+ def getDBData(self, stock_code, day, 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'
+ table = 'stock'
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, 'coins.db'))
cursor = conn.cursor()
@@ -142,35 +125,8 @@ class JSDPattern:
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)
+ result = self.getDBData(ticker['ticker_code'], ymd, mins=mins, get_days=get_days)
+ data = self.append(df=None, result=result)
return data
diff --git a/Simulation_daily.py b/Simulation_daily.py
new file mode 100644
index 0000000..9986fa5
--- /dev/null
+++ b/Simulation_daily.py
@@ -0,0 +1,437 @@
+from math import nan
+import pandas as pd
+import plotly.graph_objects as go
+from plotly import subplots
+import math
+
+import os
+import json
+
+from datetime import datetime, timedelta
+
+from hts.BuySell_Daily import BuySell_Daily
+from JSDPattern_daily import JSDPattern_daily
+
+
+class Simulation_daily:
+
+ upbit = None
+
+ def __init__(self, RESOURCE_PATH):
+
+ self.buySell_Daily = BuySell_Daily()
+ self.jSDPattern = JSDPattern_daily(RESOURCE_PATH)
+
+ return
+
+ 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, data_scaled, bsLine=None, show=False, info=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'].iloc[i] > data['close'].iloc[i]:
+ volume_colors.append("#FF0000")
+ elif data['open'].iloc[i] < data['close'].iloc[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)):
+ buy_text_list.append(
+ "[{}] {:,}
"
+ "{}, {:,} ({:,.2f})
"
+ "[BASIC]
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, poly_60: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}
"
+ "[INFO]
"
+ " new_high_7: {:,.2f}, new_high_9: {:,.2f}, new_high_26: {:,.2f}, new_low_7: {:,.2f}, new_low_9: {:,.2f}, new_low_26: {:,.2f}
"
+ .format(data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'), data["close"].iloc[i],
+ buy_type[i], buy_price_line[i], buy_price_line[i] * buy_count_line[i],
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i],
+ data['new_high_7'].iloc[i], data['new_high_9'].iloc[i], data['new_high_26'].iloc[i], data['new_low_7'].iloc[i], data['new_low_9'].iloc[i], data['new_low_26'].iloc[i],
+ ))
+ sell_text_list.append(
+ "[{}] {:,}
"
+ "{}, {:,} ({:,.2f})
"
+ "[BASIC]
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, poly_60: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}
"
+ "[INFO]
"
+ " new_high_7: {:,.2f}, new_high_9: {:,.2f}, new_high_26: {:,.2f}, new_low_7: {:,.2f}, new_low_9: {:,.2f}, new_low_26: {:,.2f}
"
+ .format(
+ data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'), data["close"].iloc[i],
+ sell_type[i], sell_price_line[i], sell_price_line[i] * sell_count_line[i],
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i],
+ data['new_high_7'].iloc[i], data['new_high_9'].iloc[i], data['new_high_26'].iloc[i], data['new_low_7'].iloc[i], data['new_low_9'].iloc[i], data['new_low_26'].iloc[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')
+
+ disparity_avg5 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg5"], name="disparity_avg5", line_color='#079118')
+ disparity_avg20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg20"], name="disparity_avg20", line_color='grey')
+ disparity_avg60 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg60"], name="disparity_avg60", line_color='#d755e8')
+ disparity_avg120 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg120"], name="disparity_avg120", line_color='#099B92')
+ disparity_avg240 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg240"], name="disparity_avg240", line_color='#2a9c0c')
+ disparity_avg480 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg480"], name="disparity_avg480", line_color='#079118')
+ disparity_avg1440 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_avg1440"], name="disparity_avg1440", line_color='#e68456')
+ disparity_480_loc = go.Scatter(x=data['ymd'], y=data_scaled["disparity_480_loc"], name="disparity_480_loc", line_color='#2a9c0c')
+ disparity_1440_loc = go.Scatter(x=data['ymd'], y=data_scaled["disparity_1440_loc"], name="disparity_1440_loc", line_color='#2a9c0c')
+
+
+ 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_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')
+ bb_pb = go.Scatter(x=data['ymd'], y=data["bb_pb"], name="bb_pb", line_color='#0196ff')
+ bb_width = go.Scatter(x=data['ymd'], y=data["bb_width"], name="bb_width", line_color='#991515')
+
+ 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_high_33 = go.Scatter(x=data['ymd'], y=data["new_high_33"], name="new_high_33", line_color='#12A524')
+ new_high_52 = go.Scatter(x=data['ymd'], y=data["new_high_52"], name="new_high_52", line_color='#099B92')
+ 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')
+ new_low_33 = go.Scatter(x=data['ymd'], y=data["new_low_33"], name="new_low_33", line_color='#12A524')
+ new_low_52 = go.Scatter(x=data['ymd'], y=data["new_low_52"], name="new_low_52", line_color='#099B92')
+
+ poly_5 = go.Scatter(x=data['ymd'], y=data_scaled["poly_5"], name="poly_5", line_color='#D27144')
+ poly_10 = go.Scatter(x=data['ymd'], y=data_scaled["poly_10"], name="poly_10", line_color='#BBBEC3')
+ poly_20 = go.Scatter(x=data['ymd'], y=data_scaled["poly_20"], name="poly_20", line_color='#d755e8')
+ poly_60 = go.Scatter(x=data['ymd'], y=data_scaled["poly_60"], name="poly_60", line_color='#099B92')
+ poly_120 = go.Scatter(x=data['ymd'], y=data_scaled["poly_120"], name="poly_120", line_color='#e68456')
+ poly_240 = go.Scatter(x=data['ymd'], y=data_scaled["poly_240"], name="poly_240", line_color='#E8DD26')
+ poly_480 = go.Scatter(x=data['ymd'], y=data_scaled["poly_480"], name="poly_480", line_color='#EF3644')
+
+ disparity_diff_20_5 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_20_5"], name="disparity_diff_20_5", line_color='#D27144')
+ disparity_diff_60_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_60_20"], name="disparity_diff_60_20", line_color='#BBBEC3')
+ disparity_diff_120_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_120_20"], name="disparity_diff_120_20", line_color='#d755e8')
+ disparity_diff_240_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_240_20"], name="disparity_diff_240_20", line_color='#099B92')
+ disparity_diff_480_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_480_20"], name="disparity_diff_480_20", line_color='#e68456')
+ disparity_diff_1440_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_1440_20"], name="disparity_diff_1440_20", line_color='#0196ff')
+
+ disparity_diff_20_5_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_20_5_rate"], name="disparity_diff_20_5_rate", line_color='#D27144')
+ disparity_diff_60_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_60_20_rate"], name="disparity_diff_60_20_rate", line_color='#BBBEC3')
+ disparity_diff_120_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_120_20_rate"], name="disparity_diff_120_20_rate", line_color='#d755e8')
+ disparity_diff_240_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_240_20_rate"], name="disparity_diff_240_20_rate", line_color='#099B92')
+ disparity_diff_480_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_480_20_rate"], name="disparity_diff_480_20_rate", line_color='#e68456')
+ disparity_diff_1440_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_1440_20_rate"], name="disparity_diff_1440_20_rate", line_color='#0196ff')
+
+ 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_5 = go.Scatter(x=data['ymd'], y=data["slowk_5"], line=dict(color='#D27144', width=2), name='slowk_5')
+ slowd_5 = go.Scatter(x=data['ymd'], y=data["slowd_5"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_5')
+ slowk_10 = go.Scatter(x=data['ymd'], y=data["slowk_10"], line=dict(color='#BBBEC3', width=2), name='slowk_10')
+ slowd_10 = go.Scatter(x=data['ymd'], y=data["slowd_10"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_10')
+ slowk_20 = go.Scatter(x=data['ymd'], y=data["slowk_20"], line=dict(color='#d755e8', width=2), name='slowk_20')
+ slowd_20 = go.Scatter(x=data['ymd'], y=data["slowd_20"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_20')
+ slowk_60 = go.Scatter(x=data['ymd'], y=data["slowk_60"], line=dict(color='#099B92', width=2), name='slowk_60')
+ slowd_60 = go.Scatter(x=data['ymd'], y=data["slowd_60"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_60')
+ slowk_120 = go.Scatter(x=data['ymd'], y=data["slowk_120"], line=dict(color='#640745', width=2), name='slowk_120')
+ slowd_120 = go.Scatter(x=data['ymd'], y=data["slowd_120"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_120')
+ slowk_240 = go.Scatter(x=data['ymd'], y=data["slowk_240"], line=dict(color='#e68456', width=2), name='slowk_240')
+ slowd_240 = go.Scatter(x=data['ymd'], y=data["slowd_240"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_240')
+ slowk_480 = go.Scatter(x=data['ymd'], y=data["slowk_480"], line=dict(color='#E8DD26', width=2), name='slowk_480')
+ slowd_480 = go.Scatter(x=data['ymd'], y=data["slowd_480"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_480')
+
+ min_price = go.Scatter(x=data['ymd'], y=data["min_price"], name="min_price", line_color='#0196ff')
+ max_price = go.Scatter(x=data['ymd'], y=data["max_price"], name="max_price", line_color='#991515')
+
+ text_list = []
+ for i in range(len(data['ymd'])):
+ text_list.append(
+ "{}
"
+ " o: {}, c: {}, h: {}, l: {}
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, poly_60: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}
"
+ " new_high_9: {}, new_high_26: {}
"
+ " avg5: {:.2f}, avg10: {:.2f}, avg20: {:.2f}, avg60: {:.2f}, avg90: {:.2f}, avg120: {:.2f}, avg240: {:.2f}
"
+ " avg360: {:.2f}, avg480: {:.2f}, avg720: {:.2f}, avg1440: {:.2f}, avg2880: {:.2f}
"
+ " loc_k: {:.2f}, loc_d: {:.2f}, loc_s: {:.2f}
"
+ .format(
+ data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'),
+ self.cz(data["open"].iloc[i]), self.cz(data["close"].iloc[i]), self.cz(data["high"].iloc[i]), self.cz(data["low"].iloc[i]),
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i],
+ data["new_high_9"].iloc[i], data["new_high_26"].iloc[i],
+ self.cz(data["avg5"].iloc[i]), self.cz(data["avg10"].iloc[i]), self.cz(data["avg20"].iloc[i]), self.cz(data["avg60"].iloc[i]), self.cz(data["avg90"].iloc[i]), self.cz(data["avg120"].iloc[i]), self.cz(data["avg240"].iloc[i]), self.cz(data["avg360"].iloc[i]), self.cz(data["avg480"].iloc[i]), self.cz(data["avg720"].iloc[i]), self.cz(data["avg1440"].iloc[i]), self.cz(data["avg2880"].iloc[i]),
+ self.cz(data['loc_240_k'].iloc[i]), self.cz(data['loc_240_d'].iloc[i]), self.cz(data['loc_240_s'].iloc[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, min_price, max_price, buy_check, sell_check, candle_stick, changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2, upper_20_Line, lower_20_Line, middle_20_line]
+ else:
+ candle_data = [avg5, avg10, avg20, avg60, avg90, avg120, avg240, avg360, avg480, avg720, avg1440, avg2880, min_price, max_price, candle_stick,changeLine, baseLine, laggingSpan, leadingSpan1, leadingSpan2]
+
+ volume_data = [volume_line]
+ disparity_data = [disparity_avg5, disparity_avg20, disparity_avg60, disparity_avg120, disparity_avg240, disparity_avg480, disparity_avg1440, disparity_480_loc, disparity_1440_loc, bb_width,
+ disparity_diff_20_5, disparity_diff_60_20, disparity_diff_120_20, disparity_diff_240_20, disparity_diff_480_20, disparity_diff_1440_20]
+ loc_disparity_data = [loc_240_k, loc_240_d, loc_240_s,
+ new_high_9 ,new_high_26, new_high_33, new_high_52,new_low_9 ,new_low_26, new_low_33, new_low_52,
+ poly_5, poly_10, poly_20, poly_60, poly_120, poly_240, poly_480,
+ disparity_diff_20_5_rate, disparity_diff_60_20_rate, disparity_diff_120_20_rate, disparity_diff_240_20_rate, disparity_diff_480_20_rate, disparity_diff_1440_20_rate
+ ]
+ stochastic_data = [
+ slowk_up_limit, slowk_middle_limit, slowk_down_limit,
+ 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,
+ bb_pb
+ ]
+ # 그래프를 그린다.
+ """
+ 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, 200, 700, 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 stochastic_data:
+ fig.append_trace(trace, 3, 1)
+ for trace in candle_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)
+
+ if info is not None:
+ buy_count, sell_count = 0, 0
+ if bsLine is not None:
+ buy_count = len(df.loc[df["buy_price"] > 0])
+ sell_count = len(df.loc[df["sell_price"] > 0])
+ fig.update_layout(height=1400,
+ title="{}, buy: {} ({:,.2f}원), sell: {} ({:,.2f}원), profit: {:,.2f}원 ({:.2f}%), holding_amt: {:.2f}".format(stock_code, buy_count, info['buy_amt'], sell_count, info['sell_amt'], info['profit'], info['rate'], info['holding_amt']),
+ xaxis_rangeslider_visible=False,
+ xaxis2_rangeslider_visible=False,
+ xaxis3_rangeslider_visible=False,
+ xaxis4_rangeslider_visible=False
+ )
+ else:
+ 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
+ )
+ #fig.update_layout(title=stock_code + "_" + str(buy_count) + "," + str(sell_count))
+ # 파일로 작성함
+ ###fileName = os.path.join(self.RESOURCE_PATH, 'analysis', stock_code + '.html')
+ ###po.write_html(fig, file=fileName, auto_open=False)
+
+ # 화면으로 출력함
+ if show:
+ fig.show()
+
+ return
+
+
+ def checkTransaction(self, ticker, data, data_scaled, 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, data_scaled, 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, data_scaled, 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 simulate(self, ticker, get_days=720):
+
+ data, data_scaled, ci = self.jSDPattern.getData(ticker, mins=720, ymd=ticker['ymd'], get_days=get_days)
+ if data is None:
+ return
+
+ with open("config.json", "r", encoding="utf-8") as f:
+ config = json.load(f)
+ BUY_INFO = config['BUY_INFO']
+ ticker['BUY_INFO'] = BUY_INFO
+ ticker['INIT'] = True
+ ticker['unit'] = self.upbit.checkUnit(data['close'].iloc[-1])
+ ticker['MAX_BUY'] = self.upbit.getMaxPrice(data['close'].iloc[-1])
+
+ bsLine = self.checkTransaction(ticker, data, data_scaled, ci)
+
+ self.draw(ticker['ticker_code'], data, data_scaled, bsLine, show=True, info=None)
+
+ if bsLine['buy_ymd'][ci-1] is not None:
+ return True
+
+ return False
+
+
+if __name__ == "__main__":
+
+ PROJECT_HOME = os.getcwd()
+ RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
+
+ # 1000원 이하: 0.1
+ # 1000원 이상: 1
+ # 1만원 이상 10
+ # 10만원 이상: 50
+ # 100만원 이상: 1000
+ #day_list = [(datetime.now()+timedelta(days=1)).strftime('%Y%m%d')]
+
+ """
+ all_tickers = pyupbit.get_tickers("KRW")
+ tickers = []
+ for ticker in all_tickers:
+ #tickers.append({'ticker_code': ticker, 'ticker_name': '', 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')},)
+ tickers.append({'ticker_code': ticker, 'ticker_name': '', 'BUY_INFO': {}, 'ymd': '20240418'},)
+
+ TODAY_BUY_ticket_list = []
+ for ticker in tickers:
+ simulation = Simulation_daily(RESOURCE_PATH)
+ buy = simulation.simulate(ticker, get_days=1500)
+ if buy:
+ TODAY_BUY_ticket_list.append(ticker)
+
+ print ('TODAY: {}개\n{}'.format (len(TODAY_BUY_ticket_list), TODAY_BUY_ticket_list))
+
+ """
+ simulation = Simulation_daily(RESOURCE_PATH)
+ tickers = [
+ {"ticker_code": "252670", "ticker_name": "KODEX 200선물인버스2X", 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')},
+ {"ticker_code": "122630", "ticker_name": "KODEX 레버리지", 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')},
+ {"ticker_code": "251340", "ticker_name": "KODEX 코스닥150선물인버스", 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')},
+ {"ticker_code": "233740", "ticker_name": "KODEX 코스닥150레버리지", 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')}
+ ]
+ for ticker in tickers:
+ simulation.simulate(ticker, get_days=1500)
+
+
+ print ("done...")
diff --git a/Simulation_minutely.py b/Simulation_minutely.py
new file mode 100644
index 0000000..d1f8430
--- /dev/null
+++ b/Simulation_minutely.py
@@ -0,0 +1,571 @@
+import numpy as np
+from math import nan
+import pandas as pd
+import plotly.graph_objects as go
+from plotly import subplots
+import math
+
+import os
+import json
+
+from datetime import datetime, timedelta
+from Upbit import Upbit
+
+from hts.BuySell_Minutely import BuySell_Minutely
+from JSDPattern_minutely import JSDPattern_minutely
+
+class Simulation_minutely:
+
+ test = None
+ upbit = None
+ buySell_Minutely = None
+
+ def __init__(self, RESOURCE_PATH):
+
+ self.test = []
+ self.upbit = Upbit(RESOURCE_PATH)
+ self.buySell_Minutely = BuySell_Minutely(RESOURCE_PATH)
+ self.jSDPattern = JSDPattern_minutely(RESOURCE_PATH)
+
+ return
+
+ 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_amount"] = 0
+
+ BUY_LIST['buy_list'].clear()
+ else:
+ BUY_LIST['avg_buy_price'] = 0
+ BUY_LIST['buy_count'] = 0
+ BUY_LIST["buy_amount"] = 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, ticker, data, data_scaled, bsLine=None, show=False, info=None):
+ stock_code = ticker['ticker_code']
+
+ # 어제 데이터는 지운다.
+ #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'].iloc[i] > data['close'].iloc[i]:
+ volume_colors.append("#FF0000")
+ elif data['open'].iloc[i] < data['close'].iloc[i]:
+ volume_colors.append("#FF0000")
+ else:
+ volume_colors.append("#000000")
+
+ # 그래프를 설정한다.
+ buy_check, sell_check = None, None
+ if bsLine is not None:
+ buy_text_list, sell_text_list = [], []
+ for i in range(len(data)):
+ buy_text_list.append(
+ "[{}] {:,}
"
+ "{}, {:,} ({:,.2f})
"
+ "[BASIC]
"
+ " support: {:.2f}, resistance: {:.2f}
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, 6: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}, poly_720: {:.5f}, poly_1440: {:.5f}
"
+ "[INFO]
"
+ " new_high_7: {:,.2f}, new_high_9: {:,.2f}, new_high_26: {:,.2f}, new_low_7: {:,.2f}, new_low_9: {:,.2f}, new_low_26: {:,.2f}
"
+ .format(data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'), data["close"].iloc[i],
+ buy_type[i], buy_price_line[i], buy_price_line[i]*buy_count_line[i],
+ data['support'].iloc[i], data['resistance'].iloc[i],
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i], data_scaled['poly_720'].iloc[i], data_scaled['poly_1440'].iloc[i],
+ data['new_high_7'].iloc[i], data['new_high_9'].iloc[i], data['new_high_26'].iloc[i], data['new_low_7'].iloc[i], data['new_low_9'].iloc[i], data['new_low_26'].iloc[i],
+ ))
+ sell_text_list.append(
+ "[{}] {:,}
"
+ "{}, {:,} ({:,.2f})
"
+ "[BASIC]
"
+ " support: {:.2f}, resistance: {:.2f}
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, 6: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}, poly_720: {:.5f}, poly_1440: {:.5f}
"
+ "[INFO]
"
+ " new_high_7: {:,.2f}, new_high_9: {:,.2f}, new_high_26: {:,.2f}, new_low_7: {:,.2f}, new_low_9: {:,.2f}, new_low_26: {:,.2f}
"
+ .format(
+ data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'), data["close"].iloc[i],
+ sell_type[i], sell_price_line[i], sell_price_line[i]*sell_count_line[i],
+ data['support'].iloc[i], data['resistance'].iloc[i],
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i], data_scaled['poly_720'].iloc[i], data_scaled['poly_1440'].iloc[i],
+ data['new_high_7'].iloc[i], data['new_high_9'].iloc[i], data['new_high_26'].iloc[i], data['new_low_7'].iloc[i], data['new_low_9'].iloc[i], data['new_low_26'].iloc[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='#D27144')
+ avg10 = go.Scatter(x=data['ymd'], y=data["avg10"], name="avg10", line_color='#BBBEC3')
+ 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')
+ avg120 = go.Scatter(x=data['ymd'], y=data["avg120"], name="avg120", line_color='#640745')
+ avg240 = go.Scatter(x=data['ymd'], y=data["avg240"], name="avg240", line_color='#e68456')
+ avg480 = go.Scatter(x=data['ymd'], y=data["avg480"], name="avg480", line_color='#A18A0D')
+ avg720 = go.Scatter(x=data['ymd'], y=data["avg720"], name="avg720", line_color='#EF3644')
+ avg1440 = go.Scatter(x=data['ymd'], y=data["avg1440"], name="avg1440", line_color='#4479D2')
+
+ poly_5 = go.Scatter(x=data['ymd'], y=data_scaled["poly_5"], name="poly_5", line_color='#D27144')
+ poly_10 = go.Scatter(x=data['ymd'], y=data_scaled["poly_10"], name="poly_10", line_color='#BBBEC3')
+ poly_20 = go.Scatter(x=data['ymd'], y=data_scaled["poly_20"], name="poly_20", line_color='#d755e8')
+ poly_60 = go.Scatter(x=data['ymd'], y=data_scaled["poly_60"], name="poly_60", line_color='#099B92')
+ poly_120 = go.Scatter(x=data['ymd'], y=data_scaled["poly_120"], name="poly_120", line_color='#e68456')
+ poly_240 = go.Scatter(x=data['ymd'], y=data_scaled["poly_240"], name="poly_240", line_color='#A18A0D')
+ poly_480 = go.Scatter(x=data['ymd'], y=data_scaled["poly_480"], name="poly_480", line_color='#0196ff')
+ poly_720 = go.Scatter(x=data['ymd'], y=data_scaled["poly_720"], name="poly_720", line_color='#EF3644')
+ poly_1440 = go.Scatter(x=data['ymd'], y=data_scaled["poly_1440"], name="poly_1440", line_color='#4479D2')
+
+ disparity_diff_20_5 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_20_5"], name="disparity_diff_20_5", line_color='#D27144')
+ disparity_diff_60_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_60_20"], name="disparity_diff_60_20", line_color='#BBBEC3')
+ disparity_diff_120_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_120_20"], name="disparity_diff_120_20", line_color='#d755e8')
+ disparity_diff_240_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_240_20"], name="disparity_diff_240_20", line_color='#099B92')
+ disparity_diff_480_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_480_20"], name="disparity_diff_480_20", line_color='#e68456')
+ disparity_diff_720_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_720_20"], name="disparity_diff_720_20", line_color='#A18A0D')
+ disparity_diff_1440_20 = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_1440_20"], name="disparity_diff_1440_20", line_color='#0196ff')
+
+ disparity_diff_20_5_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_20_5_rate"], name="disparity_diff_20_5_rate", line_color='#D27144')
+ disparity_diff_60_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_60_20_rate"], name="disparity_diff_60_20_rate", line_color='#BBBEC3')
+ disparity_diff_120_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_120_20_rate"], name="disparity_diff_120_20_rate", line_color='#d755e8')
+ disparity_diff_240_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_240_20_rate"], name="disparity_diff_240_20_rate", line_color='#099B92')
+ disparity_diff_480_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_480_20_rate"], name="disparity_diff_480_20_rate", line_color='#e68456')
+ disparity_diff_720_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_720_20_rate"], name="disparity_diff_720_20_rate", line_color='#A18A0D')
+ disparity_diff_1440_20_rate = go.Scatter(x=data['ymd'], y=data_scaled["disparity_diff_1440_20_rate"], name="disparity_diff_1440_20_rate", line_color='#0196ff')
+
+ new_high_7 = go.Scatter(x=data['ymd'], y=data["new_high_7"], name="new_high_7", line_color='#EA62A2')
+ 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_7 = go.Scatter(x=data['ymd'], y=data["new_low_7"], name="new_low_7", line_color='#EA62A2')
+ 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')
+
+ info_p_up_limit = [0.8 for i in data['ymd']]
+ info_p_middle_limit = [0.5 for i in data['ymd']]
+ info_p_down_limit = [0.2 for i in data['ymd']]
+ info_n_up_limit = [0.5 for i in data['ymd']]
+ info_n_middle_limit = [0 for i in data['ymd']]
+ info_n_down_limit = [-0.5 for i in data['ymd']]
+ info_p_up_limit = go.Scatter(x=data['ymd'], y=info_p_up_limit, line=dict(color='grey', width=1), name='info_p_up_limit')
+ info_p_middle_limit = go.Scatter(x=data['ymd'], y=info_p_middle_limit, line=dict(color='grey', width=1), name='info_p_middle_limit')
+ info_p_down_limit = go.Scatter(x=data['ymd'], y=info_p_down_limit, line=dict(color='grey', width=1), name='info_p_down_limit')
+ info_n_up_limit = go.Scatter(x=data['ymd'], y=info_n_up_limit, line=dict(color='grey', width=1), name='info_n_up_limit')
+ info_n_middle_limit = go.Scatter(x=data['ymd'], y=info_n_middle_limit, line=dict(color='grey', width=1), name='info_n_middle_limit')
+ info_n_down_limit = go.Scatter(x=data['ymd'], y=info_n_down_limit, line=dict(color='grey', width=1), name='info_n_down_limit')
+
+ rsi = go.Scatter(x=data['ymd'], y=data_scaled["rsi"], line=dict(color='#239507', width=2), name='rsi')
+ rsi_720 = go.Scatter(x=data['ymd'], y=data_scaled["rsi_720"], line=dict(color='#239507', width=2), name='rsi_720')
+ rsi_1440 = go.Scatter(x=data['ymd'], y=data_scaled["rsi_1440"], line=dict(color='#239507', width=2), name='rsi_1440')
+
+ macd = go.Scatter(x=data['ymd'], y=data_scaled["macd"], line=dict(color='#079118', width=2), name='macd')
+ macds = go.Scatter(x=data['ymd'], y=data_scaled["macds"], line=dict(dash='dashdot', color='#991515', width=2), name='macds')
+ macdo = go.Bar(x=data['ymd'], y=data_scaled["macdo"], marker_color='#7343e8', name='macdo')
+ macd_720 = go.Scatter(x=data['ymd'], y=data_scaled["macd_720"], line=dict(color='#079118', width=2), name='macd_720')
+ macd_1440 = go.Scatter(x=data['ymd'], y=data_scaled["macd_1440"], line=dict(color='#079118', width=2), name='macd_1440')
+
+ 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_5 = go.Scatter(x=data['ymd'], y=data["slowk_5"], line=dict(color='#D27144', width=2), name='slowk_5')
+ slowd_5 = go.Scatter(x=data['ymd'], y=data["slowd_5"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_5')
+ slowk_10 = go.Scatter(x=data['ymd'], y=data["slowk_10"], line=dict(color='#BBBEC3', width=2), name='slowk_10')
+ slowd_10 = go.Scatter(x=data['ymd'], y=data["slowd_10"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_10')
+ slowk_20 = go.Scatter(x=data['ymd'], y=data["slowk_20"], line=dict(color='#d755e8', width=2), name='slowk_20')
+ slowd_20 = go.Scatter(x=data['ymd'], y=data["slowd_20"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_20')
+ slowk_60 = go.Scatter(x=data['ymd'], y=data["slowk_60"], line=dict(color='#099B92', width=2), name='slowk_60')
+ slowd_60 = go.Scatter(x=data['ymd'], y=data["slowd_60"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_60')
+ slowk_120 = go.Scatter(x=data['ymd'], y=data["slowk_120"], line=dict(color='#640745', width=2), name='slowk_120')
+ slowd_120 = go.Scatter(x=data['ymd'], y=data["slowd_120"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_120')
+ slowk_240 = go.Scatter(x=data['ymd'], y=data["slowk_240"], line=dict(color='#e68456', width=2), name='slowk_240')
+ slowd_240 = go.Scatter(x=data['ymd'], y=data["slowd_240"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_240')
+ slowk_480 = go.Scatter(x=data['ymd'], y=data["slowk_480"], line=dict(color='#A18A0D', width=2), name='slowk_480')
+ slowd_480 = go.Scatter(x=data['ymd'], y=data["slowd_480"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_480')
+ slowk_720 = go.Scatter(x=data['ymd'], y=data["slowk_720"], line=dict(color='#EF3644', width=2), name='slowk_720')
+ slowd_720 = go.Scatter(x=data['ymd'], y=data["slowd_720"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_720')
+ slowk_1440 = go.Scatter(x=data['ymd'], y=data["slowk_1440"], line=dict(color='#4479D2', width=2), name='slowk_1440')
+ slowd_1440 = go.Scatter(x=data['ymd'], y=data["slowd_1440"], line=dict(dash='dashdot', color='grey', width=2), name='slowd_1440')
+
+ text_list = []
+ for i in range(len(data)):
+ text_list.append(
+ "[{}] {:,}
"
+ "[BASIC]
"
+ " support: {:.2f}, resistance: {:.2f}
"
+ " poly_5: {:.5f}, poly_10: {:.5f}, poly_20: {:.5f}, 6: {:.5f}, poly_120: {:.5f}, poly_240: {:.5f}, poly_480: {:.5f}, poly_720: {:.5f}, poly_1440: {:.5f}
"
+ "[INFO]
"
+ " new_high_7: {:,.2f}, new_high_9: {:,.2f}, new_high_26: {:,.2f}, new_low_7: {:,.2f}, new_low_9: {:,.2f}, new_low_26: {:,.2f}
"
+ .format(
+ data['ymd'].iloc[i].strftime('%Y-%m-%d %H:%M'), data["close"].iloc[i],
+ data['support'].iloc[i], data['resistance'].iloc[i],
+ data_scaled['poly_5'].iloc[i], data_scaled['poly_10'].iloc[i], data_scaled['poly_20'].iloc[i], data_scaled['poly_60'].iloc[i], data_scaled['poly_120'].iloc[i], data_scaled['poly_240'].iloc[i], data_scaled['poly_480'].iloc[i], data_scaled['poly_720'].iloc[i], data_scaled['poly_1440'].iloc[i],
+ data['new_high_7'].iloc[i], data['new_high_9'].iloc[i], data['new_high_26'].iloc[i], data['new_low_7'].iloc[i], data['new_low_9'].iloc[i], data['new_low_26'].iloc[i],
+ ))
+
+ support = go.Scatter(x=data['ymd'], y=data["support"], name="support", line_color='#192BB1')
+ resistance = go.Scatter(x=data['ymd'], y=data["resistance"], name="resistance", line_color='#E31313')
+
+ 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, avg120, avg240, avg480, avg720, avg1440, support, resistance, buy_check, sell_check, candle_stick]
+ else:
+ candle_data = [avg5, avg10, avg20, avg60, avg120, avg240, avg480, avg720, avg1440, support, resistance, candle_stick]
+
+ volume_data = [volume_line]
+ # 절대정보
+ indicator1 = [
+ info_p_up_limit, info_p_middle_limit, info_p_down_limit, info_n_up_limit, info_n_middle_limit,
+ info_n_down_limit,
+ new_high_7, new_high_9, new_high_26, new_low_7, new_low_9, new_low_26,
+ disparity_diff_20_5_rate, disparity_diff_60_20_rate, disparity_diff_120_20_rate, disparity_diff_240_20_rate, disparity_diff_480_20_rate, disparity_diff_720_20_rate, disparity_diff_1440_20_rate,
+ ]
+ # 상대정보
+ info_data = [
+ disparity_diff_20_5, disparity_diff_60_20, disparity_diff_120_20, disparity_diff_240_20, disparity_diff_480_20, disparity_diff_720_20, disparity_diff_1440_20,
+ poly_5, poly_10, poly_20, poly_60, poly_120, poly_240, poly_480, poly_720, poly_1440
+ ]
+ slow_data = [
+ slowk_up_limit, slowk_middle_limit, slowk_down_limit,
+ 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,
+ ]
+ # macd
+ macd_data = [
+ macd, macds, macdo, macd_720, macd_1440
+ ]
+ # rsi
+ rsi_data = [
+ rsi, rsi_720, rsi_1440
+ ]
+ # 그래프를 그린다.
+ """
+ fig = go.Figure(data=candle_data)
+ fig.update_layout(title=stock_code)
+ fig.show()
+ """
+ fig = subplots.make_subplots(
+ rows=7, cols=1,
+ subplot_titles=("기술지표#1", "통계정보", "캔들", "slow", "macd", "rsi", "거래량"),
+ shared_xaxes=True, horizontal_spacing=0.03, vertical_spacing=0.01,
+ row_heights=[200, 200, 800, 200, 200, 200, 200]
+ )
+ for trace in indicator1:
+ fig.append_trace(trace, 1, 1)
+ for trace in info_data:
+ fig.append_trace(trace, 2, 1)
+ for trace in candle_data:
+ fig.append_trace(trace, 3, 1)
+ for trace in slow_data:
+ fig.append_trace(trace, 4, 1)
+ for trace in macd_data:
+ fig.append_trace(trace, 5, 1)
+ for trace in rsi_data:
+ fig.append_trace(trace, 6, 1)
+ for trace in volume_data:
+ fig.append_trace(trace, 7, 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)
+
+ if info is not None:
+ buy_count, sell_count = 0, 0
+ if bsLine is not None:
+ buy_count = len(df.loc[df["buy_price"] > 0])
+ sell_count = len(df.loc[df["sell_price"] > 0])
+ fig.update_layout(
+ height=2000,
+ title="{}, buy: {} ({:,.2f}원), sell: {} ({:,.2f}원), profit: {:,.2f}원 ({:.2f}%), holding_amt: {:,.2f}".format(stock_code, buy_count, info['buy_amt'], sell_count, info['sell_amt'], info['profit'], info['rate'], info['holding_amt']),
+ xaxis_rangeslider_visible=False,
+ xaxis1_rangeslider_visible=False,
+ xaxis2_rangeslider_visible = False,
+ xaxis3_rangeslider_visible = False,
+ xaxis4_rangeslider_visible = False
+ )
+ else:
+ buy_count = 0
+ if bsLine is not None:
+ buy_count = len(df.loc[df["buy_price"] > 0])
+ fig.update_layout(
+ height=2700,
+ title="{}, buy: {}번 ".format(stock_code, buy_count),
+ xaxis_rangeslider_visible=False,
+ xaxis1_rangeslider_visible=False,
+ xaxis2_rangeslider_visible=False,
+ xaxis3_rangeslider_visible=False,
+ xaxis4_rangeslider_visible=False
+ )
+ #fig.update_layout(title=stock_code + "_" + str(buy_count) + "," + str(sell_count))
+ # 파일로 작성함
+ ###fileName = os.path.join(self.RESOURCE_PATH, 'analysis', stock_code + '.html')
+ ###po.write_html(fig, file=fileName, auto_open=False)
+
+ # 화면으로 출력함
+ if show:
+ fig.show()
+
+ return
+
+
+ def checkTransaction(self, ticker, data, data_scaled, 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'] = [-1 for i in range(size)]
+
+ size = ci
+ start = 0
+ for i in range(start, size):
+
+ bsLine['buy_ymd'][i] = data['ymd'].iloc[i]
+
+ """
+ if 0 < len(ticker['BUY_INFO']['buy_list']):
+ count = sum([price['buy_count'] for price in ticker['BUY_INFO']['buy_list']])
+ prices = [price['buy_price'] for price in ticker['BUY_INFO']['buy_list']]
+
+ ticker['BUY_INFO']['buy_count'] = count
+ ticker['BUY_INFO']['avg_buy_price'] = (sum(prices) / len(prices))
+
+ # loss cut 체크
+ if 0 < len(ticker['BUY_INFO']['buy_list']):
+ sell_count = 0
+
+ for c, buy_list in reversed(list(enumerate(ticker['BUY_INFO']['buy_list']))):
+ # 만약 장기가 아니라면 1일전 가격 아래로 떨어지면 loss cut
+ if buy_list['buy_price'] < np.min(data['close'][i-4320:i]):
+ if data['close'][i] < np.min(data['close'][i-4320:i]):
+ del ticker['BUY_INFO']['buy_list'][c]
+ sell_count += buy_list['buy_count']
+
+ if 0 < sell_count:
+ bsLine['sell_price'][i] = data['close'][i]
+ bsLine['sell_count'][i] = sell_count
+ bsLine['sell_type'][i] = 'loss_cut'
+ bsLine['sell_cut'][i] = -1
+
+ self.test.append({'type': 'SELL', 'ymd': data['ymd'].iloc[i], 'price': data['close'][i] - ticker['unit'], 'count': count, 'amt': count*(data['close'][i] - ticker['unit'])})
+ continue
+ """
+
+ # 매도 확인
+ sell_price, sell_count, sell_type = self.buySell_Minutely.getSellPrice(ticker, data, data_scaled, i, bsLine)
+ bsLine['sell_price'][i] = sell_price
+ bsLine['sell_count'][i] = sell_count
+ bsLine['sell_type'][i] = sell_type
+ bsLine['sell_cut'][i] = -1
+
+
+ # buy_cut 체크
+ check = False
+ if 0 < len(ticker['BUY_INFO']['buy_list']):
+
+ current_price = data['close'].iloc[i]
+
+ for c in range(len(ticker['BUY_INFO']['buy_list'])-1, -1, -1):
+ buy_list = ticker['BUY_INFO']['buy_list'][c]
+
+ buy_cut = ticker['BUY_INFO']['buy_list'][c]['buy_cut']
+ if buy_cut is not None and 0 < buy_cut and current_price < buy_cut:
+ self.test.append({'type': 'SELL', 'ymd': data['ymd'].iloc[i], 'price': current_price - ticker['unit'], 'count': buy_list['buy_count'], 'amt': buy_list['buy_count']*(current_price - ticker['unit'])})
+ del ticker['BUY_INFO']['buy_list'][c]
+
+ bsLine['sell_price'][i] = current_price
+ bsLine['sell_count'][i] = buy_list['buy_count']
+ bsLine['sell_type'][i] = "buy_cut"
+ bsLine['sell_cut'][i] = c
+ check = True
+ continue
+
+ if check:
+ continue
+
+
+ if 0 < sell_price:
+ self.test.append({'type': 'SELL', 'ymd': data['ymd'].iloc[i], 'price': sell_price-ticker['unit'], 'count': sell_count, 'amt': sell_count*(sell_price - ticker['unit'])})
+ self.clear_BSLINE(ticker['BUY_INFO'], sell_type)
+ else:
+ # 매도가 아니면 매수 확인
+ buy_ymd, buy_price, buy_count, buy_type, buy_cut = self.buySell_Minutely.getBuyPrice(ticker, data, data_scaled, i, bsLine)
+
+ bsLine['buy_price'][i] = buy_price
+ bsLine['buy_count'][i] = buy_count
+ bsLine['buy_type'][i] = buy_type
+ bsLine['buy_cut'][i] = buy_cut
+
+ if 0 < buy_price:
+ self.test.append({'type': 'BUY', 'ymd': data['ymd'].iloc[i], 'price': buy_price+ticker['unit'], 'count': buy_count, 'amt': buy_count*(buy_price+ticker['unit'])})
+ ticker['BUY_INFO']['buy_list'].append({'buy_ymd': buy_ymd, 'buy_price': buy_price, 'buy_count': buy_count, 'buy_type': buy_type, 'buy_cut': buy_cut})
+ ticker['BUY_INFO']["avg_buy_price"] = np.average([buy_list['buy_price'] for buy_list in ticker['BUY_INFO']['buy_list']])
+ ticker['BUY_INFO']["buy_count"] = np.sum([buy_list['buy_count'] for buy_list in ticker['BUY_INFO']['buy_list']])
+ ticker['BUY_INFO']["buy_amount"] = ticker['BUY_INFO']["avg_buy_price"] * ticker['BUY_INFO']["buy_count"]
+
+ return bsLine
+
+
+ def simulate(self, ticker, get_days=30, mins=1):
+
+ total_buy_amount, profit, buy_amt = 0, 0, 0
+
+ #data, ci = self.jSDPattern.getData(ticker, mins=1440, ymd=ymd, get_days=1500)
+ data, data_scaled, ci = self.jSDPattern.getData(ticker, mins=mins, ymd=ticker['ymd'], get_days=get_days)
+ if data is None:
+ return
+
+ with open("config.json", "r", encoding="utf-8") as f:
+ config = json.load(f)
+ BUY_INFO = config['BUY_INFO']
+ ticker['BUY_INFO'] = BUY_INFO
+ ticker['INIT'] = True
+ ticker['unit'] = self.upbit.checkUnit(data['close'].iloc[-1])
+ ticker['MAX_BUY'] = self.upbit.getMaxPrice(data['close'].iloc[-1])
+
+ bsLine = self.checkTransaction(ticker, data, data_scaled, ci)
+
+ for item in self.test:
+ if item['type'] == 'BUY':
+ buy_amt += item['amt']*0.9995
+ else:
+ profit += item['amt'] - buy_amt
+ buy_amt = 0
+
+ holding_amt = sum([buy_list['buy_price']*buy_list['buy_count'] for buy_list in ticker['BUY_INFO']['buy_list']])
+ buy_test = [item['price']*item['count']*0.9995 for item in self.test if item['type'] == 'BUY']
+ sell_test = [item['price']*item['count']*1.0005 for item in self.test if item['type'] == 'SELL']
+ if 0 < sum(buy_test):
+ rate = 100 * profit / sum(buy_test)
+ else:
+ rate = 0
+ print("\n시도 ({}): {}회, 이익: {:,.0f}원 ({:.2f}%)".format(ticker['ticker_code'], len(self.test), profit, rate))
+ print("\t- 매수: {}회, 금액: {:,.0f}원".format(len(buy_test), sum(buy_test)))
+ print("\t- 매도: {}회, 금액: {:,.0f}원".format(len(sell_test), sum(sell_test)))
+ print("\t- 보유: 금액: {:,.0f}원".format(holding_amt))
+ total_buy_amount += sum(buy_test)
+
+ info = {'profit': profit, 'rate': rate, 'buy_count': len(buy_test), 'buy_amt': sum(buy_test), 'sell_count': len(sell_test), 'sell_amt': sum(sell_test), 'holding_amt': holding_amt}
+ self.draw(ticker, data, data_scaled, bsLine, show=True, info=info)
+
+ return total_buy_amount, profit
+
+
+if __name__ == "__main__":
+
+ PROJECT_HOME = os.getcwd()
+ RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
+
+ # 1000원 이하: 0.1
+ # 1000원 이상: 1
+ # 1만원 이상 10
+ # 10만원 이상: 50
+ # 100만원 이상: 1000
+ day_list = (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')
+
+ """
+ tickers = [
+ {'ticker_code': 'KRW-ADA', 'ticker_name': '에이다', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-AVAX', 'ticker_name': '아발란체', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-BLUR', 'ticker_name': '블러', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-BSV', 'ticker_name': '비트코인에스브이', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-BTC', 'ticker_name': '비트코인', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-BTG', 'ticker_name': '비트코인골드', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-CTC', 'ticker_name': '크레딧코인', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-DOGE', 'ticker_name': '도지코인', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-DOT', 'ticker_name': '폴카닷', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-ETC', 'ticker_name': '이더리움클래식', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-ETH', 'ticker_name': '이더리움', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-FLOW', 'ticker_name': '플로우', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-GAS', 'ticker_name': '가스', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-GLM', 'ticker_name': '골렘', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-HIFI', 'ticker_name': '하이파이', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-IQ', 'ticker_name': '아이큐', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-LINK', 'ticker_name': '체인링크', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-MATIC', 'ticker_name': '폴리곤', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-MINA', 'ticker_name': '미나', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-NEAR', 'ticker_name': '니어프로토콜', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-SAND', 'ticker_name': '샌드박스', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-SC', 'ticker_name': '시아코인', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-SEI', 'ticker_name': '세이', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-SOL', 'ticker_name': '솔라나', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-STORJ', 'ticker_name': '스토리지', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-STRAX', 'ticker_name': '스트라티스', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-STX', 'ticker_name': '스택스', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-SUI', 'ticker_name': '수이', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-THETA', 'ticker_name': '쎄타토큰', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list},
+ {'ticker_code': 'KRW-XRP', 'ticker_name': '리플', 'BUY_INFO': {}, 'rise_rate': 0.0, 'INIT': True, 'volume_check': False, 'ymd': day_list}
+ ]
+
+ total_profit, total_buy = 0, 0
+ for ticker in tickers:
+ simulation = Simulation_minutely(RESOURCE_PATH)
+ total_buy_amount, profit = simulation.simulate(ticker, get_days=14)
+ total_profit += profit
+ total_buy += total_buy_amount
+ print("\nticker: {}개: 총이익: {:,.0f}원 ({:.2f})%".format(len(tickers), total_profit, 100*total_profit/total_buy))
+ """
+
+ simulation = Simulation_minutely(RESOURCE_PATH)
+ ticker = {'ticker_code': 'KRW-ONT', 'ticker_name': '체인링크', 'BUY_INFO': {}, 'ymd': (datetime.now()+timedelta(days=1)).strftime('%Y%m%d')}
+ #ticker = {'ticker_code': 'KRW-BCH', 'ticker_name': '체인링크', 'BUY_INFO': {}, 'ymd': '20240324'}
+ simulation.simulate(ticker, get_days=7)
+
+
+ print ("done...")
diff --git a/hts/BuySell_Daily.py b/hts/BuySell_Daily.py
index ed79db0..a0b1de9 100644
--- a/hts/BuySell_Daily.py
+++ b/hts/BuySell_Daily.py
@@ -10,229 +10,83 @@ class BuySell_Daily:
count += 1
return count
- def getBuyPrice(self, ticker, data, i, BS=None):
+ def getBuyPrice(self, ticker, data, data_scaled, i, BS=None):
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
- point = None
- for c in range(i-1, 0, -1):
- if data['close'][c] < data['changeLine'][c]:
- point = c
+ sub_i = None
+ for c in range(i-1, i-5, -1):
+ if 0 < BS['buy_count'][c] and 0 < BS['buy_price'][c]:
+ sub_i = 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(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(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
+ sub_check = False
+ if sub_i is not None:
+ sub_check = True
+ for c in range(sub_i, i+1):
+ if data['close'].iloc[c+1] < BS['buy_price'][c] * 0.99:
+ sub_check = False
+ break
+ if sub_check:
+ buy_price = data['close'].iloc[i] - 2 * ticker['unit']
+ buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'].iloc[i]
+ buy_type = ''
+ else:
+ tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_BBAND(ticker, data, data_scaled, 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_PolyLine(ticker, data, data_scaled, 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_Slow(ticker, data, data_scaled, 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
return buy_ymd, buy_price, buy_count, buy_type, buy_cut
- def getSellPrice(self, ticker, data, i, BS=None):
+ def getSellPrice(self, ticker, data, data_scaled, 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(ticker, data, i, BS)
- sell_type_list += tmp_sell_type_list
+ #tmp_sell_price, tmp_sell_type_list = self.getSellPrice_Umbong(ticker, data, data_scaled, 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
+ #sell_price = tmp_sell_price
if 0 < len(sell_type_list) or 0 < sell_price:
sell_type = ','.join(list(set(sell_type_list)))
return sell_price, sell_count, sell_type
- def getBuyPrice_ichimok_changeLine(self, ticker, data, i, BS=None):
+ """"""""""""""""""
+ """"""""""""""""""
+
+ def getBuyPrice_BBAND(self, ticker, data, data_scaled, i, BS):
buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
check = False
- id9, id26, id33, id52 = 8, 25, 32, 51
- if 5 < i:
- # 신저가를 갱신하지 않으면서 전환선이 떨어질 때 주가는 올라감 (기준선은 횡보, 현재 봉이 신저가가 이닐 때)
- # --> 기준선이 계속 횡보하거나 떨어지면 상승하지는 않는다.
- # https://www.youtube.com/watch?v=KZMP0Ssv8WI&t=432s (8:45)
- if data['new_low_9'][i] == 0:
- if data['changeLine'][i] < data['baseLine'][i]:
- if data['changeLine'][i] < data['changeLine'][i-1] and np.min(data['close'][i-8:i]) < data['close'][i]:
- if data['baseLine'][i-1] == data['baseLine'][i] < data['baseLine'][i-2]:
- if 3 < self.countYangBong(data, i):
- check = True
- buy_type = "ichimok_changeLine_1"
- buy_weight = 5
- buy_cut = min(np.min(data['open'][i - 60:i]), np.min(data['close'][i - 60:i]))
+ if 60 < i:
- if data['new_high_9'][i] == 1:
- if data['changeLine'][i-1] < data['changeLine'][i] and data['baseLine'][i-1] < data['baseLine'][i]:
- if data['baseLine'][i - 1] != data['baseLine'][i]:
- if 0.2 < data['leadingSpan1_leadingSpan2_diff_rate'][i+id52]:
- check = True
- buy_type = "ichimok_changeLine_2"
- buy_weight = 10
- buy_cut = min(np.min(data['open'][i - 60:i]), np.min(data['close'][i - 60:i]))
+ sub_check1, sub_check2 = False, False
+ for c in range(i-20, i):
+ if not sub_check1 and data['bb_width'].iloc[i-1] < data['bb_width'].iloc[i] and data['bb_width'].iloc[i] < 5:
+ sub_check1 = True
+ if sub_check1 and not sub_check2 and data['upper_20'].iloc[i] < data['high'].iloc[i]:
+ sub_check2 = True
+ break
- if data['new_high_26'][i] == 1:
- for c in range(i-15, i):
- if data['changeLine'][c-1] < data['baseLine'][c] and data['baseLine'][i-1] < data['changeLine'][i]:
- if 0.2 < data['leadingSpan1_leadingSpan2_diff_rate'][i + id52]:
- check = True
- buy_type = "ichimok_changeLine_3"
- buy_weight = 10
- buy_cut = min(np.min(data['open'][i - 60:i]), np.min(data['close'][i - 60:i]))
- break
-
- 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 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
-
- check = False
-
- id9, id26, id33, id52 = 9, 26, 33, 52
- if 5 < i:
- # 기준선이 하락할 때, 전환선이 상승하는 경우를 중기 추세의 변곡이라 한다
- if data['changeLine'][i-1] < data['changeLine'][i] and data['baseLine'][i] < data['baseLine'][i-1]:
- if data['changeLine'][i - 1] < data['baseLine'][i-1] and data['baseLine'][i] < data['changeLine'][i]:
- if data['open'][i] < data['close'][i]:
- if 3 < self.countYangBong(data, i):
- check = True
- buy_type = "ichimok_baseLine_1"
- buy_weight = 5
- buy_cut = min(np.min(data['open'][i - 60:i]), np.min(data['close'][i - 60:i]))
-
- # 기준선이 평행 때, 전환선이 상승하는 경우를 중기 추세의 변곡이라 한다
- if data['changeLine'][i-1] < data['changeLine'][i] and data['baseLine'][i-3] == data['baseLine'][i-2] == data['baseLine'][i-1] == data['baseLine'][i]:
- if data['changeLine'][i - 1] < data['baseLine'][i-1] and data['baseLine'][i] < data['changeLine'][i]:
- if data['open'][i] < data['close'][i]:
- if 3 < self.countYangBong(data, i):
- check = True
- buy_type = "ichimok_baseLine_1"
- buy_weight = 5
- buy_cut = min(np.min(data['open'][i - 60:i]), np.min(data['close'][i - 60:i]))
-
- 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 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
-
- check = False
-
- if 5 < i:
-
- if data['laggingSpan_close_diff_rate'][i-1] <= 0 and 0 < data['laggingSpan_close_diff_rate'][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 = '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] - 2 * ticker['unit']
- buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
- buy_weight = 2
- buy_type = 'laggingSpan2'
-
- 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_ichimok_baseLine(self, ticker, data, i, BS=None):
- sell_price = 0
- sell_type_list = []
-
- check = False
-
- id26, id52 = 26, 52
-
- if data['new_high_9'][i] == 0:
- if data['baseLine'][i-1] < data['baseLine'][i] and data['changeLine'][i] < data['changeLine'][i-1]:
- check = True
- sell_type_list.append('ichimok_baseLine')
-
- if check:
- 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] price and 1000 < profit:
+ buy_count = 2 * last_buy_count
+ elif last_buy_price < price and 1000 > profit:
+ buy_count = 1.5 * last_buy_count
+ else:
+ buy_count = 1 * last_buy_count
+
+ if 'today_buy_type' in ticker and ticker['today_buy_type'] == 3:
+ buy_count *= 2
+ else:
+ buy_count = 1.5 * ticker['MAX_BUY'] / price
+
+ if 200000 < price * buy_count:
+ buy_count = 200000 / price
+
+ return buy_count
+
+ def getBuyPrice(self, ticker, data, data_scaled, i, BS=None):
+ buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
+
+ # buy_ymd, buy_price, buy_count, buy_type, buy_cut = self.getBuyPrice_PolyLine(ticker, data, data_scaled, i, BS)
+ #tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_Candle(ticker, data, data_scaled, i, BS)
+ tmp_buy_ymd, tmp_buy_price, tmp_buy_count, tmp_buy_type, tmp_buy_cut = self.getBuyPrice_Slow(ticker, data, data_scaled, 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'].iloc[i]), '%Y-%m-%d %H:%M:%S') - ticker['BUY_INFO']['buy_list'][-1]['buy_ymd'])
+ d = diff.days
+ s = diff.seconds
+
+ # 해당 종목에 대해서 10분 이내 매수 금지
+ if s < 15 * 60:
+ return None, 0, 0, '', None
+
+ return buy_ymd, buy_price, buy_count, buy_type, buy_cut
+
+ def getSellPrice(self, ticker, data, data_scaled, i, BS=None):
+ sell_price, sell_count, sell_type = 0, 0, ''
+ sell_type_list = []
+
+ """
+ tmp_sell_price, tmp_sell_count, tmp_sell_type_list = self.getSelllPrice_Umbong(ticker, data, data_scaled, i, BS)
+ sell_count += tmp_sell_count
+ sell_type_list += tmp_sell_type_list
+ sell_price += tmp_sell_price
+ """
+
+ if 0 < len(sell_type_list) or 0 < sell_price:
+ sell_type = ','.join(list(set(sell_type_list)))
+
+ return sell_price, sell_count, sell_type
+
+ """"""""""""""""""
+ """"""""""""""""""
+
+ def getBuyPrice_Slow(self, ticker, data, data_scaled, 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['poly_20'].iloc[i - 1] < data['poly_20'].iloc[i] and data_scaled['disparity_diff_60_20_rate'].iloc[i] < -0.5:
+ if data_scaled['macd_720'].iloc[i - 1] < data_scaled['macd_720'].iloc[i] and data_scaled['macd'].iloc[i - 1] < data_scaled['macd'].iloc[i]:
+ if data['avg10'].iloc[i] < data['avg5'].iloc[i]:
+ check = True
+ buy_price = data['close'][i] - 2 * ticker['unit']
+ buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
+ buy_type = 'slowk_10'
+ # buy_cut = data['support'].iloc[i]
+ """
+
+ if data["slowk_10"].iloc[i-1] < data["slowk_10"].iloc[i] < 20:
+ if data["slowk_10"].iloc[i-1] < data["slowd_10"].iloc[i-1] and data["slowd_10"].iloc[i] < data["slowk_10"].iloc[i]:
+ check = True
+ buy_price = data['close'][i] - 2 * ticker['unit']
+ buy_count = (buy_weight * ticker['MAX_BUY']) / data['close'][i]
+ buy_type = 'slowk_10'
+ # buy_cut = data['support'].iloc[i]
+
+ if check:
+ buy_ymd = data['ymd'].iloc[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 getBuyPrice_Candle(self, ticker, data, data_scaled, i, BS):
+
+ buy_ymd, buy_price, buy_count, buy_weight, buy_type, buy_cut = None, 0, 0, 1, '', None
+
+ check = False
+
+ if 60 < i:
+ if data_scaled['disparity_diff_20_5_rate'].iloc[i] < 1 and data_scaled['disparity_diff_60_20_rate'].iloc[i] < 1 and data_scaled['disparity_diff_120_20_rate'].iloc[i] < 1:
+
+ if data['slowk_1440'].iloc[i - 1] < data['slowd_1440'].iloc[i - 1]:
+ if data['slowd_1440'].iloc[i] < data['slowk_1440'].iloc[i] < 40:
+ check = True
+ buy_price = data['close'].iloc[i] - 2 * ticker['unit']
+ buy_count = self.getBuy_Count(ticker, data['close'].iloc[i])
+ buy_type = 'slowk_1440'
+ #buy_cut = data['support'].iloc[i]
+
+ if data['avg240'].iloc[i - 1] < data['avg240'].iloc[i]:
+ if data_scaled['poly_480'].iloc[i - 1] <= 0 and 0 < data_scaled['poly_480'].iloc[i]:
+ check = True
+ buy_price = data['close'].iloc[i] - 2 * ticker['unit']
+ buy_count = self.getBuy_Count(ticker, data['close'].iloc[i])
+ buy_type = 'poly_480'
+ #buy_cut = data['support'].iloc[i]
+
+ if data_scaled['poly_720'].iloc[i - 1] < data_scaled['poly_720'].iloc[i] and data['slowk_720'].iloc[i] < 50:
+ if data['close'].iloc[i - 1] < data['avg720'].iloc[i-1] and data['avg720'].iloc[i] < data['close'].iloc[i]:
+ check = True
+ buy_price = data['close'].iloc[i] - 2 * ticker['unit']
+ buy_count = self.getBuy_Count(ticker, data['close'].iloc[i])
+ buy_type = 'poly_720'
+ #buy_cut = data['support'].iloc[i]
+
+ if data_scaled['poly_1440'].iloc[i - 1] < data_scaled['poly_1440'].iloc[i] and data['slowk_1440'].iloc[i] < 50:
+ if data['close'].iloc[i - 1] < data['avg1440'].iloc[i-1] and data['avg1440'].iloc[i] < data['close'].iloc[i]:
+ check = True
+ buy_price = data['close'].iloc[i] - 2 * ticker['unit']
+ buy_count = self.getBuy_Count(ticker, data['close'].iloc[i])
+ buy_type = 'poly_1440'
+ #buy_cut = data['support'].iloc[i]
+
+ if check:
+ buy_ymd = data['ymd'].iloc[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 getSelllPrice_Umbong(self, ticker, data, data_scaled, i, BS):
+ sell_price, sell_count = 0, 0
+ sell_type_list = []
+
+ if 0 < len(ticker['BUY_INFO']['buy_list']):
+ check = False
+ sell_count = 0
+
+ if data['close'].iloc[i] < data['open'].iloc[i]:
+ for c in range(i - 1, i - 10, -1):
+ if data['open'].iloc[c] < data['close'].iloc[c] == data['high'].iloc[c]:
+ if data['close'].iloc[i] < data['open'].iloc[c]:
+ check = True
+ sell_count_1 = sum([price['buy_count'] for price in ticker['BUY_INFO']['buy_list'] if price['buy_type'] == "slowk_1440"])
+ if 0 < sell_count_1:
+ sell_type_list.append('slowk_1440')
+
+ sell_count_2 = sum([price['buy_count'] for price in ticker['BUY_INFO']['buy_list'] if price['buy_type'] == "poly_480"])
+ if 0 < sell_count_2:
+ sell_type_list.append('poly_480')
+
+ if "buy_amount" in ticker['BUY_INFO'] and ticker['BUY_INFO']["buy_amount"] < 50000:
+ sell_count = sell_count_1 + sell_count_2
+ else:
+ sell_count = (sell_count_1 + sell_count_2) * 0.8
+
+ if check and 0 < sell_count:
+ sell_price = data['close'].iloc[i] + 2 * ticker['unit']
+
+ return sell_price, sell_count, sell_type_list