Ejemplo n.º 1
0
    def work(self, **args):
        """ 
        tasks : ['products','day','minute', 'backup']
        """
        if not self.tasks:
            self.logger.info("No more work to do!")
            return

        elif not self.session.is_connected():
            self.login(key=args['key'] if 'key' in args else None)

        else:
            #날짜
            self.today = ezdate('today')
            self.timer = time.time() #조회 제한 용 타이머

            task = self.tasks.pop(0)
            # 백업
            if task == 'backup':
                self.backup()

            # 상품정보 업데이트
            elif task == "products":
                self.request_productsinfo()

            elif task == "ohlc" or task == "density":
                #open DB
                db_dir = os.path.join(DATA_DIR, 'market.hdf5')
                filters = tb.Filters(complib='blosc', complevel=9)
                self.h5file = tb.open_file(db_dir, mode="a", filters=filters)
                
                self.products_l = list(load_products().values())
                self.codelength = len(self.products_l)
                
                self.message = [] #중요 메시지 마지막에 보여주는 용도
                
                # 신규 종목 db 생성
                for product in self.products_l:
                    if not hasattr(self.h5file.root, product['symbol']):
                        node = self.h5file.create_group('/', product['symbol'] , product['name'])
                        ohlc = self.h5file.create_table(node, "OHLC", OHLC, "Daily OHLC Data")
                        #ohlc.cols.date.create_csindex()
                        self.h5file.create_table(node, "Density", Density, "Minutely Density Data")
                        self.h5file.flush()


                if task == "ohlc":
                    self.logger.info("TASK : Updating Daily OHLC Data")
                    self.get_ohlc_data()
                elif task == 'density':
                    self.logger.info("TASK : Updating Density Data")
                    self.get_density_data()
Ejemplo n.º 2
0
    def get_ohlc_data(self):
        
        #tr 정보
        self.tr = TR.o3108()
        self.query = Query(self, self.tr.CODE)

        #db 정보
        self.product = self.products_l.pop()
        symbol = self.product['symbol']
        self.cursor = getattr(self.h5file.root, symbol).OHLC #db 커서
        self.lastday = ezdate(max(self.cursor.cols.date, default=self.today.delta(-3).stamp())) #최근 저장된 날짜
        startday = self.lastday.delta(1) #시작일
        
        # db에 액티브월물 저장 안되어있으면 저장하기
        if not hasattr(self.cursor.attrs, 'active'):
            self.cursor.attrs.active = self.product['active']['code']

        active = self.cursor.attrs.active #db에 저장된 액티브 월물코드

        # 액티브 월물이 변경된 경우: 선 갭보정 후 다운
        if self.product['active']['code'] != active:
            #digit = self.active['decimal_places'] #소숫점자릿수(반올림용)
            price_gap = self.product['active']['price_gap']
            self.cursor.cols.open[:] = self.cursor.cols.open[:] + price_gap
            self.cursor.cols.high[:] = self.cursor.cols.high[:] + price_gap
            self.cursor.cols.low[:] = self.cursor.cols.low[:] + price_gap
            self.cursor.cols.close[:] = self.cursor.cols.close[:] + price_gap
            self.cursor.attrs.active = self.product['active']['code'] # db에 새로운 액티브 코드 저장
            self.cursor.flush()
            self.message.append("!!! %s Data Has been changed up by %s from %s"%\
                             (self.product['name'], price_gap, self.lastday.str()))

        self.fields = dict(
            shcode=self.product['active']['code'],
            gubun=0, #일별
            qrycnt=500,
            sdate=startday.str(),
            edate=self.today.delta(-1).str(),
            cts_date='',
        )

        #조회 요청
        errcode = self.query.request(self.tr.INBLOCK, self.fields)
        if errcode < 0:
            self.parse_err_code(self.tr.CODE, errcode)
Ejemplo n.º 3
0
    def get_density_data(self):
        """ 분봉 데이터 받기 """
        #tr 정보
        self.tr = TR.o3103()
        self.query = Query(self, self.tr.CODE)

        #db 정보
        self.product = self.products_l.pop()
        symbol = self.product['symbol']
        
        self.cursor = getattr(self.h5file.root, symbol).Density
        self.lastdate = ezdate(max(self.cursor.cols.date, default=self.today.delta(-2).stamp())) #최근 저장된 날짜
        self.flag = False #last date 매칭 되었을때 사용

        if not hasattr(self.cursor.attrs, 'active'):
            self.cursor.attrs.active = self.product['active']['code']
        
        active = self.cursor.attrs.active #db에 저장된 종목 코드

        # 액티브 월물이 변경된 경우: 선 갭보정 후 다운
        if self.product['active']['code'] != active:
            price_gap = self.product['active']['price_gap'] #가격 차이
            #데이터 변환
            self.cursor.cols.price[:] = self.cursor.cols.price[:] + price_gap
            self.cursor.attrs.active = self.product['active']['code'] #새로운 액티브 코드 저장
            self.cursor.flush()
            self.message.append("!!!CASE1: %s Data Has been changed up by %s from %s"%\
                             (self.product['name'], price_gap, self.lastdate.str('s')))

        self.fields = dict(
            shcode=self.product['active']['code'],
            ncnt=1, #분단위
            readcnt=500,
            cts_date='',
            cts_time='',
        )
        # 로깅
        self.logger.info("Started to get MINUTE data : %s upto %s",
                         self.product['name'], self.lastdate.str('s'))

        # 조회 요청 
        errcode = self.query.request(self.tr.INBLOCK, self.fields)
        if errcode < 0:
            self.parse_err_code(self.tr.CODE, errcode)
Ejemplo n.º 4
0
    def _on_get_density_data(self, code):
        if self.tr.methodname != 'get_density_data':
            return 
        shcode = self.query.get_field_data(self.tr.OUTBLOCK, 'shcode', 0) #종목코드
        cts_date = self.query.get_field_data(self.tr.OUTBLOCK, 'cts_date', 0) #연속일자
        cts_time = self.query.get_field_data(self.tr.OUTBLOCK, 'cts_time', 0) #연속시간
        timediff = int(self.query.get_field_data(self.tr.OUTBLOCK, 'timediff', 0)) * (-1) #시차

        cnt = self.query.get_block_count(self.tr.OUTBLOCK1)
        for i in range(cnt):
            date = self.query.get_field_data(self.tr.OUTBLOCK1, 'date', i) #날짜
            dtime = self.query.get_field_data(self.tr.OUTBLOCK1, 'time', i) #시간
            high = float(self.query.get_field_data(self.tr.OUTBLOCK1, 'high', i)) #고가
            low = float(self.query.get_field_data(self.tr.OUTBLOCK1, 'low', i)) #저가
            volume = int(self.query.get_field_data(self.tr.OUTBLOCK1, 'volume', i)) #거래량

            items = []

            #날짜가 이상할때가 있음.
            try:
                ndate = np.datetime64(datetime.strptime(date+dtime, '%Y%m%d%H%M%S')) \
                         + np.timedelta64(timediff, 'h')
                date = ezdate(ndate)
                #ndate = ndate.astype('uint64')/1000000
                #sdate = datetime.strptime(date+dtime, '%Y%m%d%H%M%S') + timedelta(hours=timediff)
                #sdate = sdate.strftime('%Y-%m-%dT%H:%M:%S')
            except:
                self.logger.warning("%s has a missing DATE or something is wrong %s", shcode, date.str('s'))
                self.logger.error(traceback.format_exc())
                continue


            #거래량이 1 미만이면 버림
            if int(volume) < 1:
                self.logger.info("%s with volume %s will be passed at %s", shcode, volume, sdate)
                continue

            #db에 저장된 최근 날짜보다 이전이면 끝냄
            if np.rint(date.stamp()) <= np.rint(self.lastdate.stamp()):
                self.flag = True
                self.logger.warning("Last date of %s in DB matched at %s", shcode, date.str('s'))
                break
            
            # 날짜 겹치면 버림
            ndate = date.stamp()
            if self.cursor.read_where('date==ndate').size:
                self.logger.info("duplicated date: %s", date.str('s'))
                continue

            else:
                digit = self.product['decimals']
                tickunit = float(self.product['tick_unit'])
                
                if round(low, digit) == round(high, digit):
                    item = (date.stamp(), round(low, digit), volume)
                    items.append(item)

                else:
                    length = (high-low)/tickunit + 1
                    length = np.rint(length)
                    value = volume/length

                    if np.isinf(value) or (value < 0.1): #inf value 종종 생겨서..
                        self.logger.warning("wrong volume: %s, length: %s at %s",
                                            volume, length, date.str('s'))
                        continue

                    for price in np.arange(round(low, digit), high - tickunit/2, tickunit):
                        item = (date.stamp(), round(price, digit), value)
                        items.append(item)

                if items:
                    self.cursor.append(items)
                    self.cursor.flush()
        count = self.query.get_tr_count_request(self.tr.CODE)

        if 'items' in locals() and items:
            msg = "Updating Minute data: %s, TR: %s, (%s/%s)"\
                  %(self.product['name'], count, len(self.products_l), self.codelength)
            self.logger.info(msg)
        else:
            msg = "Nothing to update: %s, TR: %s, (%s/%s)"\
                 %(self.product['name'], count, len(self.products_l), self.codelength)
            self.logger.info(msg)

        # 10분당 조회 tr 200회 제한
        self.check_req_limit(self.tr)

        if (cts_date == '00000000') or self.flag:
            if 'date' in locals():
                self.logger.info("Reached last date at  %s", date.str('s'))

            if self.products_l:
                self.get_density_data()
            else:
                for msg in self.message:
                    self.logger.info(msg)
                self.logger.info("** Minute Data updated completely **")
                self.h5file.close()
                self.flush()
                self.work()
                
        elif cts_date != '00000000':
            self.fields['cts_date'] = cts_date
            self.fields['cts_time'] = cts_time
            errcode = self.query.request(self.tr.INBLOCK, self.fields, bnext=True)
            if errcode < 0:
                self.parse_err_code(self.tr.CODE, errcode)
Ejemplo n.º 5
0
    def _on_get_ohlc_data(self, code):
        if self.tr.methodname != 'get_ohlc_data':
            return
        data = []
        
        shcode = self.query.get_field_data(self.tr.OUTBLOCK, 'shcode', 0) #종목코드
        cts_date = self.query.get_field_data(self.tr.OUTBLOCK, 'cts_date', 0) #연속일자

        cnt = self.query.get_block_count(self.tr.OUTBLOCK1)
        for i in range(cnt):
            date = self.query.get_field_data(self.tr.OUTBLOCK1, 'date', i) #날짜
            open = self.query.get_field_data(self.tr.OUTBLOCK1, 'open', i) #시가
            high = self.query.get_field_data(self.tr.OUTBLOCK1, 'high', i) #고가
            low = self.query.get_field_data(self.tr.OUTBLOCK1, 'low', i) #저가
            close = self.query.get_field_data(self.tr.OUTBLOCK1, 'close', i) #종가
            volume = self.query.get_field_data(self.tr.OUTBLOCK1, 'volume', i) #거래량

            #날짜가 이상할때가 있음.
            try:
                date = ezdate(date)
                #ndate = np.datetime64(datetime.strptime(date, '%Y%m%d')).astype('uint64')/1000000
                #sdate = datetime.strptime(date, '%Y%m%d').strftime('%Y-%m-%d')
            except:
                self.logger.warning("%s has a missing DATE or something is wrong", shcode)
                self.logger.error(traceback.format_exc())
                continue

            #거래량이 1  미만이면 버림
            if int(volume) < 1:
                self.logger.info("%s with volume %s will be passed at %s", shcode, volume, date.str())
                continue

            if np.rint(date.stamp()) <= np.rint(self.lastday.stamp()):
                self.logger.warning("Last date of %s in DB matched at %s", shcode, date.str())
                continue

            ndate = date.stamp()
            if self.cursor.read_where('date==ndate').size:
                self.logger.info("duplicated date: %s", date.str())
                continue
            datum = (date.stamp(), open, high, low, close, volume)
            data.append(datum)

        count = self.query.get_tr_count_request(self.tr.CODE)

        if data:
            msg = "Updating daily: %s at  %s, TR: %s, (%s/%s)"\
                  %(self.product['name'], date.str(), count, len(self.products_l), self.codelength)
            self.logger.info(msg)
            self.cursor.append(data)
            self.cursor.flush()
        else:
            msg = "Nothing to update: %s , TR: %s (%s/%s)"\
                  %(self.product['name'], count, len(self.products_l), self.codelength)
            self.logger.info(msg)

        # 10분당 조회 tr 200회 제한
        self.check_req_limit(self.tr)

        if cts_date != '00000000':
            self.fields['cts_date'] = cts_date
            errcode = self.query.request(self.tr.INBLOCK, self.fields, bnext=True)
            if errcode < 0:
                self.parse_err_code(self.tr.CODE, errcode)

        else:
            if self.products_l:
                self.get_ohlc_data()
            else:
                for msg in self.message:
                    self.logger.info(msg)
                self.logger.info("** Daily Data updated completely **")

                self.h5file.close()
                self.flush()
                self.work()