def select_by_finance(timestamp=now_pd_timestamp(), entity_ids=None): if timestamp.dayofweek in (5, 6): logger.info(f'today:{timestamp} is {timestamp.day_name()},just ignore') today = to_time_str(timestamp) my_selector = TargetSelector(start_timestamp='2015-01-01', end_timestamp=today, entity_ids=entity_ids) # add the factors good_factor1 = GoodCompanyFactor(start_timestamp='2015-01-01', end_timestamp=today, entity_ids=entity_ids) good_factor2 = GoodCompanyFactor( start_timestamp='2015-01-01', end_timestamp=today, entity_ids=entity_ids, data_schema=CashFlowStatement, columns=[ CashFlowStatement.report_period, CashFlowStatement.net_op_cash_flows ], filters=[CashFlowStatement.net_op_cash_flows > 0], col_threshold={'net_op_cash_flows': 100000000}) my_selector.add_filter_factor(good_factor1) my_selector.add_filter_factor(good_factor2) my_selector.run() long_targets = my_selector.get_open_long_targets(today) logger.info(f'selected:{len(long_targets)}') return long_targets
def every_day_report(): while True: try: today = now_pd_timestamp() long_targets = select_by_finance(today) logger.info(f'selected:{len(long_targets)}') if long_targets: ma_factor = CrossMaFactor(start_timestamp='2015-01-01', end_timestamp=today, dry_run=True, persist_factor=False, entity_ids=long_targets, windows=[5, 30, 120]) my_selector = TargetSelector(start_timestamp='2015-01-01', end_timestamp=today, entity_ids=long_targets) my_selector.add_filter_factor(ma_factor) my_selector.run() final_targets = my_selector.get_open_long_targets(today) final_targets = list(set(final_targets)) logger.info(f'final selected:{len(final_targets)}') if final_targets: df = get_entities(provider='eastmoney', entity_schema=Stock, entity_ids=final_targets, columns=['code', 'name']) info = [ df.loc[i, 'code'] + ' ' + df.loc[i, 'name'] for i in df.index ] msg = ' '.join(info) else: msg = 'no targets' logger.info(msg) email_action = EmailInformer() email_action.send_message("*****@*****.**", f'{today} 基本面 + 技术面选股结果', msg) break except Exception as e: logger.exception('report3 sched error:{}'.format(e)) time.sleep(60 * 3)
def report_state(): while True: error_count = 0 email_action = EmailInformer(ssl=True) try: latest_day: Stock1dKdata = Stock1dKdata.query_data(order=Stock1dKdata.timestamp.desc(), limit=1, return_type='domain') target_date = latest_day[0].timestamp # target_date = to_pd_timestamp('2020-01-02') # 计算均线 my_selector = TargetSelector(start_timestamp='2018-01-01', end_timestamp=target_date) # add the factors factor1 = VolumeUpMa250Factor(start_timestamp='2018-01-01', end_timestamp=target_date) my_selector.add_filter_factor(factor1) my_selector.run() long_stocks = my_selector.get_open_long_targets(timestamp=target_date) msg = 'no targets' # 过滤亏损股 # check StockValuation data pe_date = target_date - datetime.timedelta(10) if StockValuation.query_data(start_timestamp=pe_date, limit=1, return_type='domain'): positive_df = StockValuation.query_data(provider='joinquant', entity_ids=long_stocks, start_timestamp=pe_date, filters=[StockValuation.pe > 0], columns=['entity_id']) bad_stocks = set(long_stocks) - set(positive_df['entity_id'].tolist()) if bad_stocks: stocks = get_entities(provider='joinquant', entity_schema=Stock, entity_ids=bad_stocks, return_type='domain') info = [f'{stock.name}({stock.code})' for stock in stocks] msg = '亏损股:' + ' '.join(info) + '\n' long_stocks = set(positive_df['entity_id'].tolist()) if long_stocks: pre_date = target_date - datetime.timedelta(3 * 365) ma_state = MaStateStatsFactor(entity_ids=long_stocks, start_timestamp=pre_date, end_timestamp=target_date, persist_factor=False) bad_stocks = [] for entity_id, df in ma_state.factor_df.groupby(level=0): if df['current_pct'].max() >= 0.35: bad_stocks.append(entity_id) long_stocks.remove(entity_id) if bad_stocks: stocks = get_entities(provider='joinquant', entity_schema=Stock, entity_ids=bad_stocks, return_type='domain') info = [f'{stock.name}({stock.code})' for stock in stocks] msg = msg + '3年内高潮过:' + ' '.join(info) + '\n' # 过滤风险股 if long_stocks: risky_codes = risky_company(the_date=target_date, entity_ids=long_stocks) if risky_codes: long_stocks = [entity_id for entity_id in long_stocks if get_entity_code(entity_id) not in risky_codes] stocks = get_entities(provider='joinquant', entity_schema=Stock, entity_ids=risky_codes, return_type='domain') info = [f'{stock.name}({stock.code})' for stock in stocks] msg = msg + '风险股:' + ' '.join(info) + '\n' if long_stocks: stocks = get_entities(provider='joinquant', entity_schema=Stock, entity_ids=long_stocks, return_type='domain') # add them to eastmoney try: try: eastmoneypy.del_group('real') except: pass eastmoneypy.create_group('real') for stock in stocks: eastmoneypy.add_to_group(stock.code, group_name='real') except Exception as e: email_action.send_message("*****@*****.**", f'report state error', 'report state error:{}'.format(e)) info = [f'{stock.name}({stock.code})' for stock in stocks] msg = msg + '盈利股:' + ' '.join(info) + '\n' logger.info(msg) email_action.send_message('*****@*****.**', f'{target_date} 放量突破年线state选股结果', msg) break except Exception as e: logger.exception('report state error:{}'.format(e)) time.sleep(60 * 3) error_count = error_count + 1 if error_count == 10: email_action.send_message("*****@*****.**", f'report state error', 'report state error:{}'.format(e))
def report_real(region): while True: error_count = 0 email_action = EmailInformer(ssl=True) try: latest_day: Stock1dKdata = Stock1dKdata.query_data( region=region, order=Stock1dKdata.timestamp.desc(), limit=1, return_type='domain') target_date = latest_day[0].timestamp # target_date = '2020-02-04' # 计算均线 my_selector = TargetSelector(region=region, start_timestamp='2018-01-01', end_timestamp=target_date) # add the factors factor1 = VolumeUpMa250Factor(region=region, start_timestamp='2018-01-01', end_timestamp=target_date) my_selector.add_filter_factor(factor1) my_selector.run() long_stocks = my_selector.get_open_long_targets( timestamp=target_date) msg = 'no targets' # 过滤亏损股 # check StockValuation data pe_date = target_date - datetime.timedelta(10) if StockValuation.query_data(region=region, start_timestamp=pe_date, limit=1, return_type='domain'): positive_df = StockValuation.query_data( region=region, provider=Provider.JoinQuant, entity_ids=long_stocks, start_timestamp=pe_date, filters=[StockValuation.pe > 0], columns=['entity_id']) bad_stocks = set(long_stocks) - set( positive_df['entity_id'].tolist()) if bad_stocks: stocks = get_entities(region=region, provider=Provider.JoinQuant, entity_schema=Stock, entity_ids=bad_stocks, return_type='domain') info = [f'{stock.name}({stock.code})' for stock in stocks] msg = '亏损股:' + ' '.join(info) + '\n' long_stocks = set(positive_df['entity_id'].tolist()) if long_stocks: # use block to filter block_selector = BlockSelector(region=region, start_timestamp='2020-01-01', long_threshold=0.8) block_selector.run() long_blocks = block_selector.get_open_long_targets( timestamp=target_date) if long_blocks: blocks: List[Block] = Block.query_data( region=region, provider=Provider.Sina, entity_ids=long_blocks, return_type='domain') info = [f'{block.name}({block.code})' for block in blocks] msg = ' '.join(info) + '\n' block_stocks: List[BlockStock] = BlockStock.query_data( region=region, provider=Provider.Sina, filters=[BlockStock.stock_id.in_(long_stocks)], entity_ids=long_blocks, return_type='domain') if block_stocks: # add them to eastmoney try: try: eastmoneypy.del_group('real') except: pass eastmoneypy.create_group('real') for block_stock in block_stocks: eastmoneypy.add_to_group( block_stock.stock_code, group_name='real') except Exception as e: email_action.send_message( "*****@*****.**", f'report_real error', 'report_real error:{}'.format(e)) block_map_stocks = {} for block_stock in block_stocks: stocks = block_map_stocks.get(block_stock.name) if not stocks: stocks = [] block_map_stocks[block_stock.name] = stocks stocks.append( f'{block_stock.stock_name}({block_stock.stock_code})' ) for block in block_map_stocks: stocks = block_map_stocks[block] stock_msg = ' '.join(stocks) msg = msg + f'{block}:\n' + stock_msg + '\n' logger.info(msg) email_action.send_message('*****@*****.**', f'{target_date} 放量突破年线real选股结果', msg) break except Exception as e: logger.exception('report_real error:{}'.format(e)) time.sleep(60 * 3) error_count = error_count + 1 if error_count == 10: email_action.send_message("*****@*****.**", f'report_real error', 'report_real error:{}'.format(e))
def report_state(region): while True: error_count = 0 email_action = EmailInformer(ssl=True) try: latest_day: Stock1dKdata = Stock1dKdata.query_data( region=region, order=Stock1dKdata.timestamp.desc(), limit=1, return_type='domain') target_date = latest_day[0].timestamp # target_date = to_pd_timestamp('2020-01-02') # 计算均线 my_selector = TargetSelector(region=region, start_timestamp='2018-01-01', end_timestamp=target_date) # add the factors factor1 = ImprovedMaFactor(region=region, start_timestamp='2018-01-01', end_timestamp=target_date) my_selector.add_filter_factor(factor1) my_selector.run() long_stocks = my_selector.get_open_long_targets( timestamp=target_date) stock_map_slope = {} logger.info(long_stocks) msg = 'no targets' if long_stocks: pre_date = target_date - datetime.timedelta(2 * 365) ma_state = MaStateStatsFactor(region=region, entity_ids=long_stocks, start_timestamp=pre_date, end_timestamp=target_date, need_persist=False) ma_state.factor_df['slope'] = 100 * ma_state.factor_df[ 'current_pct'] / ma_state.factor_df['current_count'] high_stocks = [] for entity_id, df in ma_state.factor_df.groupby(level=0): if df['current_pct'].max() >= 0.7: high_stocks.append(entity_id) stock_map_slope[entity_id] = round(df['slope'].iat[-1], 2) if high_stocks: stocks = get_entities(region=region, provider=Provider.JoinQuant, entity_schema=Stock, entity_ids=high_stocks, return_type='domain') info = [ f'{stock.name}({stock.code})[{stock_map_slope.get(stock.entity_id)}]' for stock in stocks ] msg = msg + '2年内高潮过:' + ' '.join(info) + '\n' # 过滤风险股 if long_stocks: risky_codes = risky_company(region=region, the_date=target_date, entity_ids=long_stocks, income_yoy=-0.8, profit_yoy=-0.8) if risky_codes: long_stocks = [ entity_id for entity_id in long_stocks if get_entity_code(entity_id) not in risky_codes ] stocks = get_entities(region=region, provider=Provider.JoinQuant, entity_schema=Stock, codes=risky_codes, return_type='domain') info = [ f'{stock.name}({stock.code})[{stock_map_slope.get(stock.entity_id)}]' for stock in stocks ] msg = msg + '风险股:' + ' '.join(info) + '\n' if long_stocks: stocks = get_entities(region=region, provider=Provider.JoinQuant, entity_schema=Stock, entity_ids=long_stocks, return_type='domain') # add them to eastmoney try: try: eastmoneypy.del_group('real') except: pass eastmoneypy.create_group('real') for stock in stocks: eastmoneypy.add_to_group(stock.code, group_name='real') except Exception as e: email_action.send_message( "*****@*****.**", f'report state error', 'report state error:{}'.format(e)) info = [ f'{stock.name}({stock.code})[{stock_map_slope.get(stock.entity_id)}]' for stock in stocks ] msg = msg + '选中:' + ' '.join(info) + '\n' logger.info(msg) email_action.send_message('*****@*****.**', f'{target_date} 放量突破年线state选股结果', msg) break except Exception as e: logger.exception('report state error:{}'.format(e)) time.sleep(60 * 3) error_count = error_count + 1 if error_count == 10: email_action.send_message("*****@*****.**", f'report state error', 'report state error:{}'.format(e))
def report_targets( factor_cls: Type[Factor], entity_provider, data_provider, title, entity_type="stock", informer: EmailInformer = None, em_group=None, em_group_over_write=True, filter_by_volume=True, adjust_type=None, start_timestamp="2019-01-01", **factor_kv, ): logger.info( f"entity_provider: {entity_provider}, data_provider: {data_provider}, entity_type: {entity_type}, start_timestamp: {start_timestamp}" ) error_count = 0 while error_count <= 10: try: if not adjust_type: adjust_type = default_adjust_type(entity_type=entity_type) target_date = get_latest_kdata_date(provider=data_provider, entity_type=entity_type, adjust_type=adjust_type) logger.info(f"target_date :{target_date}") current_entity_pool = None if filter_by_volume: # 成交量 vol_df = get_top_volume_entities( entity_type=entity_type, start_timestamp=next_date(target_date, -30), end_timestamp=target_date, adjust_type=adjust_type, pct=0.4, data_provider=data_provider, ) current_entity_pool = vol_df.index.tolist() logger.info( f"current_entity_pool({len(current_entity_pool)}): {current_entity_pool}" ) kdata_schema = get_kdata_schema(entity_type, level=IntervalLevel.LEVEL_1DAY, adjust_type=adjust_type) filters = [] if "turnover_threshold" in factor_kv: filters = filters + [ kdata_schema.turnover >= factor_kv.get("turnover_threshold") ] if "turnover_rate_threshold" in factor_kv: filters = filters + [ kdata_schema.turnover_rate >= factor_kv.get("turnover_rate_threshold") ] if filters: filters = filters + [kdata_schema.timestamp == target_date] kdata_df = kdata_schema.query_data( provider=data_provider, filters=filters, columns=["entity_id", "timestamp"], index="entity_id") if current_entity_pool: current_entity_pool = set(current_entity_pool) & set( kdata_df.index.tolist()) else: current_entity_pool = kdata_df.index.tolist() if "entity_ids" in factor_kv: if current_entity_pool: current_entity_pool = set(current_entity_pool) & set( factor_kv.pop("entity_ids")) else: current_entity_pool = set(factor_kv.pop("entity_ids")) # add the factor my_selector = TargetSelector(start_timestamp=start_timestamp, end_timestamp=target_date, select_mode=SelectMode.condition_or) entity_schema = get_entity_schema(entity_type=entity_type) tech_factor = factor_cls( entity_schema=entity_schema, entity_provider=entity_provider, provider=data_provider, entity_ids=current_entity_pool, start_timestamp=start_timestamp, end_timestamp=target_date, adjust_type=adjust_type, **factor_kv, ) my_selector.add_factor(tech_factor) my_selector.run() long_stocks = my_selector.get_open_long_targets( timestamp=target_date) inform( informer, entity_ids=long_stocks, target_date=target_date, title=title, entity_provider=entity_provider, entity_type=entity_type, em_group=em_group, em_group_over_write=em_group_over_write, ) break except Exception as e: logger.exception("report error:{}".format(e)) time.sleep(60 * 3) error_count = error_count + 1 if error_count == 10: informer.send_message( zvt_config["email_username"], f"report {entity_type}{factor_cls.__name__} error", f"report {entity_type}{factor_cls.__name__} error: {e}", )
def report_targets( factor_cls: Type[Factor], entity_provider, data_provider, title, entity_type="stock", em_group=None, em_group_over_write=True, filter_by_volume=True, adjust_type=None, start_timestamp="2019-01-01", **factor_kv, ): logger.info( f"entity_provider: {entity_provider}, data_provider: {data_provider}, entity_type: {entity_type}, start_timestamp: {start_timestamp}" ) error_count = 0 while error_count <= 10: email_action = EmailInformer() try: if entity_type == "stock" and not adjust_type: adjust_type = AdjustType.hfq target_date = get_latest_kdata_date(provider=data_provider, entity_type=entity_type, adjust_type=adjust_type) logger.info(f"target_date :{target_date}") current_entity_pool = None if filter_by_volume: # 成交量 vol_df = get_top_volume_entities( entity_type=entity_type, start_timestamp=next_date(target_date, -30), end_timestamp=target_date, adjust_type=adjust_type, pct=0.4, ) current_entity_pool = vol_df.index.tolist() logger.info( f"current_entity_pool({len(current_entity_pool)}): {current_entity_pool}" ) # add the factor my_selector = TargetSelector(start_timestamp=start_timestamp, end_timestamp=target_date, select_mode=SelectMode.condition_or) entity_schema = get_entity_schema(entity_type=entity_type) tech_factor = factor_cls( entity_schema=entity_schema, entity_provider=entity_provider, provider=data_provider, entity_ids=current_entity_pool, start_timestamp=start_timestamp, end_timestamp=target_date, adjust_type=adjust_type, **factor_kv, ) my_selector.add_factor(tech_factor) my_selector.run() long_stocks = my_selector.get_open_long_targets( timestamp=target_date) msg = "no targets" if long_stocks: entities = get_entities(provider=entity_provider, entity_type=entity_type, entity_ids=long_stocks, return_type="domain") if em_group: try: codes = [entity.code for entity in entities] add_to_eastmoney(codes=codes, entity_type=entity_type, group=em_group, over_write=em_group_over_write) except Exception as e: email_action.send_message( zvt_config["email_username"], f"report {entity_type}{factor_cls.__name__} error", f"report {entity_type}{factor_cls.__name__} error: {e}", ) infos = [ f"{entity.name}({entity.code})" for entity in entities ] msg = "\n".join(infos) + "\n" logger.info(msg) email_action.send_message(zvt_config["email_username"], f"{target_date} {title}", msg) break except Exception as e: logger.exception("report error:{}".format(e)) time.sleep(60 * 3) error_count = error_count + 1 if error_count == 10: email_action.send_message( zvt_config["email_username"], f"report {entity_type}{factor_cls.__name__} error", f"report {entity_type}{factor_cls.__name__} error: {e}", )