def equity_interest_pledge_too_high(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) nop(context) query_fields = ['质押次数', '无限售股质押数量', '限售股份质押数量', '总股本', '质押比例'] if not data_hub.get_data_center().check_readable_name(query_fields): return AnalysisResult(securities, AnalysisResult.SCORE_NOT_APPLIED, 'Unknown readable name detect.') df = data_hub.get_data_center().query('Stockholder.PledgeStatus', securities, (years_ago(2), now()), fields=query_fields + ['stock_identity', 'due_date'], readable=True) if df is None or len(df) == 0: return AnalysisResult(securities, AnalysisResult.SCORE_NOT_APPLIED, 'No data for ' + str(securities)) df = df.sort_values('due_date', ascending=False) score = 100 reason = [] for index, row in df.iterrows(): due_date = row['due_date'] pledge_rate = row['质押比例'] if pledge_rate > 0.5: score = 0 if pledge_rate > 0.1: reason.append('%s: 质押比例:%.2f%%' % (str(due_date), pledge_rate * 100)) return AnalysisResult(securities, score, reason)
def analysis_finance_report_sign(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('finance_audit', None) is None: context.cache['finance_audit'] = data_hub.get_data_center().query( 'Finance.Audit') df = context.cache.get('finance_audit', None) error_report = check_gen_report_when_data_missing( df, securities, 'Finance.Audit', ['stock_identity', 'period', 'conclusion']) if error_report is not None: return error_report df_slice = df[df['stock_identity'] == securities] df_slice_in_4_years = df_slice[df_slice['period'] > years_ago(4)] score = 100 reason = [] for index, row in df_slice_in_4_years.iterrows(): period = row['period'] conclusion = row['conclusion'] if conclusion != '标准无保留意见': score = 0 reason.append(date2text(period) + ' : ' + conclusion) if len(reason) == 0: reason.append('近四年均为标准无保留意见') return AnalysisResult(securities, score, reason)
def analysis_dispersed_ownership(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database, context) df = data_hub.get_data_center().query( 'Stockholder.Statistics', securities, (years_ago(3), now()), ) if df is None or len(df) == 0: return AnalysisResult(securities, AnalysisResult.SCORE_NOT_APPLIED, '没有数据') df = df[df['period'].dt.month == 12] df = df.sort_values('period', ascending=False) score = 100 reason = [] applied = False for index, row in df.iterrows(): period = row['period'] stockholder_top10 = row['stockholder_top10'] stockholder_top10_nt = row['stockholder_top10_nt'] if not isinstance(stockholder_top10, (list, tuple)): continue if len(stockholder_top10) != 10: continue largest_ratio = 0.0 biggest_holder = '' for stockholder_data in stockholder_top10: if 'hold_ratio' not in stockholder_data.keys( ) or 'holder_name' not in stockholder_data.keys(): break applied = True hold_ratio = stockholder_data.get('hold_ratio') holder_name = stockholder_data.get('holder_name') if hold_ratio > largest_ratio: largest_ratio = hold_ratio biggest_holder = holder_name if largest_ratio == 0.0: return AnalysisResult(securities, AnalysisResult.SCORE_NOT_APPLIED, '缺少必要数据,请确保数据包含tushare pro数据源') if largest_ratio < 0.1: score = 0 reason.append('%s: 最大股东 %s 持股比例为%.2f%%,小于10%%' % (str(period), biggest_holder, largest_ratio * 100)) else: reason.append('%s: 最大股东 %s 持股比例为%.2f%%' % (str(period), biggest_holder, largest_ratio * 100)) if len(reason) == 0: reason.append('没有数据') return AnalysisResult(securities, score, reason) if applied else \ AnalysisResult(securities, AnalysisResult.SCORE_NOT_APPLIED, reason)
def analysis_location_limitation(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('securities_info', None) is None: context.cache['securities_info'] = data_hub.get_data_center().query('Market.SecuritiesInfo') df = context.cache.get('securities_info', None) df_slice = df[df['stock_identity'] == securities] area = get_dataframe_slice_item(df_slice, 'area', 0, '') exclude = area in ['黑龙江', '辽宁', '吉林'] reason = securities + '地域为' + str(area) return AnalysisResult(securities, not exclude, reason)
def analysis_less_than_3_years(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('securities_info', None) is None: context.cache['securities_info'] = data_hub.get_data_center().query('Market.SecuritiesInfo') df = context.cache.get('securities_info', None) df_slice = df[df['stock_identity'] == securities] listing_date = get_dataframe_slice_item(df_slice, 'listing_date', 0, now()) exclude = now().year - listing_date.year < 3 reason = '上市日期' + str(listing_date) + ('小于三年' if exclude else '大于三年') return AnalysisResult(securities, not exclude, reason)
def analysis_exclude_industries(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('securities_info', None) is None: context.cache['securities_info'] = data_hub.get_data_center().query('Market.SecuritiesInfo') df = context.cache.get('securities_info', None) df_slice = df[df['stock_identity'] == securities] industry = get_dataframe_slice_item(df_slice, 'industry', 0, '') exclude = industry in ['种植业', '渔业', '林业', '畜禽养殖', '农业综合'] reason = '所在行业[' + str(industry) + (']属于农林牧渔' if exclude else ']不属于农林牧渔') return AnalysisResult(securities, not exclude, reason)
def check_industry_in(securities: str, industries: [str], data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> bool: nop(database) if context.cache.get('securities_info', None) is None: context.cache['securities_info'] = data_hub.get_data_center().query( 'Market.SecuritiesInfo') df_info = context.cache.get('securities_info', None) df_slice = df_info[df_info['stock_identity'] == securities] industry = get_dataframe_slice_item(df_slice, 'industry', 0, '') return industry in industries
def query_finance_pattern(data_hub: DataHubEntry, identity: str, time_serial: tuple, fields: list, mapping: dict) -> pd.DataFrame: query_fields = [mapping.get(f, f) for f in fields] query_fields = list(set(query_fields)) if 'period' in query_fields: query_fields.remove('period') if 'stock_identity' in query_fields: query_fields.remove('stock_identity') data_utility = data_hub.get_data_utility() df = data_utility.auto_query(identity, time_serial, query_fields, join_on=['stock_identity', 'period']) df.fillna(0.0, inplace=True) df = df.sort_values('period', ascending=False) inv_dict = {v: k for k, v in mapping.items()} df = df.rename(inv_dict, axis='columns') return df
def analysis_investigation(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('investigation', None) is None: context.cache['investigation'] = data_hub.get_data_center().query( 'Market.Investigation') df = context.cache.get('investigation', None) error_report = check_gen_report_when_data_missing( df, securities, 'Market.Investigation', [ 'stock_identity', 'investigate_date', 'investigate_topic', 'investigate_reason' ]) if error_report is not None: return error_report df_slice = df[df['stock_identity'] == securities] df_slice_in_4_years = df_slice[df_slice['investigate_date'] > years_ago(5)] score = 100 reason = [] for index, row in df_slice_in_4_years.iterrows(): score = 0 investigate_date = row['investigate_date'] investigate_topic = row['investigate_topic'] investigate_reason = row['investigate_reason'] reason.append('%s: <<%s>> -- %s' % (date2text(investigate_date), investigate_topic, investigate_reason)) if len(reason) == 0: reason.append('近四年无立案调查记录') return AnalysisResult(securities, score, reason)
def analysis_inquiry(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) df = data_hub.get_data_center().query('Market.Enquiries', securities) if df is None or len(df) == 0: return AnalysisResult(securities, AnalysisResult.SCORE_PASS, '四年内无问询记录(也可能是数据缺失)') error_report = check_gen_report_when_data_missing( df, securities, 'Market.Enquiries', ['stock_identity', 'enquiry_date', 'enquiry_topic']) if error_report is not None: return error_report df_slice = df[df['stock_identity'] == securities] df_slice_in_4_years = df_slice[df_slice['enquiry_date'] > years_ago(5)] score = 100 reason = [] for index, row in df_slice_in_4_years.iterrows(): enquiry_date = row['enquiry_date'] enquiry_topic = row['enquiry_topic'] enquiry_title = row['enquiry_title'] if '问询函' in enquiry_topic or '关注函' in enquiry_topic: score = 59 reason.append( '%s: <<%s>> -- %s' % (date2text(enquiry_date), enquiry_topic, enquiry_title)) if len(reason) == 0: reason.append('近四年无敏感问询') return AnalysisResult(securities, score, reason)
def analysis_finance_report_sign(securities: str, data_hub: DataHubEntry, database: DatabaseEntry, context: AnalysisContext) -> AnalysisResult: nop(database) if context.cache.get('finance_audit', None) is None: context.cache['finance_audit'] = data_hub.get_data_center().query('Finance.Audit') df = context.cache.get('finance_audit', None) error_report = check_gen_report_when_data_missing(df, securities, 'Finance.IncomeStatement', ['stock_identity', 'period', 'conclusion']) if error_report is not None: return error_report df_slice = df[df['stock_identity'] == securities] df_slice_in_4_years = df_slice[df_slice['period'] > years_ago(4)] score = 100 reason = [] for index, row in df_slice_in_4_years.iterrows(): period = row['period'] conclusion = row['conclusion'] if conclusion != '标准无保留意见': score = 0 reason.append(date2text(period) + ' : ' + conclusion) if len(reason) == 0: reason.append('近四年均为标准无保留意见') # df_slice.sort_values('period', ascending=True) # # if len(df_slice) == 1: # print('Too less record: ' + securities) # df_slice_in_3_years = df_slice[df_slice['period'] > years_ago(3)] # # conclusion_all = df_slice['conclusion'] # conclusion_all_list = conclusion_all.to_list() # # conclusion_3_years = df_slice_in_3_years['conclusion'] # conclusion_3_years_list = conclusion_3_years.to_list() # ok_count = 0 # nok_count = 0 # for conclusion in conclusion_all_list: # if conclusion != '标准无保留意见': # nok_count += 1 # else: # ok_count += 1 # score = 100 * ok_count / (ok_count + nok_count) if (ok_count + nok_count) > 0 else 100 # # for conclusion in conclusion_3_years_list: # if conclusion != '标准无保留意见': # score = 0 # break # agency = get_dataframe_slice_item(df_slice, 'agency', 0, '') # sign = get_dataframe_slice_item(df_slice, 'sign', 0, '') # reason = '标准无保留意见' if score == 100 else '存在非标意见' return AnalysisResult(securities, score, reason)