Files
DeepStock/HTS_etf.py
dsyoon 03cbec5803 init
2023-11-01 00:16:52 +09:00

262 lines
12 KiB
Python

import time
import os
import sqlite3
from datetime import datetime
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
SELL_GAP = None
stock_code = None
stock_name = None
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
bot = None
stockStatus = None
def __init__(self, RESOURCE_PATH, stock_code, stock_name, SELL_GAP):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.SELL_GAP = SELL_GAP
self.stock_code = stock_code
self.stock_name = stock_name
self.orderChecker = OrderChecker(self.RESOURCE_PATH, self.stock_code)
self.buySellChecker = BuySellChecker()
self.labelChecker = LabelChecker(RESOURCE_PATH)
self.bot = TelegramBot()
self.stockStatus = StockStatus(RESOURCE_PATH)
return
def getTodayStateValue(self, stock_code, dbfile_name="stock.db"):
try:
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, dbfile_name))
cursor = conn.cursor()
cursor.execute('SELECT stochastic_slow_k FROM stock_analysis WHERE CODE=? order by ymd desc limit 1', (stock_code,))
db_result = cursor.fetchone()
cursor.close()
conn.close()
if db_result is not None:
return db_result[0]
except:
return 100
return 100
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:
if bs_sell_price is not None:
if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], bs_sell_price)
check = True
else:
if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], jangoDic[code]['현재가'])
check = True
else:
if jangoDic[code]['매도가능'] > 0:
if jangoDic[code]['평가손익'] < -1.5 or 3 < jangoDic[code]['평가손익'] or self.SELL_GAP < jangoDic[code]['평가금액']-jangoDic[code]['매입금액']:
# 1.5% 손해 혹은 2% 이상 시 수익 매도
self.requestOrder(OrderType.sell, code[1:], jangoDic[code]['매도가능'], 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 get_MAX_PRICE(self, stock_code, stochastic_slow_k):
MAX_PRICE = 30000
if stock_code == "252670":
# "KODEX 200선물인버스2X"
if stochastic_slow_k < 20:
MAX_PRICE = 200000
elif 20 <= stochastic_slow_k < 40:
MAX_PRICE = 150000
elif 40 <= stochastic_slow_k < 60:
MAX_PRICE = 100000
else:
MAX_PRICE = 50000
elif stock_code == "122630":
# "KODEX 레버리지"
if stochastic_slow_k < 20:
MAX_PRICE = 100000
elif 20 <= stochastic_slow_k < 40:
MAX_PRICE = 70000
elif 40 <= stochastic_slow_k < 60:
MAX_PRICE = 50000
else:
MAX_PRICE = 30000
elif stock_code == "251340":
# "KODEX 코스닥150선물인버스"
if stochastic_slow_k < 20:
MAX_PRICE = 100000
elif 20 <= stochastic_slow_k < 40:
MAX_PRICE = 70000
elif 40 <= stochastic_slow_k < 60:
MAX_PRICE = 50000
else:
MAX_PRICE = 30000
elif stock_code == "233740":
# "KODEX 코스닥150레버리지"
if stochastic_slow_k < 20:
MAX_PRICE = 70000
elif 20 <= stochastic_slow_k < 40:
MAX_PRICE = 50000
elif 40 <= stochastic_slow_k < 60:
MAX_PRICE = 30000
else:
MAX_PRICE = 10000
return MAX_PRICE
def buyRealTime(self, today, analyzed_day=1000, logFp=None):
stochastic_slow_k = self.getTodayStateValue(self.stock_code)
MAX_PRICE = self.get_MAX_PRICE(self.stock_code, stochastic_slow_k)
print("START...")
THIS_TIME = datetime.now()
LAST_DATA = self.getLastData(self.stock_code, today)
while datetime.strptime(today + " 063000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100",'%Y%m%d %H%M%S'):
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 090100", '%Y%m%d %H%M%S'):
self.bot.sendMsg("START... {} ({}) SLOW_K: {}".format(self.stock_code, self.stock_name, MAX_PRICE))
logFp.write("START {} ({}) SLOW_K: {}\n".format(self.stock_code, self.stock_name, MAX_PRICE))
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
# 매도를 체크한다.
self.sellStocks(self.stock_code)
time.sleep(0.1)
try:
# 데이터를 가지고 온다.
result = self.getRealTime(self.stock_code, today, LAST_DATA)
except:
print("#ERROR:", self.stock_code)
continue
data = self.buySellChecker.analyze(result)
data.drop(data.index[:len(data) - analyzed_day], inplace=True)
# 사야 할 시점과 팔아야 할 시점을 체크한다.
bsLine = self.buySellChecker.checkTransaction(self.stock_code, data, None, None, isRealTime=True)
bs_buy_price = bsLine['buy'][0]
bs_buy_weight = bsLine['buy_weight'][0]
bs_sell_price = bsLine['sell'][0]
# 미체결 기록을 가져와서 10분 이상 된 매수 주문을 취소 한다.
ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.cancel(today, "A" + self.stock_code, ORDER_LIST, mins=10)
if len(orderListToCancel) > 0:
self.cancelOrderList(orderListToCancel)
if bs_buy_price > 1000:
#if not self.orderChecker.exist(today, "A" + self.stock_code, hours=9):
buy_count = int(MAX_PRICE / bs_buy_price)
if buy_count > 0:
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, self.stock_code, buy_count, bs_buy_price)
self.orderChecker.buy(today, "A" + self.stock_code, buy_count, bs_buy_price, orderNum)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, self.stock_code, bs_buy_price, buy_count)
logFp.write("{} BUY {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, buy_count))
if bs_sell_price > 1000:
check = self.sellStocks(self.stock_code, bs_sell_price)
if check:
# 로그 출력
print("SELL", THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, self.stock_name, bs_sell_price)
logFp.write("{} SELL {} {} {}\n".format(THIS_TIME.strftime('%Y%m%d %H%M%S'), self.stock_code, bs_buy_price, bs_sell_price))
# 로그 출력
print("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f" %
(str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-1]))
logFp.write("TIMECHECK: %s, code: %s, buy: %d, sell: %d, open: %d, close: %d, high: %d, low: %d, macd: %.2f\n" %
(str(THIS_TIME), self.stock_code, bs_buy_price, bs_sell_price, data["open"][len(data["open"])-1], data["close"][len(data["close"])-1], data["high"][len(data["high"])-1], data["low"][len(data["low"])-1], data["macd"][len(data["macd"])-1]))
if (int(THIS_TIME.strftime("%M")) % 50 == 0 or int(THIS_TIME.strftime("%M")) % 20 == 0):
self.bot.alarm_live(self.stock_code, self.stock_name, data["close"][len(data["close"])-1], data["macd"][len(data["macd"])-1])
logFp.flush()
time.sleep(60)
THIS_TIME = datetime.now()
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