티스토리 뷰

* 데이터 출처 : 키움증권

<주요 기능>

1. 키움증권의 Open API를 이용하여 데이터 가져오기

2. 가져온 데이터를 용도에 맞춰 편집하기

3. 편집함 데이터를 저장하기

 

from pykiwoom.kiwoom import *
import pyautogui
import time
import cConstants
import requests
import json
from datetime import datetime, timedelta
from cBMailer import cBMailer
import os
from pandas import pandas as pd
from pandas import DataFrame
from cKakaoAPI import cKakaoAPI

class BStockTrader12:
    RequestInterval = 4.0
    KospiItems = []
    KosdaqItems = []
    StartItem = None
    KakaoAPI = None
    Tablename_KOSPI = 'Daily_KOSPI2'
    Tablename_KOSDAQ = 'Daily_KOSDAQ2'
    INTERVAL_MAIL = 1800
    Time_Mail = 0 # latest mailing time
    Time_KiwoomRequest = 0

    def __init__(self, startItem=None):
        self.kiwoom = Kiwoom()
        self.kiwoom.CommConnect(block=True)
        if startItem: self.StartItem = startItem
        self.CreateTable(self.Tablename_KOSPI)
        self.CreateTable(self.Tablename_KOSDAQ)
        try:
            self.KakaoAPI = cKakaoAPI()
        except:
            print("[???] Except in cKakaoAPI()")

    def Close(self):
        self.kiwoom.CommTerminate()

    def CreateTable(self, tableName):
        ServerURL = cConstants.URL_BSTSERVER_1
        requestHeader = cConstants.REQUESTHEADER

        print('Loading collection list ...')
        data1 = {
            'RequestType': 'CreateTable',
            'TableType': 'Daily',
            'Tablename': tableName
        }
        res1 = requests.post(ServerURL, headers=requestHeader, data=data1)
        print(res1.text)

    def SetItems(self):
        kospiCode = '0'
        kosdaqCode = '10'

        itemCodes_KOSPI = self.kiwoom.GetCodeListByMarket(kospiCode)
        itemCodes_KOSDAQ = self.kiwoom.GetCodeListByMarket(kosdaqCode)
        print('KOSPI:', len(itemCodes_KOSPI))
        itemIndex1 = -1
        for itemCode in itemCodes_KOSPI:
            itemIndex1 += 1
            name = self.kiwoom.GetMasterCodeName(itemCode)
            stockCount = self.kiwoom.GetMasterListedStockCnt(itemCode)
            listedDate = self.kiwoom.GetMasterListedStockDate(itemCode)
            print(itemCode, ' : ', name)
            itemInfo = {
                'market': 'KOSPI',
                'code': str(itemCode),
                'name': name,
                'stockCount': stockCount,
                'listedDate': listedDate
                }
            self.KospiItems.append(itemInfo)

        for itemCode in itemCodes_KOSDAQ:
            itemIndex1 += 1
            name = self.kiwoom.GetMasterCodeName(itemCode)
            stockCount = self.kiwoom.GetMasterListedStockCnt(itemCode)
            listedDate = self.kiwoom.GetMasterListedStockDate(itemCode)
            print(itemCode, ' : ', name)
            itemInfo = {
                'market': 'KOSDAQ',
                'code': itemCode,
                'name': name,
                'stockCount': stockCount,
                'listedDate': listedDate
                }
            self.KosdaqItems.append(itemInfo)
            
        self.UpdateItems2Server(self.KospiItems, self.Tablename_KOSPI)
        self.UpdateItems2Server(self.KosdaqItems, self.Tablename_KOSDAQ)
   
    def UpdateItems2Server(self, marketItems, tableName):
        ServerURL = cConstants.URL_BSTSERVER_1
        requestHeader = cConstants.REQUESTHEADER

        data0 = {
            'RequestType': 'LoadDailyDatas',
            'Tablename': tableName,
            'DataType': 'ba00',
            'DataNumber': 2000
        }
        itemCodes = []
        try:
            res1 = requests.post(ServerURL, headers=requestHeader, data=data0)
            if cConstants.IsTesting: print(res1.text)
            rxData = res1.json()
            Results = rxData['Results']
            for rst1 in Results:
                itemCodes.append(rst1['ItemCode'])
        except:
            print("[Exception in UpdateItems2Server()")
            itemCodes = []
            #return None
        
        date0 = datetime.now()
        datename0 = date0.strftime("%Y%m%d")

        uploadDataL = []
        for itemInfo in marketItems:
            if itemInfo['code'] in itemCodes: continue
            uploadData1 = {
                'ItemCode': itemInfo['code'],
                'ItemName': itemInfo['name'],
                'DDate': datename0,
                'DataType': 'ba00',
                'Data0': itemInfo['stockCount'],
                #'Data1': itemInfo['listedDate']
            }
            #print(uploadData1)
            uploadDataL.append(uploadData1)

        transmitedData = {
            'Tablename': tableName,
            'Datas' : json.dumps(uploadDataL)
        }
        self.UploadDailyData(transmitedData)


    def SetAccountInfo(self):
        account_num = self.kiwoom.GetLoginInfo("ACCOUNT_CNT")        # 전체 계좌수
        accounts = self.kiwoom.GetLoginInfo("ACCNO")                 # 전체 계좌 리스트
        user_id = self.kiwoom.GetLoginInfo("USER_ID")                # 사용자 ID
        user_name = self.kiwoom.GetLoginInfo("USER_NAME")            # 사용자명
        keyboard = self.kiwoom.GetLoginInfo("KEY_BSECGB")            # 키보드보안 해지여부
        firewall = self.kiwoom.GetLoginInfo("FIREW_SECGB")           # 방화벽 설정 여부

        self.AccountInfo = {
            'accountNumber': account_num,
            'accountList': accounts,
            'userId': user_id,
            'userName': user_name,
            'keyboard': keyboard,
            'firewall': firewall
        }
        print("[AccountInfo]", self.AccountInfo)
        self.AccountNo = accounts[0]

    def AnalyzeEachItem_Method1(self, itemInfo, itemNo=-1):
        rsp1 = self.LoadDailyData_ba01(itemInfo)
        if rsp1:
            length11 = len(rsp1)
            day0 = rsp1[0].get('DDate')
            print('[day0]', day0)
        else:
            day0 = None

        date0 = datetime.now()
        datename0 = date0.strftime("%Y%m%d")
        hour1 = int(date0.strftime("%H"))
        if(hour1 >= 18):
            if day0:
               if day0 > datename0: return None
        else:
            if day0:
               if day0 >= datename0: return None

        thisCode = itemInfo['code']
        thisName = itemInfo['name']

        try:
            dailyDatas = self.SetData_1day(itemInfo)
        except:
            message4Kakao = "[???] Exception in daily-datas for [ItemName]"+thisName+", [ItemCode]"+thisCode
            if self.KakaoAPI: self.KakaoAPI.SendMessage(message4Kakao)
            return None
        if len(dailyDatas) < 10:
            message4Kakao = "[!] Little daily-datas for [ItemName]"+thisName+", [ItemCode]"+thisCode
            if self.KakaoAPI: self.KakaoAPI.SendMessage(message4Kakao)
            return None
        print("[dailyDatas[0]]", dailyDatas[0])
        try:
            bunDatas = self.SetData_1min(itemInfo, day0)
        except:
            message4Kakao = "[???] Exception in bun-datas for [ItemName]"+thisName+", [ItemCode]"+thisCode
            if self.KakaoAPI: self.KakaoAPI.SendMessage(message4Kakao)
            return None
        if len(bunDatas) < 10:
            message4Kakao = "[!] Little bun-datas for [ItemName]"+thisName+", [ItemCode]"+thisCode
            if self.KakaoAPI: self.KakaoAPI.SendMessage(message4Kakao)
            return None
        print("[bunDatas[0]]", bunDatas[0])

        method1Datas = []
        mailData = None
        time1 = time.time()
        dataCount = 0
        index2 = -1
        for index1 in range(len(dailyDatas)-2, -1, -1):
            data1 = dailyDatas[index1]
            date1 = data1['Da']
            if hour1 < 18 and date1 >= datename0: break
            if day0:
                if date1 <= day0: continue
            yesterdayPrice = dailyDatas[index1+1]['CP']
            datas2 = []
            count2 = 0
            if cConstants.IsTesting: print('[Date1]', date1)
            if index2 < 0:
                startIndex = len(bunDatas)-1
            else:
                startIndex = index2
            for index2 in range(startIndex, -1, -1):
                data2 = bunDatas[index2]
                date2 = data2['day']
                if date2 < date1: 
                    continue
                elif date2 == date1: 
                    finalDate = date2
                    datas2.append(data2)
                    count2 += 1
                    if index2 != 0:continue

                if not datas2: break

                data2 = self.AnalyzeData_10080(datas2, yesterdayPrice)
                method1Data = {
                    'ItemCode': thisCode,
                    'ItemName': thisName,
                    'DataType': 'ba01',
                    'DDate': date1,
                    'Data0': json.dumps(data1),
                }
                if data2: method1Data['Data1'] = json.dumps(data2)
                if cConstants.IsTesting: print(method1Data)
                method1Datas.append(method1Data)
                dataCount += 1
                if dataCount >=10:
                    dataCount = 0
                    if itemInfo['market']=='KOSPI': tableName = self.Tablename_KOSPI
                    elif itemInfo['market']=='KOSDAQ': tableName =  self.Tablename_KOSDAQ
                    else:
                        print("[!!!] Unknown MARKET")
                        return None
                    transmitedData = {
                        'Tablename': tableName,
                        'Datas' : json.dumps(method1Datas)
                    }
                    self.UploadDailyData(transmitedData)
                    mailData = method1Datas
                    method1Datas = []
                break


        if method1Datas:
            if itemInfo['market']=='KOSPI': tableName = self.Tablename_KOSPI
            elif itemInfo['market']=='KOSDAQ': tableName = self.Tablename_KOSDAQ
            else:
                print("[!!!] Unknown MARKET")
                return None
            transmitedData = {
                'Tablename': tableName,
                'Datas' : json.dumps(method1Datas)
            }
            self.UploadDailyData(transmitedData)
            mailData = method1Datas

        if mailData:
            message4Kakao = "[ItemCode]" + thisCode
            message4Kakao += ", [ItemName]" + thisName
            message4Kakao += ", [final date]" + finalDate
            try:
                if self.KakaoAPI: self.KakaoAPI.SendMessage(message4Kakao)
            except:
                print("[???] Except in KakaoAPI.SendMessage()")
            message1 = '[BST] Method1 completed ==>' + itemInfo['code'] +'-' + itemInfo['name'] + 'with' + str(itemNo)
            content1 = {
                'Receivers': 'bilient2014@gmail.com, ideas2biz@outlook.com',
                'Body': json.dumps(mailData),
                'Subject': message1
            }
            try:
                time0 = time.time()
                if (time0 - self.Time_Mail) > self.INTERVAL_MAIL:
                    self.Time_Mail = time0
                    mailer1 = cBMailer();
                    mailer1.SendMail(content1)
            except:
                print("[???] Except in mailer1.SendMail()")

            method1Datas = []



    def UploadDailyData(self, data0):
        ServerURL = cConstants.URL_BSTSERVER_1
        requestHeader = cConstants.REQUESTHEADER

        print('Uploading daily data ...')
        data0['RequestType'] ='InsertDailyData'
        res1 = requests.post(ServerURL, headers=requestHeader, data=data0)
        print(res1.text)
        pass

    def LoadDailyData_ba01(self, itemInfo):
        ServerURL = cConstants.URL_BSTSERVER_1
        requestHeader = cConstants.REQUESTHEADER

        if itemInfo['market']=='KOSPI': tableName = self.Tablename_KOSPI
        elif itemInfo['market']=='KOSDAQ': tableName = self.Tablename_KOSDAQ

        print('Loading daily data ...')
        data0 = {
            'RequestType': 'LoadDailyDatas',
            'Tablename': tableName,
            'ItemCode': itemInfo['code'],
            'DataType': 'ba01',
            'DataNumber': 10
        }

        try:
            res1 = requests.post(ServerURL, headers=requestHeader, data=data0)
            if cConstants.IsTesting: print(res1.text)
            articleList = res1.json()
            return articleList['Results']
        except:
            return None
#------------------------------------------------------------------
    def SetData_1day(self, ItemInfo):
        trCode = 'opt10081'
        retDatas1 = self.GetData_10081(ItemInfo)

        return retDatas1

    def GetData_10081(self, itemInfo):
        trCode = 'opt10081'
        print(trCode, ' :', itemInfo['code'], ' ... ', )
        Data_10081 = []
        itemCode = itemInfo['code']
        time1 = time.time()
        time1 = self.WaitRequestInterval(time1)
        df = self.kiwoom.block_request(trCode,
                                    종목코드=itemCode,
                                    #기준일자= '20190101',
                                    output="주식일봉차트조회요청",
                                    next=0
        )
        print(df.head())
        rets1 = self.ExtractData_10081(df)
        for ret1 in rets1:
            Data_10081.append(ret1)

        #print("[Length : 10081]", len(Data_10081))
        #print("[Data0]", Data_10081[0])
        #print("[DataFinal]", Data_10081[len(Data_10081)-1])
        if itemInfo: return Data_10081

        while self.kiwoom.tr_remained:
            time1 = self.WaitRequestInterval(time1)
            #print("[time1]", time1)
            df = self.kiwoom.block_request(trCode,
                                        종목코드=itemCode,
                                        #기준일자= '20190101',
                                        output="주식일봉차트조회요청",
                                        next=0
            )
            #print(df.head())
            try:
                rets1 = self.ExtractData_10081(df)
            except:
                break;
            for ret1 in rets1:
                Data_10081.append(ret1)

        print('length :', len(Data_10081))

        return Data_10081

    def ExtractData_10081(seslf, data0):
        codes = data0['종목코드'] # 종목코드
        currents = data0['현재가'] # 현재가
        amounts = data0['거래량'] # 거래량
        moneys = data0['거래대금'] # 거래대금
        dates = data0['일자'] # 일자
        starts = data0['시가'] # 시가
        highs = data0['고가'] # 고가
        lows = data0['저가'] # 저가
        corr1s = data0['수정주가구분'] # 대업종구분
        corrRatios = data0['수정비율'] # 소업종구분
        upjongDaes = data0['대업종구분'] # 종목정보
        upjongSos = data0['소업종구분'] # 수정주가이벤트
        itemInfos = data0['종목정보'] # 전일종가
        corrEvents = data0['수정주가이벤트'] # 수정주가이벤트
        yesters = data0['전일종가'] # 전일종가

        index1 = 0
        values = []
        for curr1 in currents:
            try:
                value1 = {
                    'Da': dates[index1], # date
                    'St':  abs(int(starts[index1])), # Start price
                    'Hi': abs(int(highs[index1])), # High price
                    'Lo':  abs(int(lows[index1])), # Low price
                    'CP':  abs(int(currents[index1])), # current price
                    'TQ':  abs(int(amounts[index1])), # Trade quantity
                    'YP': yesters[index1] # Final price yesterday
                    }
            except:
                continue
            #print(value1)
            values.append(value1)
            index1 += 1


        return values



#------------------------------------------------------------------
    def SetData_1min(self, ItemCode, date0=None):
        trCode = 'opt10080'
        retDatas1 = self.GetData_10080(ItemCode, date0)
        return retDatas1


    def GetData_10080(self, itemInfo, day0=None):
        timeInterval = 0.9
        trCode = 'opt10080'
        print(trCode, ' :', itemInfo['code'], ' ... ', )
        Data_10080 = []
        itemCode = itemInfo['code']
        time1 = time.time()
        time1 = self.WaitRequestInterval(time1)
        df = self.kiwoom.block_request(trCode,
                                    종목코드=itemCode,
                                    틱범위= 1,
                                    output="주식분봉차트조회요청",
                                    next=0
        )
        print(df.head())
        rets1 = self.ExtractData_10080(df)
        for ret1 in rets1:
            Data_10080.append(ret1)
        if day0:
            length11 = len(rets1)
            day11 = rets1[length11-1]['day']
            #print('[day11]', day11)
            if day11 < day0:
                #print('length :', len(Data_10080))
                return Data_10080
        while self.kiwoom.tr_remained:
            time1 = self.WaitRequestInterval(time1)
            df = self.kiwoom.block_request(trCode,
                                        종목코드=itemCode,
                                        틱범위= 1,
                                        output="주식분봉차트조회요청",
                                        next=2
            )
            #print(df.head())
            try:
                rets1 = self.ExtractData_10080(df)
            except:
                break;
            for ret1 in rets1:
                Data_10080.append(ret1)
            if day0:
                length11 = len(rets1)
                day11 = rets1[length11-1]['day']
                #print('[day11]', day11)
                if day11 < day0:
                    #print('length :', len(Data_10080))
                    return Data_10080
            if cConstants.IsTesting:
                return Data_10080

        print('length :', len(Data_10080))

        return Data_10080

    def ExtractData_10080(seslf, data0):
        currents = data0['현재가'] # 현재가
        amounts = data0['거래량'] # 거래량
        times = data0['체결시간'] # 체결시간
        starts = data0['시가'] # 시가
        highs = data0['고가'] # 고가
        lows = data0['저가'] # 저가`
        corrs = data0['수정주가구분'] # 수정주가구분
        corratios = data0['수정비율'] # 수정비율
        upjong_daes = data0['대업종구분'] # 대업종구분
        upjong_sos = data0['소업종구분'] # 소업종구분
        itemInfos = data0['종목정보'] # 종목정보
        corrEvents = data0['수정주가이벤트'] # 수정주가이벤트
        yesters = data0['전일종가'] # 전일종가

        index1 = 0
        values = []
        for curr1 in currents:
            day1 = times[index1][:8]
            time1 = times[index1][8:]
            try:
                value1 = {
                    'day': day1,
                    'time': time1,
                    'start':  abs(int(starts[index1])),
                    'high': abs(int(highs[index1])),
                    'low':  abs(int(lows[index1])),
                    'curr':  abs(int(currents[index1])),
                    'amount':  abs(int(amounts[index1])),
                    }
            except:
                continue
            #print(value1)
            values.append(value1)
            index1 += 1

        return values

    def AnalyzeData_10080(self, datas, yesterPrice=None):
        if len(datas) < 180: 
            print('Not enough data number')
            #return None

        if not yesterPrice:
            yesterPrice = datas[0]['curr']
        low1 = datas[0]['low']
        high1 = datas[0]['high']
        Increase01 = 0
        Increase02 = 0
        Increase03 = 0
        Increase04 = 0
        Decrease01 = 0
        Decrease02 = 0
        Decrease03 = 0
        Decrease04 = 0
        Amplitude = 0
        count1 = 0
        valid30min = True
        valid60min = True
        for data1 in datas:
            if valid30min and (data1['time']>='093000'):
                valid30min = False
                Increase01_30 = Increase01
                Increase02_30 = Increase02
                Increase03_30 = Increase03
                Increase04_30 = Increase04
                Decrease01_30 = Decrease01
                Decrease02_30 = Decrease02
                Decrease03_30 = Decrease03
                Decrease04_30 = Decrease04
                Count_30 = count1
                Amplitude_30 = Amplitude
            if valid60min and (data1['time']>='100000'):
                valid60min = False
                Increase01_60 = Increase01
                Increase02_60 = Increase02
                Increase03_60 = Increase03
                Increase04_60 = Increase04
                Decrease01_60 = Decrease01
                Decrease02_60 = Decrease02
                Decrease03_60 = Decrease03
                Decrease04_60 = Decrease04
                Count_60 = count1
                Amplitude_60 = Amplitude
            Diff01 = data1['high'] - high1
            Diff02 = data1['high'] - low1
            Diff03 = data1['low'] - high1
            Diff04 = data1['low'] - low1
            Diff05 = data1['high'] - data1['low']
            if Diff01 > 0: Increase01 += Diff01
            if Diff02 > 0: Increase02 += Diff02
            if Diff03 > 0: Increase03 += Diff03
            if Diff04 > 0: Increase04 += Diff04
            if Diff01 < 0: Decrease01 -= Diff01
            if Diff02 < 0: Decrease02 -= Diff02
            if Diff03 < 0: Decrease03 -= Diff03
            if Diff04 < 0: Decrease04 -= Diff04
            Amplitude += Diff05

            high1 = data1['high']
            low1 = data1['low']
            count1 += 1
            try:
                if Increase01_30 < 0:
                    Increase01_30 = Increase01
            except:
                Increase01_30 = Increase01
                Increase02_30 = Increase02
                Increase03_30 = Increase03
                Increase04_30 = Increase04
                Decrease01_30 = Decrease01
                Decrease02_30 = Decrease02
                Decrease03_30 = Decrease03
                Decrease04_30 = Decrease04
                Count_30 = count1
                Amplitude_30 = Amplitude
            try:
                if Increase01_60 < 0:
                    Increase01_60 = Increase01
            except:
                Increase01_60 = Increase01
                Increase02_60 = Increase02
                Increase03_60 = Increase03
                Increase04_60 = Increase04
                Decrease01_60 = Decrease01
                Decrease02_60 = Decrease02
                Decrease03_60 = Decrease03
                Decrease04_60 = Decrease04
                Count_60 = count1
                Amplitude_60 = Amplitude


        ret1 = {
            'I01': format(Increase01/yesterPrice, '.3f'),
            'I02': format(Increase02/yesterPrice, '.3f'),
            'I03': format(Increase03/yesterPrice, '.3f'),
            'I04': format(Increase04/yesterPrice, '.3f'),
            'D01': format(Decrease01/yesterPrice, '.3f'),
            'D02': format(Decrease02/yesterPrice, '.3f'),
            'D03': format(Decrease03/yesterPrice, '.3f'),
            'D04': format(Decrease04/yesterPrice, '.3f'),
            'Amp': format(Amplitude/yesterPrice, '.3f'),
            'I01_30': format(Increase01_30/yesterPrice, '.3f'),
            'I02_30': format(Increase02_30/yesterPrice, '.3f'),
            'I03_30': format(Increase03_30/yesterPrice, '.3f'),
            'I04_30': format(Increase04_30/yesterPrice, '.3f'),
            'D01_30': format(Decrease01_30/yesterPrice, '.3f'),
            'D02_30': format(Decrease02_30/yesterPrice, '.3f'),
            'D03_30': format(Decrease03_30/yesterPrice, '.3f'),
            'D04_30': format(Decrease04_30/yesterPrice, '.3f'),
            'Amp_30': format(Amplitude_30/yesterPrice, '.3f'),
            'Cn_60': Count_60,
            'I01_60': format(Increase01_60/yesterPrice, '.3f'),
            'I02_60': format(Increase02_60/yesterPrice, '.3f'),
            'I03_60': format(Increase03_60/yesterPrice, '.3f'),
            'I04_60': format(Increase04_60/yesterPrice, '.3f'),
            'D01_60': format(Decrease01_60/yesterPrice, '.3f'),
            'D02_60': format(Decrease02_60/yesterPrice, '.3f'),
            'D03_60': format(Decrease03_60/yesterPrice, '.3f'),
            'D04_60': format(Decrease04_60/yesterPrice, '.3f'),
            'Amp_60': format(Amplitude_60/yesterPrice, '.3f'),
            'Cn_30': Count_30,

            'Cn': count1
        }

        return ret1
#----------------------------------------------------------------------------------
    def WaitRequestInterval(self, time1):
        #time0 = time.time()
        while True:
            time2 = time.time()
            if (time2 - self.Time_KiwoomRequest) > self.RequestInterval:
                self.Time_KiwoomRequest = time2
                break
            else:
                time.sleep(0.5)

        return time2
반응형