This commit is contained in:
dsyoon
2023-01-15 18:50:35 +09:00
parent be702a4404
commit 44b2e9f5bb
4 changed files with 234 additions and 189 deletions

View File

@@ -1,185 +0,0 @@
import time
import os
from datetime import datetime
from stock.analysis.DailyStatus import DailyStatus
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
class HTS_252670_DAILY (HTS):
RESOURCE_PATH = None
stock_code = None
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
dailyStatus = None
def __init__(self, RESOURCE_PATH, stock_code, buy_count):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.stock_code = stock_code
self.buy_count = buy_count
self.orderChecker = OrderChecker(self.RESOURCE_PATH, self.stock_code)
self.buySellChecker = BuySellChecker()
self.labelChecker = LabelChecker(RESOURCE_PATH)
self.dailyStatus = DailyStatus(RESOURCE_PATH)
return
def getSellingPrice(self, log_time, stock_code, final_price, check=False):
# final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미
# final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미
# final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임
sell_price = -1
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if jangoDic[code]['매도가능'] > 0:
if check:
if jangoDic[code]['장부가']*0.05 < jangoDic[code]['장부가'] - final_price:
sell_price = jangoDic[code]['장부가']
if code == "A" + stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
print("ORDER_SELL", stock_code, 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)
print("ORDER_SELL", stock_code, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price)
return
def buyRealTime(self, today):
print ("START...")
THIS_TIME = datetime.now()
final_sell_check = False
LAST_DATA = self.dailyStatus.getLastData(stock_code, 200)
while datetime.strptime(today + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'):
# 1515 까지만 매수를 시도한다.
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
# 매분 3초마다 실행한다.
if THIS_TIME.strftime('%S') == "03":
# 데이터를 가지고 온다.
result = self.getRealTime(self.stock_code, today, LAST_DATA)
# 규칙 기반의 분석을 통해서 볼린저밴드 상/하단을 계산한다.
data = self.buySellChecker.analyze(result)
# 만약 미체결 내역이 있는데, 지표가 꺽여 내려온다면, 매수 주문을 취소 시킨다.
last_index = len(data['close']) - 1
if data['slow_k'][last_index-1]>=80 and data['slow_k'][last_index-1] > data['slow_k'][last_index]:
# 미체결 기록을 가져온다.
ORDER_LIST = self.requestOrderList()
orderListToCancel = self.orderChecker.remove(self.stock_code, OrderType.sell, ORDER_LIST)
self.cancelOrderList(orderListToCancel)
print("CANCEL", THIS_TIME.strftime('%Y%m%d %H%M%S'), len(orderListToCancel), len(ORDER_LIST))
# 사야 할 시점/가격과 팔아야 할 시점/가격을 체크한다.
bsLine, data = self.buySellChecker.checkTransaction(data, self.stock_code, isRealTime=True)
bs_buy_price = bsLine['buy'][0]
bs_buy_weight = bsLine['buy_weight'][0]
bs_sell_price = bsLine['sell'][0]
data_size = len(data["close"])
final_price = data["close"][data_size-1]
if bs_buy_price > 0:
# 기본 100 주에 가중치를 추가해서 매수한다.
BUY_COUNT = int(self.buy_count * bs_buy_weight)
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, self.stock_code, BUY_COUNT , bs_buy_price)
# 미체결 기록을 가져온다.
ORDER_LIST = self.requestOrderList()
# 매수 주문을 기록한다.
orderListToCancel = self.orderChecker.add(self.stock_code, OrderType.buy, orderNum, BUY_COUNT, bs_buy_price, ORDER_LIST)
# 1 시간 이전 미체결을 모두 취소한다.
self.cancelOrderList(orderListToCancel)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), BUY_COUNT, bs_buy_price, len(orderListToCancel), len(ORDER_LIST))
if bs_sell_price > 0:
# 미체결 기록을 가져온다.
ORDER_LIST = self.requestOrderList()
# 매도 주문을 기록을 가져온다.
orderListToCancel = self.orderChecker.remove(self.stock_code, OrderType.sell, ORDER_LIST)
# 매도 미체결을 모두 취소한다.
self.cancelOrderList(orderListToCancel)
# 매도한다.
self.getSellingPrice(THIS_TIME, self.stock_code, final_price)
# 로그 출력
print("TIMECHECK: %s, price: %d, avg3: %.2f, avg5: %.2f, avg10: %.2f, slow_k: %.2f, open: %d, high: %d, low: %d" %
(str(THIS_TIME), final_price,
data["avg3"][data_size - 1], data["avg6"][data_size - 1], data["avg9"][data_size - 1], data["slow_k"][data_size - 2],
data["open"][data_size - 1], data["high"][data_size - 1], data["low"][data_size - 1],))
elif datetime.strptime(today + " 151530", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151600", '%Y%m%d %H%M%S'):
# 3시 15분 30초부터 3시 16분 사이는 잔량을 매도한다.
if not final_sell_check:
####
# 손해 보지 않는 가격에 매도한다.
####
# 주문 리스트를 가져온다.
orderList = self.requestOrderList()
# 15:10:00 이후라면 모든 미체결 취소한다.
self.cancelOrderList(orderList)
# 매도 가격을 가져온다.
result = self.getRealTime(self.stock_code, today, LAST_DATA)
final_price = result["close"][len(result["close"]) - 1]
self.getSellingPrice(THIS_TIME, self.stock_code, final_price)
final_sell_check = True
time.sleep(0.9)
THIS_TIME = datetime.now()
return
def updteTodayStock(self, db_filename, stock_code, today_str):
bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str)
self.labelChecker.updateLabel(db_filename, stock_code, bsLine, data, today_str)
return
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
# KODEX 인버스 * 2
stock_code = "252670"
stock_name = "KODEX 200선물인버스2X"
buy_count = 900
hts = HTS_252670_DAILY(RESOURCE_PATH, stock_code, buy_count)
today_str = today.strftime('%Y%m%d')
hts.buyRealTime(today_str)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
#today_str = "20220916"
hts.insertStockData(db_filename, stock_code, stock_name, today_str)
#hts.updteTodayStock(db_filename, stock_code, today_str)
print ("done...")

133
HTS_daily.py Normal file
View File

@@ -0,0 +1,133 @@
import time
import os
import sqlite3
from datetime import datetime
from stock.analysis.DailyStatus import DailyStatus
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
class HTS_DAILY (HTS):
RESOURCE_PATH = None
stock_code = None
buy_count = None
orderChecker = None
buySellChecker = None
labelChecker = None
dailyStatus = None
analyzed_day = None
MAX_BUY_PRICE = None
def __init__(self, RESOURCE_PATH):
super().__init__(RESOURCE_PATH)
self.RESOURCE_PATH = RESOURCE_PATH
self.dailyStatus = DailyStatus(RESOURCE_PATH)
self.analyzed_day = 60
self.MAX_BUY_PRICE = 500000
return
def getSellingPrice(self, log_time, stock_code, final_price, check=False):
# final_price와 diff를 받으면, 해당 가격으로 그냥 매도한다는 의미
# final_price와 diff가 None이면 장부가와 final 중 max로 팔겠다는 의미
# final_price가 0이고 diff가 None이면 장부가로 팔겠다는 의미임
sell_price = -1
jangoDic = self.requstJango()
if jangoDic and len(jangoDic.keys()) > 0:
for code in jangoDic:
if jangoDic[code]['매도가능'] > 0:
if check:
if jangoDic[code]['장부가']*0.05 < jangoDic[code]['장부가'] - final_price:
sell_price = jangoDic[code]['장부가']
if code == "A" + stock_code:
orderNum = self.requestOrder(OrderType.sell, stock_code, jangoDic[code]['매도가능'], sell_price)
print("ORDER_SELL", stock_code, 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)
print("ORDER_SELL", stock_code, log_time.strftime('%Y%m%d %H%M%S'), jangoDic[code]['매도가능'], sell_price)
return
def buyRealTime(self, today, n = 200):
print ("START...")
THIS_TIME = datetime.now()
while datetime.strptime(today + " 070000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 153100", '%Y%m%d %H%M%S'):
# 1515 까지만 매수를 시도한다.
if datetime.strptime(today + " 090000", '%Y%m%d %H%M%S') < THIS_TIME < datetime.strptime(today + " 151500", '%Y%m%d %H%M%S'):
stockTableName = 'stock'
conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, self.dbFileName))
cursor = conn.cursor()
cursor.execute('SELECT distinct code, name FROM ' + stockTableName + ' order by code')
items = cursor.fetchall()
cursor.close()
conn.close()
for idx, item in enumerate(items):
stock_code = item[0]
stock_name = item[1]
if stock_name.find('스팩') >= 0:
continue
print(idx, stock_code, stock_name)
print("Analysis # :", idx, ", CODE: ", stock_code, ", NAME: ", stock_name)
stock = self.dailyStatus.getLastData(stock_code, n)
self.getRealTime_DailyCheck(today, stock_code, stock)
data = self.dailyStatus.analyze(stock, self.analyzed_day)
# 분석일 데이터만 활용한다 (이전 데이터는 제거)
data.drop(data.index[:self.analyzed_day], inplace=True)
bsLine, data = self.buySellChecker.checkTransactionWithEnvelope(data, stock_code, isRealTime=False)
if len(data.index) > 10 and max(bsLine['buy'][len(bsLine['buy']) - 2:]) > 0:
last_index = len(bsLine['buy'])-1
if bsLine['buy'][last_index] > 0:
bs_buy_price = bsLine['buy'][last_index]
bs_buy_weight = bsLine['buy_weight'][last_index]
buy_count = int(self.MAX_BUY_PRICE / bs_buy_price)
# 매수를 주문한다.
orderNum = self.requestOrder(OrderType.buy, stock_code, buy_count, bs_buy_price)
# 로그 출력
print("BUY", THIS_TIME.strftime('%Y%m%d %H%M%S'), orderNum, stock_code, stock_name, bs_buy_price, buy_count)
THIS_TIME = datetime.now()
return
def updteTodayStock(self, db_filename, stock_code, today_str):
bsLine, data = self.labelChecker.makeCandidate(stock_code, today_str)
self.labelChecker.updateLabel(db_filename, stock_code, bsLine, data, today_str)
return
if __name__ == "__main__":
today = datetime.today()
PROJECT_HOME = os.getcwd()
RESOURCE_PATH = os.path.join(PROJECT_HOME, "resources")
hts = HTS_DAILY(RESOURCE_PATH)
today_str = today.strftime('%Y%m%d')
hts.buyRealTime(today_str)
db_filename = os.path.join(RESOURCE_PATH, "hts.db")
#today_str = "20220916"
hts.insertStockData(db_filename, stock_code, stock_name, today_str)
#hts.updteTodayStock(db_filename, stock_code, today_str)
print ("done...")

View File

@@ -749,6 +749,105 @@ class HTS:
return result
def getRealTime_DailyCheck(self, today, stock_code, stock):
objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
bConnect = objCpCybos.IsConnect
if (bConnect == 0):
print("PLUS가 정상적으로 연결되지 않음. ")
exit()
# 차트 객체 구하기
objStockChart = win32com.client.Dispatch("CpSysDib.StockChart")
objStockChart.SetInputValue(0, 'A'+stock_code) # 종목 코드
objStockChart.SetInputValue(1, ord('1')) # 1: 기간으로 조회, 2: 개수로 조회
objStockChart.SetInputValue(2, today) # 기간 조회 시, 시작일
objStockChart.SetInputValue(3, today) # 기간 조회 시, 종료일
objStockChart.SetInputValue(4, 400) # 조회 시 가져오는 Line 개수
objStockChart.SetInputValue(5, [0, 1, 2, 3, 4, 5, 8]) # 날짜,시간,시가,고가,저가,종가,거래량
objStockChart.SetInputValue(6, ord('m')) # '차트 주가 - 월(M), 주(W), 일(D), 시(H), 분(m), 초(S) 차트 요청
objStockChart.SetInputValue(7, 1)
objStockChart.SetInputValue(9, ord('1')) # 수정주가 사용
objStockChart.BlockRequest()
size = objStockChart.GetHeaderValue(3)
today_str = ""
open, close, high, low, volume = 0, 0, 0, 9999999990, 0
#print("날짜", "시간", "시가", "고가", "저가", "종가", "거래량")
start_time = datetime.strptime(today + " 090000", '%Y%m%d %H%M%S')
#
# 역순으로 결과가 오는지 확인이 필요함
#
for i in range(size-1, -1, -1):
int_day = objStockChart.GetDataValue(0, i)
int_time = objStockChart.GetDataValue(1, i)
# ymd: '2022.03.29'
# time = datetime.strptime(str(int_day)+" "+str(int_time).zfill(4)+"00", '%Y%m%d %H%M%S')
# time_str = time.strftime('%Y.%m.%d')
today_str = today[0:4] + "." + today[4:6] + "." + today[6:8]
if i == 0:
open = objStockChart.GetDataValue(2, i)
if i == size - 1:
close = objStockChart.GetDataValue(5, i)
high = max(high, objStockChart.GetDataValue(3, i))
low = min(low, objStockChart.GetDataValue(4, i))
volume = volume + objStockChart.GetDataValue(6, i)
stock['PRICE'].append(
{
"ymd": today_str,
"close": close,
"diff": -1,
"open": open,
"high": high,
"low": low,
"volume": volume,
"avg3": -1,
"avg4": -1,
"avg5": -1,
"avg6": -1,
"avg10": -1,
"avg12": -1,
"avg20": -1,
"avg36": -1,
"avg40": -1,
"avg48": -1,
"avg60": -1,
"avg120": -1,
"avg200": -1,
"avg240": -1,
"avg300": -1,
"disparity_avg5": -1,
"disparity_avg10": -1,
"disparity_avg20": -1,
"disparity_avg60": -1,
"disparity_avg120": -1,
"bolingerband_upper": -1,
"bolingerband_lower": -1,
"bolingerband_middle": -1,
"envelope_upper": -1,
"envelope_lower": -1,
"envelope_middle": -1,
"ichimokucloud_changeLine": -1,
"ichimokucloud_baseLine": -1,
"ichimokucloud_leadingSpan1": -1,
"ichimokucloud_leadingSpan2": -1,
"stochastic_fast_k": -1,
"stochastic_slow_k": -1,
"stochastic_slow_d": -1,
"rsi": -1,
"rsis": -1,
"macd": -1,
"macds": -1,
"macdo": -1,
}
)
return
def getClosePrice_realtime(self, stock_code, today):
result = {"open": [], "close": [], "high": [], "low": [], "vol": []}

View File

@@ -633,11 +633,12 @@ class DailyStatus (HTS):
else:
n = 200
today = datetime.today().strftime('%Y%m%d')
if stock_codes is not None:
for stock_code in stock_codes:
stock = self.getLastData(stock_code, n)
today = datetime.today().strftime('%Y%m%d')
self.getData(today, stock)
analyzed_day = 60
data = self.analyze(stock, analyzed_day)
@@ -661,7 +662,6 @@ class DailyStatus (HTS):
cursor.close()
conn.close()
today = datetime.today().strftime('%Y%m%d')
dailyDirName = os.path.join(self.RESOURCE_PATH, 'analysis', today, 'daily')
if os.path.exists(dailyDirName):
shutil.rmtree(dailyDirName)
@@ -682,8 +682,6 @@ class DailyStatus (HTS):
print("Analysis # :", idx, ", CODE: ", stock_code, ", NAME: ", stock_name)
stock = self.getLastData(stock_code, n)
today = datetime.today().strftime('%Y%m%d')
self.getData(today, stock)
analyzed_day = 60
data = self.analyze(stock, analyzed_day)