def get_stock_basics( self ): # 返回值: # code,代码 # name,名称 # industry,所属行业 # area,地区 # pe,市盈率 # outstanding,流通股本(亿) # totals,总股本(亿) # totalAssets,总资产(万) = 净资产 + 负债 = ( 股东权益 + 少数股东权益 ) + 负债 # liquidAssets,流动资产 # fixedAssets,固定资产 # reserved,公积金 # reservedPerShare,每股公积金 # esp,每股收益 # bvps,每股净资产 = ( 股东权益 + 少数股东权益 ) / 总股本 # pb,市净率 = 股价 / 每股净资产 # timeToMarket,上市日期 # undp,未分利润 # perundp, 每股未分配 # rev,收入同比(%) # profit,利润同比(%) # gpr,毛利率(%) # npr,净利润率(%) # holders,股东人数 if os.path.exists( self.__basics_file_name ): return Utils.read_data( self.__basics_file_name ) else: ERROR( self.__basics_file_name + ' not exists' ) exit()
def get_k_line_data( self, code ): cur_stock_k_line_file = self.__k_line_file_path + code + '.xlsx' if os.path.exists( cur_stock_k_line_file ): return Utils.read_data( cur_stock_k_line_file ) else: ERROR( cur_stock_k_line_file + ' not exists' ) return pd.DataFrame()
def download_divi_data( self, year, top ): try: df_tmp = ts.profit_data( year, top ) except: ERROR( 'exception occurs when update divi data of year {0}'.format( year ) ) return pd.DataFrame() else: LOG( 'update divi data of year {0}'.format( year ) ) thread_queue.put( df_tmp )
def update_concept_classified( self ): if not os.path.exists( self.__concept_classified_file_name ): try: df_concept_classified = ts.get_concept_classified() except: ERROR( 'exception occurs when update concept classified data' ) else: LOG( 'update concept classified' ) Utils.save_data( df_concept_classified, self.__concept_classified_file_name, 'concept classified' )
def get_concept_classified_data( self ): # 返回值: # code:股票代码 # name:股票名称 # c_name:概念名称 if os.path.exists( self.__concept_classified_file_name ): return Utils.read_data( self.__concept_classified_file_name ) else: ERROR( self.__concept_classified_file_name + ' not exists' ) exit()
def update_stock_basics( self ): if not os.path.exists( self.__basics_file_name ): try: df_stock_basics = ts.get_stock_basics() except: ERROR( 'exception occurs when update stock_basics' ) else: LOG( 'update basics data' ) Utils.save_data( df_stock_basics, self.__basics_file_name, 'stock basics' )
def get_restrict_stock_data( self ): # 返回值: # code:股票代码 # name:股票名称 # date:解禁日期 # count:解禁数量(万股) # ratio:占总盘比率 if os.path.exists( self.__restrict_stock_file_name ): return Utils.read_data( self.__restrict_stock_file_name ) else: ERROR( self.__restrict_stock_file_name + ' not exists' ) exit()
def update_k_line_data_range( self, df_stock_basics, id_start, id_end ): for i in range( id_start, id_end ): code = '%06d' % int( df_stock_basics['code'][i] ) cur_k_line_file = self.__k_line_file_path + code + '.xlsx' if not os.path.exists( cur_k_line_file ): try: df_k_line_data = ts.get_k_data( code, ktype = 'D', autype = 'qfq' ) except: ERROR( 'exception occurs when update k_line data {0}'.format( code ) ) else: LOG( '{3} update {0} k_line data {1:4d}/{2:4d} '.format( code, i + 1, num_stock, threading.current_thread().getName() ) ) Utils.save_data( df_k_line_data, cur_k_line_file, code )
def get_cashflow_data( self ): # code,代码 # name,名称 # cf_sales,经营现金净流量对销售收入比率 # rateofreturn,资产的经营现金流量回报率 # cf_nm,经营现金净流量与净利润的比率 # cf_liabilities,经营现金净流量对负债比率 # cashflowratio,现金流量比率 if os.path.exists( self.__cashflow_file_name ): return Utils.read_data( self.__cashflow_file_name ) else: ERROR( self.__cashflow_file_name + ' not exists' ) exit()
def get_divi_data( self ): # 返回值: # code:股票代码 # name:股票名称 # year:分配年份 # report_date:公布日期 # divi:分红金额(每10股) # shares:转增和送股数(每10股) if os.path.exists( self.__divi_file_name ): return Utils.read_data( self.__divi_file_name ) else: ERROR( self.__divi_file_name + ' not exists' ) exit()
def get_forcast_quarter_report_data( self ): # 返回值: # code,代码 # name,名称 # type,业绩变动类型【预增、预亏等】 # report_date,发布日期 # pre_eps,上年同期每股收益 # range,业绩变动范围 if os.path.exists( self.__forcast_quarter_report_file_name ): return Utils.read_data( self.__forcast_quarter_report_file_name ) else: ERROR( self.__forcast_quarter_report_file_name + ' not exists' ) exit()
def __init__( self, name_model = 'spill_wave' ): self.root_file_path = '../trade/position/' self.__file_path_trade = '../trade/position/simulate_trade_flow.xlsx' self.__file_path_position = '../trade/position/simulate_position.xlsx' if name_model == 'spill_wave': self.df_model_stock = Utils.read_data( model.spill_wave.Analyse().spill_wave_stock_file ) else: ERROR( 'model select error.' ) self.initial_fund = 200000.0 # 初始投资额 self.remain_money = self.initial_fund self.max_buy_each_stock = self.initial_fund / 4.0 # 每股最大买入额 self.df_trade = DataFrame( columns = ( 'time', 'code', 'name', 'type', 'amount', 'total_earn', 'remain' ) ) self.df_position = DataFrame( columns = ( 'code', 'name', 'buy_date', 'cost_price', 'sell_price', 'position', 'earn' ) )
def get_growth_data( self ): # 返回值: # code,代码 # name,名称 # mbrg,主营业务收入增长率(%) # nprg,净利润增长率(%) # nav,净资产增长率 # targ,总资产增长率 # epsg,每股收益增长率 # seg,股东权益增长率 if os.path.exists( self.__growth_file_name ): return Utils.read_data( self.__growth_file_name ) else: ERROR( self.__growth_file_name + ' not exists' ) exit()
def get_operation_data( self ): # 返回值: # code,代码 # name,名称 # arturnover,应收账款周转率(次) # arturndays,应收账款周转天数(天) # inventory_turnover,存货周转率(次) # inventory_days,存货周转天数(天) # currentasset_turnover,流动资产周转率(次) # currentasset_days,流动资产周转天数(天) if os.path.exists( self.__operation_file_name ): return Utils.read_data( self.__operation_file_name ) else: ERROR( self.__operation_file_name + ' not exists' ) exit()
def get_debtpaying_data( self ): # 返回值: # code,代码 # name,名称 # currentratio,流动比率 = 流动资产 / 流动负债 ( 一般高于2 ) # quickratio,速动比率 = 速动资产 / 流动负债 # cashratio,现金比率 # icratio,利息支付倍数 = 税息前利润 / 利息费用 ( 一般高于1.5 ) # sheqratio,股东权益比率 = 股东权益总额 / 资产总额 ( 高于0.6 ) # adratio,股东权益增长率 if os.path.exists( self.__debtpaying_file_name ): return Utils.read_data( self.__debtpaying_file_name ) else: ERROR( self.__debtpaying_file_name + ' not exists' ) exit()
def get_profit_data( self ): # 返回值: # code,代码 # name,名称 # roe,净资产收益率(%) # net_profit_ratio,净利率(%) # gross_profit_rate,毛利率(%) # net_profits,净利润(百万元) # eps,每股收益 # business_income,营业收入(百万元) # bips,每股主营业务收入(元) if os.path.exists( self.__profit_file_name ): return Utils.read_data( self.__profit_file_name ) else: ERROR( self.__profit_file_name + ' not exists' ) exit()
def update_forcast_quarter_report_data( self ): if not os.path.exists( self.__forcast_quarter_report_file_name ): list_date_quarter = Utils.parse_date_to_ymd( self.__date ) df_forcast_quarter_report_data = pd.DataFrame() for year in range( 2003, int( list_date_quarter[0] ) + 1 ): for quarter in range( 1, 5 ): try: df_tmp = ts.forecast_data( year, quarter ) except: ERROR( 'exception occurs when update forcast quarter report data of year {0} quarter {1}'.format( year, quarter ) ) else: df_forcast_quarter_report_data = df_forcast_quarter_report_data.append( df_tmp ) LOG( 'update forcast quarter report data of year {0} quarter {1}'.format( year, quarter ) ) if year == int( list_date_quarter[0] ) and quarter == list_date_quarter[3]: break Utils.save_data( df_forcast_quarter_report_data, self.__forcast_quarter_report_file_name, 'forcast quarter report' )
def get_quarter_report_data( self ): # 返回值: # code,代码 # name,名称 # esp,每股收益 # eps_yoy,每股收益同比(%) # bvps,每股净资产 # roe,净资产收益率(%) # epcf,每股现金流量(元) # net_profits,净利润(万元) # profits_yoy,净利润同比(%) # distrib,分配方案 # report_date,发布日期 if os.path.exists( self.__quarter_report_file_name ): return Utils.read_data( self.__quarter_report_file_name ) else: ERROR( self.__quarter_report_file_name + ' not exists' ) exit()
def update_restrict_stock_data( self, extend_years = 3 ): if not os.path.exists( self.__restrict_stock_file_name ): list_date_quarter = Utils.parse_date_to_ymd( self.__date ) df_restrict_stock_data = pd.DataFrame() for year in range( 2010, int( list_date_quarter[0] ) + extend_years + 1 ): for month in range( 1, 13 ): try: df_tmp = ts.xsg_data( year, month ) except: ERROR( 'exception occurs when update restrict stock data of year {0} month {1}'.format( year, month ) ) else: df_restrict_stock_data = df_restrict_stock_data.append( df_tmp ) LOG( 'update restrict stock data of year {0} month {1}'.format( year, month ) ) if year == int( list_date_quarter[0] ) + extend_years and month == int( list_date_quarter[1] ): break Utils.save_data( df_restrict_stock_data, self.__restrict_stock_file_name, 'restrict stock' )
def update_cashflow_data( self ): if not os.path.exists( self.__cashflow_file_name ): list_date_quarter = Utils.parse_date_to_ymd( self.__date ) df_cashflow_data = pd.DataFrame() for year in range( 2003, int( list_date_quarter[0] ) + 1 ): for quarter in range( 1, 5 ): if year == int( list_date_quarter[0] ) and quarter == list_date_quarter[3]: break try: df_tmp = ts.get_cashflow_data( year, quarter ) except: ERROR( 'exception occurs when update cashflow data of year {0} quarter {1}'.format( year, quarter ) ) return else: df_tmp[ 'year' ] = year df_tmp[ 'quarter' ] = quarter df_cashflow_data = df_cashflow_data.append( df_tmp ) LOG( 'update cashflow data of year {0} quarter {1}'.format( year, quarter ) ) Utils.save_data( df_cashflow_data, self.__cashflow_file_name, 'cashflow' )
def __init__(self, mode='fixed_interval', head_to_start_or_end=30, end_to_tail=0, threshold_market_days=40): # mode = 'elastic_interval' # fixed prefix and suffix # mode = 'fixed_interval' # note: k_line数据总区间划分为[ start head end tail ] 震荡计算区间为[ head : end ] Base.__init__(self) self.mode = mode if self.mode == 'fixed_interval': self.calc_head_to_start_or_end = head_to_start_or_end # 股票震荡计算开始日距end天数(head_to_end),在计算具体股票时赋值,用股票上市总天数减去当前值 elif self.mode == 'elastic_interval': self.calc_head_to_start_or_end = head_to_start_or_end # 股票震荡计算开始日距start天数(head_to_start) else: ERROR('init mode error') self.calc_end_to_tail = end_to_tail # 股票震荡计算end距tail天数 self.threshold_min_market_days = threshold_market_days + head_to_start_or_end + end_to_tail # 股票上市天数阈值 self.threshold_oscillation_aptitude = 0.05 # 震荡幅度阈值
def update_profit_data( self ): if not os.path.exists( self.__profit_file_name ): list_date_quarter = Utils.parse_date_to_ymd( self.__date ) df_profit_data = pd.DataFrame() for year in range( 2003, int( list_date_quarter[0] ) + 1 ): for quarter in range( 1, 5 ): if year == int( list_date_quarter[0] ) and quarter == list_date_quarter[3]: break try: df_tmp = ts.get_profit_data( year, quarter ) except: ERROR( 'exception occurs when update profit data of year {0} quarter {1}'.format( year, quarter ) ) return else: df_tmp[ 'year' ] = year df_tmp[ 'quarter' ] = quarter df_profit_data = df_profit_data.append( df_tmp ) LOG( 'update profit data of year {0} quarter {1}'.format( year, quarter ) ) # 解决 ts.get_growth_data() 拿不到数据时一直等待的问题 #self.update_growth_data() Utils.save_data( df_profit_data, self.__profit_file_name, 'quarter report' )
def notify_realtime_earnings(self): # 实时持仓盈亏检测通知 while True: df_position = DataFrame() if os.path.exists(self.__file_path_position): try: df_position = Utils.read_data(self.__file_path_position) except: # 可能在修改文件,等一分钟 sleep(60) continue else: ERROR('file {0} not exists.'.format(self.__file_path_position)) return cur_time = Utils.cur_time() hour = int(cur_time.split(':')[0]) minute = int(cur_time.split(':')[1]) if hour < 9 or (hour == 9 and minute < 30): LOG( 'notify_realtime_earnings: morning\n{0} hours {1} minutes later market open'\ .format( int( Utils.now2market_morning_time() / 3600 ), int( Utils.now2market_morning_time() % 3600 / 60 ) ) ) sleep(Utils.now2market_morning_time()) elif (hour == 11 and minute >= 30) or hour == 12: LOG('notify_realtime_earnings: nooning\n{0} hours {1} minutes later market open' .format(int(Utils.now2market_nooning_time() / 3600), int(Utils.now2market_nooning_time() % 3600 / 60))) sleep(Utils.now2market_nooning_time()) elif hour >= 15: LOG('notify_realtime_earnings: market close') break content_notify = '' content_notify += '{0}\n'.format(cur_time) total_earn = 0 for index in df_position.index: code = '%06d' % df_position.loc[index]['code'] name = df_position.loc[index]['name'] try: df_realtime_quotes = Data().get_realtime_quotes(code) buy_price = float(df_position.loc[index]['buy_price']) cur_price = float(df_realtime_quotes['price']) position = df_position.loc[index]['position'] earn = (cur_price - buy_price) * position total_earn += earn content_notify += '-{0} {1} cur:{2:.2f} cost:{3:.2f} sell:{4:.2f} position:{5} earn:{6:.2f}\n'\ .format( code, name, cur_price, buy_price, float( df_position.loc[ index ][ 'sell_price' ] ), position, earn) except: pass content_notify += 'total_earn:{0:.2f}'.format(total_earn) if SEND_EMAIL: Utils.send_email(content_notify, 'position notification') sleep(60 * 10) else: LOG(content_notify) sleep(60 * 10)
def query_stock_info(ls_code, ls_all_stock_data, df_model_basics): [ df_stock_basics, df_quarter_report_data, df_profit_data, df_operation_data, df_growth_data, df_debtpaying_data, \ df_cashflow_data, df_divi_data, df_forcast_quarter_report_data, df_restrict_stock_data, df_concept_classified ] = ls_all_stock_data space = lambda x: ' ' * x # 方便区分不同季度数据 pd.options.mode.chained_assignment = None # 不显示warn信息 default='warn' dict_stock_info = {} for code in ls_code: try: basics = df_stock_basics.loc[int(code)] content = '\n{0} {1}\n'.format(code, basics['name']) try: cur_price = float( Data().get_k_line_data(code).iloc[-1]['close']) except: cur_price = float( Data().get_realtime_quotes(code)['price']) content += '\nbasics:\n上市日期:{0}\n所属行业:{1}\t行业市盈率排名:{6}\n地区:{2}\n市盈率(动态):{3}\n市盈率(静态):{4:.2f}\n市净率:{5}\n'\ .format( basics[ 'timeToMarket' ], basics[ 'industry' ], basics[ 'area' ], basics[ 'pe' ], \ cur_price / float( basics[ 'esp' ] ), float( basics[ 'pb' ] ), df_model_basics[ 'rank_pe' ][ int( code ) ] ) content += '每股公积金:{0}\n每股未分配利润:{1}\n'\ .format( basics[ 'reservedPerShare' ], basics[ 'perundp' ] ) content += '总市值:{0:.2f} 亿元\n流动市值:{1:.2f} 亿元\n'\ .format( cur_price * float( basics[ 'totals' ] ), cur_price * float( basics[ 'outstanding' ] ) ) content += '总资产:{0:.2f} 亿元\n固定资产:{1:.2f} 亿元\n流动资产:{2:.2f} 亿元\n'\ .format( float( basics[ 'totalAssets' ] ) / 10000, float( basics[ 'fixedAssets' ] ) / 10000, \ float( basics[ 'liquidAssets' ] ) / 10000 ) except: content = '\n{0}\n'.format(code) try: content += '\nconcept:\n' id_concept = 1 id_rank = 1 name_concept = '_'.join(['concept', str(id_concept)]) name_rank = '_'.join(['rank_pe', str(id_rank)]) while df_model_basics[name_concept][int(code)] is not np.nan: content += '{0} 市盈率排名:{1}\n'.format( df_model_basics[ name_concept ][ int( code ) ], \ df_model_basics[ name_rank ][ int( code ) ] ) id_concept += 1 id_rank += 1 if id_concept > 20: break name_concept = '_'.join(['concept', str(id_concept)]) name_rank = '_'.join(['rank_pe', str(id_rank)]) content += '\n' except: pass try: profit = df_profit_data.loc[int(code)].sort_values( by=['year', 'quarter'], axis=0, ascending=True).drop_duplicates() content += '\nprofit:\n排名:{0}\n年份 季度 净资产收益率 净利润(百万) 每股收益(元)每股主营业务收入(元)\n'\ .format( df_model_basics[ 'rank_profit_grow' ][ int( code ) ] ) for id in range(profit.index.size): content += '{5}{0} {1} {2:-10.2f} {3:-12.2f} {4:-15.2f} {6:-20.2f}\n'.format( profit.iloc[ id ][ 'year' ], profit.iloc[ id ][ 'quarter' ], \ profit.iloc[ id ][ 'roe' ], profit.iloc[ id ][ 'net_profits' ], profit.iloc[ id ][ 'eps' ], \ space( int( profit.iloc[ id ][ 'quarter' ] ) - 1 ), profit.iloc[ id ][ 'bips' ] ) except: pass try: operation = df_operation_data.loc[int(code)].sort_values( by=['year', 'quarter'], axis=0, ascending=True).drop_duplicates() content += '\noperation:\n年份 季度 应收账款周转天数 存货周转天数 流动资产周转天数\n' for id in range(operation.index.size): content += '{5}{0} {1} {2:-16.2f} {3:-8.2f} {4:-15.2f}\n'.format( operation.iloc[ id ][ 'year' ], \ operation.iloc[ id ][ 'quarter' ],operation.iloc[ id ][ 'arturndays' ], operation.iloc[ id ][ 'inventory_days' ], \ operation.iloc[ id ][ 'currentasset_days' ], space( int( operation.iloc[ id ][ 'quarter' ] ) - 1 ) ) except: pass try: debtpaying = df_debtpaying_data.loc[int(code)].sort_values( by=['year', 'quarter'], axis=0, ascending=True).drop_duplicates() content += '\ndebtpaying:\n年份 季度 流动比率 利息支付倍数 股东权益比率 股东权益增长率\n' for col in ['currentratio', 'icratio', 'sheqratio', 'adratio']: for id in range(debtpaying.index.size): try: float(debtpaying[col].iloc[id]) except: debtpaying[col].iloc[id] = np.nan for id in range(debtpaying.index.size): content += '{5}{0} {1} {2:-8.2f} {3:-12.2f} {4:-10.2f} {6:-14.2f}\n'.format( debtpaying.iloc[ id ][ 'year' ], \ debtpaying.iloc[ id ][ 'quarter' ], float( debtpaying.iloc[ id ][ 'currentratio' ] ), float( debtpaying.iloc[ id ][ 'icratio' ] ), \ float( debtpaying.iloc[ id ][ 'sheqratio' ] ), space( int( debtpaying.iloc[ id ][ 'quarter' ] ) - 1 ), \ float( debtpaying.iloc[ id ][ 'adratio' ] ) ) except: pass try: divi = df_divi_data.loc[int(code)] content += '\ndivision:\n年份 公布日期 分红金额(每10股) 转增股数(每10股)\n' if type(divi) == pd.Series: divi = divi.to_frame().T if type(divi) == pd.DataFrame: divi = divi.sort_values(by=['year', 'report_date'], axis=0, ascending=True) for id in range(divi.index.size): content += '{0} {1} {2:-12d} {3:-16d}\n'.format( divi.iloc[ id ][ 'year' ], divi.iloc[ id ][ 'report_date' ], int( divi.iloc[ id ][ 'divi' ] ), \ int( divi.iloc[ id ][ 'shares' ] ) ) else: ERROR('divi type error.') except: pass try: forcast_quarter_data = df_forcast_quarter_report_data.loc[int( code)] content += '\nforcast quarter report:\n发布日期 业绩变动类型 上年同期每股收益 业绩变动范围\n' if type(forcast_quarter_data) == pd.Series: forcast_quarter_data = forcast_quarter_data.to_frame().T if type(forcast_quarter_data) == pd.DataFrame: forcast_quarter_data = forcast_quarter_data.sort_values( by='report_date', axis=0, ascending=True) for id in range(forcast_quarter_data.index.size): content += '{0} {1:>8s} {2:-14.2f} {3:>12s}\n'.format( forcast_quarter_data.iloc[ id ][ 'report_date' ], \ forcast_quarter_data.iloc[ id ][ 'type' ], float( forcast_quarter_data.iloc[ id ][ 'pre_eps' ] ), \ forcast_quarter_data.iloc[ id ][ 'range' ] ) else: ERROR('forcast_quarter_data type error.') except: pass try: restrict = df_restrict_stock_data.loc[int(code)] content += '\nrestrict:\n解禁日期 解禁数量(万股) 占总盘比率\n' if type(restrict) == pd.Series: restrict = restrict.to_frame().T if type(restrict) == pd.DataFrame: restrict = restrict.sort_values(by='date', axis=0, ascending=True) for id in range(restrict.index.size): content += '{0} {1:-12.2f} {2:-10.2f}\n'.format( restrict.iloc[ id ][ 'date' ], \ float( restrict.iloc[ id ][ 'count' ] ), float( restrict.iloc[ id ][ 'ratio' ] ) ) else: ERROR('restrict type error.') except: pass try: df_news = ts.get_notices(code) content += '\nnotice:\n' for index in range(0, 10): # df_news.index: content += '{3}、{0}\t{1}\tdate:{2}\n'.format( df_news[ 'title' ][ index ], \ df_news[ 'type' ][ index ], df_news[ 'date' ][ index ], index + 1 ) if index < 3: content += ts.notice_content(df_news['url'][index]) content += '\n\n' content += '\n' except: pass LOG(content) dict_stock_info[code] = content return dict_stock_info
def sub_calc_divi_earn(self, list_code, id_start, id_end, df_divi_data, queue_process): ls_tmp = [] object_Data = Data() for id in range(id_start, id_end): code = list_code[id] tmp_divi = df_divi_data.loc[code] code = '%06d' % code # 判断tmp_divi类型 if type(tmp_divi) == pd.Series: name = tmp_divi['name'] elif type(tmp_divi) == pd.DataFrame: name = tmp_divi.iloc[0]['name'] else: ERROR('tmp_divi type error when calc divi earn') continue try: # 获取不到k线数据 或 k线数据为空,则跳过 df_k_line_data = object_Data.get_k_line_data(code) if df_k_line_data.index.size == 0 or df_k_line_data.empty: continue except: continue earn_rate = 0 if type(tmp_divi) == pd.Series: date = tmp_divi['report_date'] divi = float('{0:.2f}'.format(tmp_divi['divi'])) shares = tmp_divi['shares'] if divi == 0 and shares == 0: continue try: df_divi_k_line_data = df_k_line_data[df_k_line_data.date == date] except: continue else: if not df_divi_k_line_data.empty: earn_rate = self.calc_earn(df_k_line_data, df_divi_k_line_data) if earn_rate is None: continue ls_tmp.append( [code, name, date, divi, shares, earn_rate]) LOG([code, name, date, divi, shares, earn_rate]) else: continue elif type(tmp_divi) == pd.DataFrame: for i in range(tmp_divi.index.size): date = tmp_divi.iloc[i]['report_date'] divi = float('{0:.2f}'.format(tmp_divi.iloc[i]['divi'])) shares = tmp_divi.iloc[i]['shares'] if divi == 0 and shares == 0: continue try: df_divi_k_line_data = df_k_line_data[ df_k_line_data.date == date] except: continue else: if not df_divi_k_line_data.empty: earn_rate = self.calc_earn(df_k_line_data, df_divi_k_line_data) if earn_rate is None: continue ls_tmp.append( [code, name, date, divi, shares, earn_rate]) LOG([code, name, date, divi, shares, earn_rate]) else: continue queue_process.put_nowait(ls_tmp)