import os.path
import copy
import platform
if platform.system().lower().find("window") >= 0 and platform.architecture()[0] != "64bit" :
    import win32com.client
import csv
import time
import sqlite3
from datetime import datetime, timedelta
from hts.OrderItem import OrderItem

class HTS:

    objCpCybos = None
    objCpCodeMgr = None
    RESOURCE_PATH = None

    def __init__(self, RESOURCE_PATH):
        self.RESOURCE_PATH = RESOURCE_PATH
        #self.connect()
        return

    def connect(self):
        # 연결 여부 체크
        self.objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
        bConnect = self.objCpCybos.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            exit()
        return

    def all_stocks(self):
        # 종목코드 리스트 구하기
        self.objCpCodeMgr = win32com.client.Dispatch("CpUtil.CpCodeMgr")
        codeList = self.objCpCodeMgr.GetStockListByMarket(1)  # 거래소
        codeList2 = self.objCpCodeMgr.GetStockListByMarket(2)  # 코스닥

        print("거래소 종목코드", len(codeList))
        for i, code in enumerate(codeList):
            secondCode = self.objCpCodeMgr.GetStockSectionKind(code)
            name = self.objCpCodeMgr.CodeToName(code)
            stdPrice = self.objCpCodeMgr.GetStockStdPrice(code)
            print(i, code, secondCode, stdPrice, name)

        print("코스닥 종목코드", len(codeList2))
        for i, code in enumerate(codeList2):
            secondCode = self.objCpCodeMgr.GetStockSectionKind(code)
            name = self.objCpCodeMgr.CodeToName(code)
            stdPrice = self.objCpCodeMgr.GetStockStdPrice(code)
            print(i, code, secondCode, stdPrice, name)

        print("거래소 + 코스닥 종목코드 ", len(codeList) + len(codeList2))
        return

    # 차트 데이터 구하기
    def getChartData(self, stock_code):
        # 차트 객체 구하기
        objStockChart = win32com.client.Dispatch("CpSysDib.StockChart")

        objStockChart.SetInputValue(0, 'A'+stock_code)  # 종목 코드 - 삼성전자
        objStockChart.SetInputValue(1, ord('2'))  # 개수로 조회
        objStockChart.SetInputValue(4, 100)  # 최근 100일 치
        objStockChart.SetInputValue(5, [0, 2, 3, 4, 5, 8])  # 날짜,시가,고가,저가,종가,거래량
        objStockChart.SetInputValue(6, ord('D'))  # '차트 주가 - 일간 차트 요청
        objStockChart.SetInputValue(9, ord('1'))  # 수정주가 사용
        objStockChart.BlockRequest()

        len = objStockChart.GetHeaderValue(3)

        print("날짜", "시가", "고가", "저가", "종가", "거래량")
        print("==============================================-")

        for i in range(len):
            day = objStockChart.GetDataValue(0, i)
            open = objStockChart.GetDataValue(1, i)
            high = objStockChart.GetDataValue(2, i)
            low = objStockChart.GetDataValue(3, i)
            close = objStockChart.GetDataValue(4, i)
            vol = objStockChart.GetDataValue(5, i)
            print(day, open, high, low, close, vol)

        return

    # 주식 현재가 조회
    def currentStock(self, stock_code):
        # 현재가 객체 구하기
        self.objStockMst = win32com.client.Dispatch("DsCbo1.StockMst")
        self.objStockMst.SetInputValue(0, 'A'+stock_code)  # 종목 코드
        self.objStockMst.BlockRequest()

        # 현재가 통신 및 통신 에러 처리
        rqStatus = self.objStockMst.GetDibStatus()
        rqRet = self.objStockMst.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            exit()

        # 현재가 정보 조회
        code = self.objStockMst.GetHeaderValue(0)  # 종목코드
        name = self.objStockMst.GetHeaderValue(1)  # 종목명
        time = self.objStockMst.GetHeaderValue(4)  # 시간
        cprice = self.objStockMst.GetHeaderValue(11)  # 종가
        diff = self.objStockMst.GetHeaderValue(12)  # 대비
        open = self.objStockMst.GetHeaderValue(13)  # 시가
        high = self.objStockMst.GetHeaderValue(14)  # 고가
        low = self.objStockMst.GetHeaderValue(15)  # 저가
        offer = self.objStockMst.GetHeaderValue(16)  # 매도호가
        bid = self.objStockMst.GetHeaderValue(17)  # 매수호가
        vol = self.objStockMst.GetHeaderValue(18)  # 거래량
        vol_value = self.objStockMst.GetHeaderValue(19)  # 거래대금

        # 예상 체결관련 정보
        exFlag = self.objStockMst.GetHeaderValue(58)  # 예상체결가 구분 플래그
        exPrice = self.objStockMst.GetHeaderValue(55)  # 예상체결가
        exDiff = self.objStockMst.GetHeaderValue(56)  # 예상체결가 전일대비
        exVol = self.objStockMst.GetHeaderValue(57)  # 예상체결수량

        print("코드", code)
        print("이름", name)
        print("시간", time)
        print("종가", cprice)
        print("대비", diff)
        print("시가", open)
        print("고가", high)
        print("저가", low)
        print("매도호가", offer)
        print("매수호가", bid)
        print("거래량", vol)
        print("거래대금", vol_value)

        if (exFlag == ord('0')):
            print("장 구분값: 동시호가와 장중 이외의 시간")
        elif (exFlag == ord('1')):
            print("장 구분값: 동시호가 시간")
        elif (exFlag == ord('2')):
            print("장 구분값: 장중 또는 장종료")

        print("예상체결가 대비 수량")
        print("예상체결가", exPrice)
        print("예상체결가 대비", exDiff)
        print("예상체결수량", exVol)

        return

    # 주식 현금 매수주문
    def requestOrder(self, type, stock_code, count, price):
        # type = 2: buy, type=1: sell
        # 주문 초기화
        objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
        initCheck = objTrade.TradeInit(0)
        if (initCheck != 0):
            print("주문 초기화 실패")
            exit()

        # 주식 매수 주문
        acc = objTrade.AccountNumber[0]  # 계좌번호
        accFlag = objTrade.GoodsList(acc, 1)  # 주식상품 구분
        # acc = "782446178"
        # accFlag[0] = "01"
        objStockOrder = win32com.client.Dispatch("CpTrade.CpTd0311")
        objStockOrder.SetInputValue(0, type.value)  # 1: 매도, 2: 매수
        objStockOrder.SetInputValue(1, acc)  # 계좌번호
        objStockOrder.SetInputValue(2, accFlag[0])  # 상품구분 - 주식 상품 중 첫번째
        objStockOrder.SetInputValue(3, "A"+stock_code)  # 종목코드
        objStockOrder.SetInputValue(4, count)  # 매수수량 count주
        objStockOrder.SetInputValue(5, price)  # 주문단가  - price 원
        objStockOrder.SetInputValue(7, "0")  # 주문 조건 구분 코드, 0: 기본 1: IOC 2:FOK
        objStockOrder.SetInputValue(8, "01")  # 주문호가 구분코드 - 01: 보통

        # 매수 주문 요청
        nRet = objStockOrder.BlockRequest()
        if (nRet != 0):
            print("order error", nRet)
            return None

        rqStatus = objStockOrder.GetDibStatus()
        rqRet = objStockOrder.GetDibMsg1()
        print("통신상태", rqStatus, rqRet)
        if rqStatus != 0:
            return None

        orderNum = objStockOrder.GetHeaderValue(0)

        if (type == "1"):
            print ("(SELL", count, price, ")")
        else:
            print ("(BUY", count, price, ")")
        return orderNum

    # 계좌 잔고 확인
    def requstJango(self):
        jangoDic = {}

        objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
        initCheck = objTrade.TradeInit(0)
        if (initCheck != 0):
            print("주문 초기화 실패")
            exit()

        # 주식 매수 주문
        acc = objTrade.AccountNumber[0]  # 계좌번호
        accFlag = objTrade.GoodsList(acc, 1)  # 주식상품 구분

        objRq = win32com.client.Dispatch("CpTrade.CpTd6033")

        objRq.SetInputValue(0, acc)  # 계좌번호
        objRq.SetInputValue(1, accFlag[0])  # 상품구분 - 주식 상품 중 첫번째
        objRq.SetInputValue(2, 50)  # 요청 건수(최대 50)
        dicflag1 = {ord(' '): '현금',
                         ord('Y'): '융자',
                         ord('D'): '대주',
                         ord('B'): '담보',
                         ord('M'): '매입담보',
                         ord('P'): '플러스론',
                         ord('I'): '자기융자',
                         }
        while True:
            objRq.BlockRequest()
            # 통신 및 통신 에러 처리
            rqStatus = objRq.GetDibStatus()
            rqRet = objRq.GetDibMsg1()
            #print("통신상태", rqStatus, rqRet)
            if rqStatus != 0:
                return False

            cnt = objRq.GetHeaderValue(7)
            if cnt > 3:
                return jangoDic

            for i in range(cnt):
                item = {}
                code = objRq.GetDataValue(12, i)  # 종목코드
                item['종목코드'] = code
                item['종목명'] = objRq.GetDataValue(0, i)  # 종목명
                item['대출일'] = objRq.GetDataValue(2, i)  # 대출일
                item['잔고수량'] = objRq.GetDataValue(7, i)  # 체결잔고수량
                item['매도가능'] = objRq.GetDataValue(15, i)
                item['장부가'] = objRq.GetDataValue(17, i)  # 체결장부단가
                # item['평가금액'] = self.objRq.GetDataValue(9, i)  # 평가금액(천원미만은 절사 됨)
                # item['평가손익'] = self.objRq.GetDataValue(11, i)  # 평가손익(천원미만은 절사 됨)
                # 매입금액 = 장부가 * 잔고수량
                item['매입금액'] = item['장부가'] * item['잔고수량']
                item['현재가'] = 0
                item['대비'] = 0
                item['거래량'] = 0

                # 잔고 추가
                # key = (code, item['현금신용'],item['대출일'] )
                key = code
                jangoDic[key] = item

                if len(jangoDic) >= 3:  # 최대 3 종목만,
                    break

            if len(jangoDic) >= 3:
                break

            if (objRq.Continue == False):
                break

        check = False
        for item in jangoDic:
            if item:
                check = True
                break
        if not check:
            return None
        return jangoDic

    #  예약 주문 내역 조회 및 미체결 리스트 구하기
    def requestOrderList(self):
        # type = 2: buy, type=1: sell
        orderList = []
        # 주문 초기화
        objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
        initCheck = objTrade.TradeInit(0)
        if (initCheck != 0):
            print("주문 초기화 실패")
            exit()

        # 주식 매수 주문
        acc = objTrade.AccountNumber[0]  # 계좌번호
        accFlag = objTrade.GoodsList(acc, 1)  # 주식상품 구분

        objResult = win32com.client.Dispatch("CpTrade.CpTd5339")
        objResult.SetInputValue(0, acc)  # 계좌번호
        objResult.SetInputValue(1, accFlag[0])  # 상품구분 - 주식 상품 중 첫번째
        objResult.SetInputValue(4, "0") # 전체
        objResult.SetInputValue(5, "1") # 정렬 기준 - 역순
        objResult.SetInputValue(6, "0") # 전체
        objResult.SetInputValue(7, 20) # 요청개수 - 최대 20개

        while True:
            ret = objResult.BlockRequest()
            if objResult.GetDibStatus() != 0:
                print("통신상태", objResult.GetDibStatus(), objResult.GetDibMsg1())
                return False

            if (ret == 2 or ret == 3):
                print("통신 오류", ret)
                return False

            # 통신 초과 요청 방지에 의한 요류 인 경우
            while (ret == 4):  # 연속 주문 오류 임. 이 경우는 남은 시간동안 반드시 대기해야 함.
                time.sleep(1)
                ret = objResult.BlockRequest()

            # 수신 개수
            cnt = objResult.GetHeaderValue(5)
            print("[Cp5339] 수신 개수 ", cnt)
            if cnt == 0:
                break

            for i in range(cnt):
                item = OrderItem()
                item.orderNum = objResult.GetDataValue(1, i)
                item.orderPrev = objResult.GetDataValue(2, i)
                item.code = objResult.GetDataValue(3, i)  # 종목코드
                item.name = objResult.GetDataValue(4, i)  # 종목명
                item.orderDesc = objResult.GetDataValue(5, i)  # 주문구분내용
                item.amount = objResult.GetDataValue(6, i)  # 주문수량
                item.price = objResult.GetDataValue(7, i)  # 주문단가
                item.ContAmount = objResult.GetDataValue(8, i)  # 체결수량
                item.credit = objResult.GetDataValue(9, i)  # 신용구분
                item.modAvali = objResult.GetDataValue(11, i)  # 정정취소 가능수량
                item.buysell = objResult.GetDataValue(13, i)  # 매매구분코드
                item.creditdate = objResult.GetDataValue(17, i)  # 대출일
                item.orderFlagDesc = objResult.GetDataValue(19, i)  # 주문호가구분코드내용
                item.orderFlag = objResult.GetDataValue(21, i)  # 주문호가구분코드

                orderList.append(item)

                # 연속 처리 체크 - 다음 데이터가 없으면 중지
            if objResult.Continue == False:
                print("[Cp5339] 연속 조회 여부: 다음 데이터가 없음")
                break

        return orderList

    #  미체결 취소하기
    def cancelOrderList(self, orderList=None):

        if len(orderList) < 1:
            return

        objTrade = win32com.client.Dispatch("CpTrade.CpTdUtil")
        initCheck = objTrade.TradeInit(0)
        if (initCheck != 0):
            print("주문 초기화 실패")
            exit()
        acc = objTrade.AccountNumber[0]  # 계좌번호
        accFlag = objTrade.GoodsList(acc, 1)  # 주식상품 구분

        objCancelOrder = win32com.client.Dispatch("CpTrade.CpTd0314")  # 취소

        onums = []
        codes = []
        amounts = []
        for item in orderList:
            onums.append(item.orderNum)
            codes.append(item.code)
            amounts.append(item.amount)

        for i in range(len(onums)):
            ordernum = onums[i]
            code = codes[i]
            amount = amounts[i]
            objCancelOrder.SetInputValue(1, ordernum)  # 원주문 번호 - 정정을 하려는 주문 번호
            objCancelOrder.SetInputValue(2, acc)  # 상품구분 - 주식 상품 중 첫번째
            objCancelOrder.SetInputValue(3, accFlag[0])  # 상품구분 - 주식 상품 중 첫번째
            objCancelOrder.SetInputValue(4, code)  # 종목코드
            objCancelOrder.SetInputValue(5, amount)  # 정정 수량, 0 이면 잔량 취소임

            # 취소주문 요청
            ret = objCancelOrder.BlockRequest()
            print("[CpRPOrder/BlockRequestCancel] 주문결과", objCancelOrder.GetDibStatus(), objCancelOrder.GetDibMsg1())
            if objCancelOrder.GetDibStatus() != 0:
                break

        return

    # 주식 현재가 조회
    def writeStockData(self, stock_code, today):
        objCpCybos = win32com.client.Dispatch("CpUtil.CpCybos")
        bConnect = objCpCybos.IsConnect
        if (bConnect == 0):
            print("PLUS가 정상적으로 연결되지 않음. ")
            exit()

        # 차트 객체 구하기
        objStockChart = win32com.client.Dispatch("CpSysDib.StockChart")

        timecheck_filename = os.path.join(self.RESOURCE_PATH, "hts", stock_code+"_"+today+".csv")
        outfp = open(timecheck_filename, mode="w", encoding="utf-8")
        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)

        outfp.write("%s,%s,%s,%s,%s,%s,%s\n" % ("날짜", "시간", "시가", "고가", "저가", "종가", "거래량"))
        for i in range(size - 1, -1, -1):
            day = objStockChart.GetDataValue(0, i)
            time = objStockChart.GetDataValue(1, i)
            start = objStockChart.GetDataValue(2, i)
            high = objStockChart.GetDataValue(3, i)
            low = objStockChart.GetDataValue(4, i)
            close = objStockChart.GetDataValue(5, i)
            vol = objStockChart.GetDataValue(6, i)
            outfp.write("%d,%s,%d,%d,%d,%d,%d\n" % (day, str(time).zfill(4), start, high, low, close, vol))
        outfp.close()

        return

    def getStockInfo(self, stock_code, today):
        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)

        data = []
        for i in range(size - 1, -1, -1):
            day = objStockChart.GetDataValue(0, i)
            time = objStockChart.GetDataValue(1, i)
            start = objStockChart.GetDataValue(2, i)
            high = objStockChart.GetDataValue(3, i)
            low = objStockChart.GetDataValue(4, i)
            close = objStockChart.GetDataValue(5, i)
            vol = objStockChart.GetDataValue(6, i)

            data.append([day, str(time).zfill(4), start, high, low, close, vol])

        return data

    def insertStockData(self, db_filename, stock_code, stock_name, today):
        tableName = 'hts'
        conn = sqlite3.connect(db_filename)
        cursor = conn.cursor()

        # 테이블 생성
        cursor.execute("CREATE TABLE IF NOT EXISTS " + tableName + " (CODE text, NAME text, ymd text, hms text, close REAL, open REAL, high REAL, low REAL, volume REAL, label INTEGER DEFAULT 0)")

        # 키 생성
        create_key = "CREATE INDEX IF NOT EXISTS " + tableName + "_idx on " + tableName + " (CODE, ymd, hms) "
        cursor.execute(create_key)

        conn.commit()
        cursor.close()
        conn.close()

        items = self.getStockInfo(stock_code, today)

        conn = sqlite3.connect(db_filename)
        cursor = conn.cursor()
        idx = 0
        for item in items:
            ymd = item[0]
            hms = item[1]
            open = item[2]
            high = item[3]
            low = item[4]
            close = item[5]
            volume = item[6]

            idx += 1

            cursor.execute('DELETE FROM ' + tableName + ' WHERE CODE=? and ymd=? and hms=?', (stock_code, ymd, hms,))
            cursor.execute("INSERT INTO " + tableName + "(CODE, NAME, ymd, hms, close, open, high, low, volume) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)", (stock_code, stock_name, ymd, hms, close, open, high, low, volume))

        conn.commit()
        cursor.close()
        conn.close()
        print("insert...", stock_code, stock_name, today)

        return


    def write(self, day, result):
        #날짜,시간,시가,고가,저가,종가,거래량
        #20210909,900,2070,2070,2070,2070,0

        outFp = open(day+".csv", mode="w", encoding="UTF-8")
        outFp.write("날짜,시간,시가,고가,저가,종가,거래량\n")
        for i in range(len(result["time"])):
            outFp.write("%s,%s,%s,%s,%s,%s,%s\n"%(
                result["time"][i].strftime('%Y%m%d'),
                result["time"][i].strftime('%H%M'),
                result["open"][i],
                result["high"][i],
                result["low"][i],
                result["close"][i],
                result["vol"][i]))
        outFp.close()
        return

    def getCSV(self, fileName, result):
        with open(fileName, 'r', encoding='utf-8') as infp:
            reader = csv.reader(infp)
            next(reader)

            for rows in reader:
                days = rows[0]  # hts.날짜
                time = rows[1]  # hts.시간
                open_v = rows[2]  # hts.시가
                high = rows[3]  # hts.고가
                low = rows[4]  # hts.저가
                close = rows[5]  # hts.종가
                vol = rows[6]  # hts.거래량

                temp = datetime.strptime(str(days) + " " + str(time).zfill(4) + "00", '%Y%m%d %H%M%S')
                #if temp < start_time:
                #    continue

                result["time"].append(temp)
                result["open"].append(int(open_v))
                result["close"].append(int(close))
                result["high"].append(int(high))
                result["low"].append(int(low))
                result["vol"].append(int(vol))
        return

    def updateLabel(self, db_filename, stock_code, bsLine, data, ymd):
        tableName = 'hts'
        conn = sqlite3.connect(db_filename)
        cursor = conn.cursor()

        cursor.execute('Update ' + tableName + ' set label=? WHERE CODE=? and ymd=?', (0, stock_code, ymd,))

        for i in range(len(bsLine["buy"])):
            if bsLine["buy"][i] > 0:
                ymd = data['date'][i].strftime('%Y%m%d')
                hms = data['date'][i].strftime('%H%M')
                cursor.execute('Update ' + tableName + ' set label=? WHERE CODE=? and ymd=? and hms=?', (2, stock_code, ymd, hms))

        for i in range(len(bsLine["sell"])):
            if bsLine["sell"][i] > 0:
                ymd = data['date'][i].strftime('%Y%m%d')
                hms = data['date'][i].strftime('%H%M')
                cursor.execute('Update ' + tableName + ' set label=? WHERE CODE=? and ymd=? and hms=?', (1, stock_code, ymd, hms))

        conn.commit()
        cursor.close()
        conn.close()
        print("update...", stock_code, ymd)
        return

    def clearLabel(self, db_filename, stock_code, ymd):
        tableName = 'hts'
        conn = sqlite3.connect(db_filename)
        cursor = conn.cursor()

        cursor.execute('update ' + tableName + ' set label=? WHERE CODE=? and ymd=? ', (0, stock_code, ymd,))

        conn.commit()
        cursor.close()
        conn.close()
        print("delete...", stock_code, ymd)
        return

    def makeLabel(self, db_filename, stock_code, ymd, hms, label):
        tableName = 'hts'
        conn = sqlite3.connect(db_filename)
        cursor = conn.cursor()

        cursor.execute('Update ' + tableName + ' set label=? WHERE CODE=? and ymd=? and hms=?', (label, stock_code, ymd, hms,))

        conn.commit()
        cursor.close()
        conn.close()
        print("update...", stock_code, ymd, hms, label)
        return

    def getYMD(self, stock_code):
        tableName = 'hts'
        conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "hts.db"))
        cursor = conn.cursor()

        result = []
        cursor.execute('SELECT distinct ymd FROM ' + tableName + ' WHERE CODE=? order by ymd', (stock_code,))
        db_result = cursor.fetchall()
        for rows in db_result:
            ymd = rows[0]  # hts.날짜

            result.append(ymd)

        return result

    def getDBData(self, stock_code, day, result):
        tableName = 'hts'
        conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "hts.db"))
        cursor = conn.cursor()

        cursor.execute('SELECT ymd, hms, open, high, low, close, volume, label FROM ' + tableName + ' WHERE CODE=? and ymd=? order by ymd, hms', (stock_code, day,))
        db_result = cursor.fetchall()
        for rows in db_result:
            ymd = rows[0]  # hts.날짜
            hms = rows[1]  # hts.시간
            open = rows[2]  # hts.시가
            high = rows[3]  # hts.고가
            low = rows[4]  # hts.저가
            close = rows[5]  # hts.종가
            vol = rows[6]  # hts.거래량
            label = 0 if rows[7] is None else rows[7] # hts.매매구분

            temp = datetime.strptime(str(ymd) + " " + str(hms).zfill(4) + "00", '%Y%m%d %H%M%S')

            result["time"].append(temp)
            result["open"].append(int(open))
            result["close"].append(int(close))
            result["high"].append(int(high))
            result["low"].append(int(low))
            result["vol"].append(int(vol))
            result["label"].append(int(label))

        return

    def isValidYMD(self, stock_code, day):
        tableName = 'hts'
        conn = sqlite3.connect(os.path.join(self.RESOURCE_PATH, "hts.db"))
        cursor = conn.cursor()

        cursor.execute('SELECT ymd, count(*) as cnt FROM ' + tableName + ' WHERE CODE=? and ymd=?', (stock_code, day,))
        db_result = cursor.fetchone()
        if db_result[1] > 0:
            return True
        return False

    def getLastData(self, stock_code, today, n=3):
        result = {"check": set(),
                  "time": [],
                  "open": [],
                  "close": [],
                  "high": [],
                  "low": [],
                  "vol": [],
                  "label": []}

        days = []
        for i in range(1, 100):
            last_day = (datetime.strptime(today, '%Y%m%d') - timedelta(i)).strftime('%Y%m%d')
            isValid = self.isValidYMD(stock_code, last_day)
            if isValid:
                days.append(last_day)
                if len(days) >= n:
                    break

        days = sorted(days)
        for day in days:
            self.getDBData(stock_code, day, result)

        return result

    # 주식 현재가 조회
    def getRealTime(self, stock_code, today, LAST_DATA=None):
        if LAST_DATA is not None:
            result = copy.deepcopy(LAST_DATA)
        else:
            result = {"check": set(), "time": [], "open": [], "close": [], "high": [], "low": [], "vol": [], "label": []}

        #### real time에서 아직 저장된 것이 없기 때문에 result는 아무것도 채워지지 않는다.
        self.getDBData(stock_code, today, result)


        int_given_day = int(today)
        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)

        #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)

            if int_day < int_given_day:
                continue
            time = datetime.strptime(str(int_day)+" "+str(int_time).zfill(4)+"00", '%Y%m%d %H%M%S')
            if time < start_time:
                continue

            open = objStockChart.GetDataValue(2, i)
            close = objStockChart.GetDataValue(5, i)
            high = objStockChart.GetDataValue(3, i)
            low = objStockChart.GetDataValue(4, i)
            vol = objStockChart.GetDataValue(6, i)

            if len(result["check"]) == 0:
                result["check"].add(start_time)
                result["time"].append(start_time)
                result["open"].append(open)
                result["close"].append(open)
                result["high"].append(open)
                result["low"].append(open)
                result["vol"].append(0)
                result["label"].append(0)

            if time not in result["check"]:
                result["check"].add(time)
                result["time"].append(time)

                result["open"].append(open)
                result["close"].append(close)
                result["high"].append(high)
                result["low"].append(low)
                result["vol"].append(vol)
                result["label"].append(0)

        return result