def get_stock_basic(self): """ 从ts_pro.stock_basic获取个股的基本信息列表 return:<df> is success, None if fail """ file_name = PurePath('stock_basic.csv') file_path = sub_path / file_name self.basic = ts_pro.stock_basic( fields= 'ts_code,symbol,name,area,industry,fullname,enname,market,exchange,curr_type,list_status,list_date,delist_date,is_hs' ) if isinstance(self.basic, pd.DataFrame): if len(self.basic) > 10: self.basic.set_index('ts_code', inplace=True) self.basic.to_csv(file_path, encoding='utf-8') log_args = [file_path] add_log( 40, '[fn]:Stock_Basic.get_stock_basic() file "{0[0]}" saved', log_args) return self.basic log_args = [file_path] add_log( 20, '[fn]:Stock_Basic.get_stock_basic() failed to save file "{0[0]}"', log_args) return
def que_list_date(self, ts_code): """查询上市时间list_date return:<str> e.g. '19930503' ts_code:<str> e.g. '000001.SH' """ from st_board import valid_date_str_fmt try: result = self.basic.loc[ts_code]['list_date'] except KeyError: log_args = [ts_code] add_log( 20, '[fn]:Stock_Basic.que_list_date() ts_code: "{0[0]}" was not found in Stock.base. use DEFAULT_OPEN_DATE_STR instead', log_args) result = DEFAULT_OPEN_DATE_STR return result if valid_date_str_fmt(result): return result else: result = DEFAULT_OPEN_DATE_STR log_args = [ts_code, result] add_log( 40, '[fn]:Stock_Basic.que_list_date() ts_code: "{0[0]}" used "DEFAULT_OPEN_DATE_STR" {0[1]} instead "list_date".', log_args) return result
def que_list_date(self, ts_code): """ 查询上市时间 ts_code:<str> e.g. "518880.SH" return:<str> e.g. "19930512" """ from st_board import valid_date_str_fmt ts_code = ts_code.upper() try: result = self.basic_e.loc[ts_code]['list_date'] except KeyError: try: result = self.basic_o.loc[ts_code]['list_date'] except KeyError: log_args = [ts_code] add_log( 20, '[fn]:Fund_Basic.que_list_date() ts_code:{0[0]} was not found in Fund.base_e/_o', log_args) return if valid_date_str_fmt(result): return result else: log_args = [ts_code, result] add_log( 20, '[fn]:Fund_Basic.que_list_date() ts_code:{0[0]} result:{0[1]} invalid', log_args) return
def get_fund_basic(self, market='E'): """ 从ts_pro.fund_basic获取个股的基本信息列表 market: <str> 'E'场内 'O'场外 return: <df> is success, None if fail """ if market == 'E': file_name = PurePath('fund_e_basic.csv') # 场内基金 elif market == 'O': file_name = PurePath('fund_o_basic.csv') # 场外基金 else: log_args = [market] add_log( 20, '[fn]:Fund_Basic.get_fund_basic() unsupported market type:{0[0], aborted', log_args) return file_path = sub_path / file_name if market == 'E': self.basic_e = ts_pro.fund_basic(market=market) # 场内基金 if isinstance(self.basic_e, pd.DataFrame): if len(self.basic_e) > 10: self.basic_e.set_index('ts_code', inplace=True) self.basic_e.to_csv(file_path, encoding='utf-8') log_args = [file_path, len(self.basic_e)] add_log( 40, '[fn]:Fund_Basic.get_fund_basic() file "{0[0]}" saved, items:{0[1]}', log_args) return self.basic_e log_args = [file_path] add_log( 20, '[fn]:Fund_Basic.get_fund_basic() failed to save file "{0[0]}"', log_args) return elif market == 'O': self.basic_o = ts_pro.fund_basic(market=market) # 场外基金 if isinstance(self.basic_o, pd.DataFrame): if len(self.basic_o) > 10: self.basic_o.set_index('ts_code', inplace=True) self.basic_o.to_csv(file_path, encoding='utf-8') log_args = [file_path, len(self.basic_o)] add_log( 40, '[fn]:Fund.get_fund_basic() file "{0[0]}" saved, items:{0[1]}', log_args) return self.basic_o log_args = [file_path] add_log( 20, '[fn]:Fund_Basic.get_fund_basic() failed to save file "{0[0]}"', log_args) return
def in_calendar(self, date_str): """ 查看日期是否在calendar中 """ try: self.trade_calendar.index.get_loc(int(date_str)) return True except Exception as e: log_args = [type(e)] add_log(20, '[fn]Raw_Data.in_calendar() except type:{0[0]}', log_args) return
def next_trade_day(self, dt_str, next_n=1): """ 查询之后第n个交易日 dt_str: <string> in 'YYYYMMDD' e.g.'20190721' next_n: <int> return: <string> in 'YYYYMMDD' e.g.'20190719' """ SUSPENDED_DAYS_LIM = 100 if self.valid_trade_calendar() is None: add_log(20, '[fn]Raw_Data.next_trade_day() trade_calendar invalid') return if next_n < 1: log_args = [next_n] add_log( 20, '[fn]Raw_Data.next_trade_day() next_n:{0[0]} invalid'.format( log_args)) return if isinstance(dt_str, str) and (len(dt_str) == 8): tdf = self.trade_calendar try: pos = tdf.index.get_loc(int(dt_str)) for _ in range(int(next_n)): for i in range(1, SUSPENDED_DAYS_LIM): # 估计最长休市天数不超过x天 if tdf.iloc[pos + i]['is_open'] == 1: pos = pos + i break else: add_log( 20, '[fn]Raw_Data.next_trade_day() suspended days exceed limit' ) return except KeyError: log_args = [dt_str] add_log( 10, '[fn]Raw_Data.next_trade_day() dt_str "{0[0]}" not in stock_basic.csv. check date_str and pull Raw_Data', log_args) return next_trade_date = tdf.iloc[ pos].name # tdf.iloc[pos]是Series,所以用.name # print('[L167] next_trade_date: {}'.format()) return str(next_trade_date) else: log_args = [dt_str] add_log( 20, '[fn]Raw_Data.next_trade_day() dt_str "{0[0]}" incorrect format', log_args) return
def load_fund_basic(self, market='E'): """ 从fund_e_basic.csv或fund_o_basic.csv文件读入个股的基本信息列表 return:<df> is success, None if fail """ if market == 'E': file_name = PurePath('fund_e_basic.csv') # 场内基金 elif market == 'O': file_name = PurePath('fund_o_basic.csv') # 场外基金 else: log_args = [market] add_log( 20, '[fn]:Fund_Basic.load_fund_basic() unsupported market type:{0[0], aborted', log_args) return file_path = sub_path / file_name try: if market == 'E': self.basic_e = pd.read_csv(file_path, dtype={ 'found_date': str, 'due_date': str, 'list_date': str, 'delist_date': str, 'issue_date': str, 'purc_startdate': str, 'redm_startdate': str }, index_col='ts_code') return self.basic_e elif market == 'O': self.basic_o = pd.read_csv(file_path, dtype={ 'found_date': str, 'due_date': str, 'list_date': str, 'delist_date': str, 'issue_date': str, 'purc_startdate': str, 'redm_startdate': str }, index_col='ts_code') return self.basic_o except FileNotFoundError: log_args = [file_name] add_log( 20, '[fn]Fund_Basic.load_fund_basic()e. file "{0[0]}" not found', log_args) return
def load_all_assets_list(self): """ 从all_assets_list.csv中读取全代码列表 """ file_name = PurePath("all_assets_list.csv") file_path = sub_path / sub_path_config / file_name try: df = pd.read_csv(file_path, index_col='ts_code') except FileNotFoundError: log_args = [file_path] add_log(10, '[fn]Raw_Data.load_all_assets_list. "{0[0]}" not found', log_args) df = None self.all_assets_list = df
def query_name(self, ts_code): """ 查询asset的name return: <str> e.g. "上证指数" """ try: name = self.all_assets_list.loc[ts_code]['name'] except Exception as e: # 具体except待细化 log_args = [ts_code, type(e)] add_log( 20, '[fn]Raw_Data.query_name(). ts_code:{0[0]} failed to get name, except:{0[1]}', log_args) return return name
def len_trade_days(self, start_day, end_day=None): """ 查询两个日期间所包括的交易日数,start_day算第1天,end_day也算1天 具体except处理待完善 start_day: <str> e.g. '20191231' end_day: None = today_str() 今天的字符串 <str> e.g. '20191231' """ from st_board import today_str if end_day is None: end_day = today_str() if self.in_calendar(start_day) is not True: log_args = [start_day] add_log( 20, '[fn]Raw_Data.len_trade_days() start_day:{0[0]} not in calendar', log_args) return if self.in_calendar(end_day) is not True: log_args = [end_day] add_log( 20, '[fn]Raw_Data.len_trade_days() end_day:{0[0]} not in calendar', log_args) return try: int_start = int(start_day) int_end = int(end_day) except ValueError: log_args = [start_day, end_day] add_log( 20, '[fn]Raw_Data.len_trade_days() start_day:{0[0]} or end_day:{0[1]} invalid', log_args) return try: df = self.trade_calendar[ self.trade_calendar.index.to_series().between( int_start, int_end)] rslt = df['is_open'].value_counts()[1] except IndexError: log_args = [start_day, end_day] add_log( 30, '[fn]Raw_Data.len_trade_days() start_day:{0[0]} or end_day:{0[1]} invalid or mis-order', log_args) return except KeyError: rslt = 0 # 之间无交易日 return rslt
def load_trade_calendar(self): """ load trade_calendar.csv文件,读入self.trade_calendar """ file_name = PurePath("trade_calendar.csv") file_path = sub_path / file_name try: self.trade_calendar = pd.read_csv(file_path, dtype={ 'cal_date': str, 'pretrade_date': str }, index_col='cal_date') except FileNotFoundError: log_args = [file_path] add_log( 20, '[fn]Raw_Data.load_trade_calendar(). file "{0[0]}" not found', log_args) self.trade_calendar = None
def valid_ts_code(self, ts_code): """验证在raw_data内ts_code是否有效, return: <bool> True=valid """ if ts_code in SPC_TS_CODE: return True # --------------------Index--------------- try: name = self.all_assets_list.loc[ts_code]['name'] # print("[debug L249] name:{}".format(name)) except KeyError: log_args = [ts_code] add_log(30, '[fn]Raw_Data.valid_ts_code(). ts_code "{0[0]}" invalid', log_args) return if isinstance(name, str): if len(name) > 0: return True return
def load_stock_basic(self): """ 从stock_basic.csv文件读入个股的基本信息列表 return:<df> is success, None if fail """ file_name = PurePath("stock_basic.csv") file_path = sub_path / file_name try: self.basic = pd.read_csv(file_path, dtype={ 'symbol': str, 'list_date': str, 'delist_date': str }, index_col='ts_code') return self.basic except FileNotFoundError: log_args = [file_path] add_log( 20, '[fn]Stock_Basic.load_stock_basic()e. file "{0[0]}" not found', log_args) return
def load_index_basic(self): """ load index_basic.csv文件,读入self.index_basic_df """ # 上交所指数 file_name = PurePath("index_basic_sse.csv") try: self._sse = pd.read_csv(sub_path / file_name, dtype={ 'base_date': str, 'list_date': str }) self.valid['index_basic_sse'] = STATUS_WORD[1] except FileNotFoundError: log_args = [file_name] add_log(20, '[fn]Index.load_index_basic(). file "{0[0]}" not found', log_args) self._sse = None # 深交所指数 file_name = PurePath("index_basic_szse.csv") try: self._szse = pd.read_csv(sub_path / file_name, dtype={ 'base_date': str, 'list_date': str }) self.valid['index_basic_szse'] = STATUS_WORD[1] except FileNotFoundError: log_args = [file_name] add_log(20, '[fn]Index.load_index_basic(). file "{0[0]}" not found', log_args) self._szse = None # 申万指数 file_name = PurePath("index_basic_sw.csv") try: self._sw = pd.read_csv(sub_path / file_name, dtype={ 'base_date': str, 'list_date': str }) self.valid['index_basic_sw'] = STATUS_WORD[1] except FileNotFoundError: log_args = [file_name] add_log(20, '[fn]Index.load_index_basic(). file "{0[0]}" not found', log_args) self._sw = None self._update_index_basic_df() return
def last_trade_day(self, dt_str=None): """ 查询指定日当日或之前最近的交易日,返回日期字符串 dt_str: <string> in 'YYYYMMDD' e.g.'20190721' None 代表当日 return: <string> in 'YYYYMMDD' e.g.'20190719' """ if self.valid_trade_calendar() is None: add_log(20, '[fn]Raw_Data.last_trade_day() trade_calendar invalid') return if dt_str is None: dt = datetime.now() dt_str = dt.strftime("%Y%m%d") if isinstance(dt_str, str) and (len(dt_str) == 8): # tdf = self.trade_calendar.set_index(['cal_date']) tdf = self.trade_calendar try: is_open = tdf.loc[int(dt_str)]['is_open'] if is_open == 1: return dt_str elif is_open == 0: pretrade_date = tdf.loc[int(dt_str)]['pretrade_date'] return str(pretrade_date) else: return None except KeyError: log_args = [dt_str] add_log( 10, '[fn]Raw_Data.last_trade_day() dt_str "{0[0]}" not in stock_basic.csv. check date_str and pull Raw_Data', log_args) return else: log_args = [dt_str] add_log( 20, '[fn]Raw_Data.last_trade_day() dt_str "{0[0]}" incorrect format', log_args) return None
def report(al_file): """ 报告:每日资产概览 al_file: <str> al_<al_file>.csv """ from st_board import Strategy from st_board import today_str # global raw_data def head_across(row, column, text): """ 用于辅助打印标题栏0行的一组标题 """ nonlocal ws1 cross = 4 # 单元格跨四格 ws1.write(row, column, text, fmt_head0) for i in range(1, cross): ws1.write_blank(row, column + i, '', fmt_head0) # =================报告文件================= today_s = today_str() trade_day_str = raw_data.last_trade_day(today_s) file_name = PurePath('rpt_racing_' + al_file + '_' + trade_day_str + '.xlsm') file_path = sub_path_rpt / file_name # =================初始化Strategy================= stg = Strategy('report_daily_basic') stg.add_pool(desc='p10', al_file=al_file, assets_daily_data='basic', del_trsfed=None) p10 = stg.pools[10] # ------condition_0 pre_args1 = {'idt_type': 'ma', 'period': 2} pre_args2 = {'idt_type': 'ma', 'period': 5} p10.add_condition(pre_args1, pre_args2, '>') # ------condition_1 pre_args1 = {'idt_type': 'ma', 'period': 10} pre_args2 = {'idt_type': 'ma', 'period': 20} p10.add_condition(pre_args1, pre_args2, '>') # ------condition_2 pre_args1 = {'idt_type': 'ma', 'period': 60} pre_args2 = {'idt_type': 'const', 'const_value': 0} p10.add_condition(pre_args1, pre_args2, '>') stg.init_pools_cnds_matrix() stg.init_ref_assets() end_date = trade_day_str start_date = raw_data.previous_trade_day(end_date, 2) stg.update_cycles(start_date=start_date, end_date=end_date) # ----当前周期的结束日期 m1d = raw_data.previous_trade_day(end_date, 1) # 前1交易日 m2d = start_date # 前2交易日 m5d = raw_data.previous_trade_day(end_date, 5) # 前5交易日 m10d = raw_data.previous_trade_day(end_date, 10) # 前10交易日 m20d = raw_data.previous_trade_day(end_date, 20) # 前20交易日 m60d = raw_data.previous_trade_day(end_date, 60) # 前60交易日 # ----前一周期的开始结束日期 p1d_end = m1d # 前1周期结束日期 p1d_start = raw_data.previous_trade_day(p1d_end, 1) # 前1周期开始日期 p2d_end = m2d # 前1周期结束日期 p2d_start = raw_data.previous_trade_day(p2d_end, 2) # 前1周期开始日期 p5d_end = m5d # 前1周期结束日期 p5d_start = raw_data.previous_trade_day(p5d_end, 5) # 前1周期开始日期 p10d_end = raw_data.previous_trade_day(m10d, 1) # 前1周期结束日期 p10d_start = m10d # 前1周期开始日期 p20d_end = raw_data.previous_trade_day(m20d, 1) # 前1周期结束日期 p20d_start = m20d # 前1周期开始日期 p60d_end = raw_data.previous_trade_day(m60d, 1) # 前1周期结束日期 p60d_start = m60d # 前1周期开始日期 # =================数据准备================= data = [] # [(数据1, 数据2, 数据3), (...)]存放用于报告显示的数据 df = pd.DataFrame(columns=['ts_code', 'm1d_pct', 'close', 'p1d_pct']) # 缓存<df> # df.set_index('ts_code', inplace=True) for asset in p10.assets.values(): ts_code = asset.ts_code name = asset.name # ----最新的复权因子,当日收盘 adj = 1 # 非Stock复权因子设为1 if isinstance(asset, Stock): adj_sr = Stock.load_adj_factor(ts_code, nrows=1) if adj_sr is not None: adj, = adj_sr['adj_factor'].head(1) # 最新的复权因子 try: close, _ = asset.get_price(trade_date=end_date, seek_direction='backwards') # 最新收盘 except Exception as e: log_args = [asset.ts_code, e] add_log( 20, '[fn]report_race.report() ts_code:{0[0]}; except type:{0[1]}, no valid close recently. skip asset', log_args) continue # ----1日 try: close_m1d, _ = asset.get_price(trade_date=m1d, seek_direction='backwards') m1d_pct = (close - close_m1d) / close_m1d # 本周期1日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m1d_pct TypeError, set value = -0.99', log_args) m1d_pct = -0.99 try: close_p1d_end, _ = asset.get_price(trade_date=p1d_end, seek_direction='backwards') close_p1d_start, _ = asset.get_price(trade_date=p1d_start, seek_direction='backwards') p1d_pct = (close_p1d_end - close_p1d_start) / close_p1d_start # 前周期1日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p1d_pct TypeError, set value = -0.99', log_args) p1d_pct = -0.99 close_m = close / adj # 本周期最新未除权价格 # ----2日 try: close_m2d, _ = asset.get_price(trade_date=m2d, seek_direction='backwards') m2d_pct = (close - close_m2d) / close_m2d # 本周期2日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m2d_pct TypeError, set value = -0.99', log_args) m2d_pct = -0.99 try: close_p2d_end, _ = asset.get_price(trade_date=p2d_end, seek_direction='backwards') close_p2d_start, _ = asset.get_price(trade_date=p2d_start, seek_direction='backwards') p2d_pct = (close_p2d_end - close_p2d_start) / close_p2d_start # 前周期2日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p2d_pct TypeError, set value = -0.99', log_args) p2d_pct = -0.99 try: close_ma2, = asset.ma_2.df_idt.head(1)['MA'].values close_ma2r = close_ma2 / adj # 本周期ma2未除权价格 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; close_ma2r TypeError, set value = -99', log_args) close_ma2r = -99 # ----5日 try: close_m5d, _ = asset.get_price(trade_date=m5d, seek_direction='backwards') m5d_pct = (close - close_m5d) / close_m5d # 本周期5日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m5d_pct TypeError, set value = -0.99', log_args) m5d_pct = -0.99 try: close_p5d_end, _ = asset.get_price(trade_date=p5d_end, seek_direction='backwards') close_p5d_start, _ = asset.get_price(trade_date=p5d_start, seek_direction='backwards') p5d_pct = (close_p5d_end - close_p5d_start) / close_p5d_start # 前周期5日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p5d_pct TypeError, set value = -0.99', log_args) p5d_pct = -0.99 try: close_ma5, = asset.ma_5.df_idt.head(1)['MA'].values close_ma5r = close_ma5 / adj # 本周期ma5未除权价格 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; close_ma5r TypeError, set value = -99', log_args) close_ma5r = -99 # ----10日 try: close_m10d, _ = asset.get_price(trade_date=m10d, seek_direction='backwards') m10d_pct = (close - close_m10d) / close_m10d # 本周期10日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m10d_pct TypeError, set value = -0.99', log_args) m10d_pct = -0.99 try: close_p10d_end, _ = asset.get_price(trade_date=p10d_end, seek_direction='backwards') close_p10d_start, _ = asset.get_price(trade_date=p10d_start, seek_direction='backwards') p10d_pct = (close_p10d_end - close_p10d_start) / close_p10d_start # 前周期10日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p10d_pct TypeError, set value = -0.99', log_args) p10d_pct = -0.99 try: close_ma10, = asset.ma_10.df_idt.head(1)['MA'].values close_ma10r = close_ma10 / adj # 本周期ma10未除权价格 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; close_ma10r TypeError, set value = -99', log_args) close_ma10r = -99 # ----20日 try: close_m20d, _ = asset.get_price(trade_date=m20d, seek_direction='backwards') m20d_pct = (close - close_m20d) / close_m20d # 本周期20日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m20d_pct TypeError, set value = -0.99', log_args) m20d_pct = -0.99 try: close_p20d_end, _ = asset.get_price(trade_date=p20d_end, seek_direction='backwards') close_p20d_start, _ = asset.get_price(trade_date=p20d_start, seek_direction='backwards') p20d_pct = (close_p20d_end - close_p20d_start) / close_p20d_start # 前周期20日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p20d_pct TypeError, set value = -0.99', log_args) p20d_pct = -0.99 try: close_ma20, = asset.ma_20.df_idt.head(1)['MA'].values close_ma20r = close_ma20 / adj # 本周期ma20未除权价格 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; close_ma20r TypeError, set value = -99', log_args) close_ma20r = -99 # ----60日 try: close_m60d, _ = asset.get_price(trade_date=m60d, seek_direction='backwards') m60d_pct = (close - close_m60d) / close_m60d # 本周期60日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; m60d_pct TypeError, set value = -0.99', log_args) m60d_pct = -0.99 try: close_p60d_end, _ = asset.get_price(trade_date=p60d_end, seek_direction='backwards') close_p60d_start, _ = asset.get_price(trade_date=p60d_start, seek_direction='backwards') p60d_pct = (close_p60d_end - close_p60d_start) / close_p60d_start # 前周期60日涨跌幅 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; p60d_pct TypeError, set value = -0.99', log_args) p60d_pct = -0.99 try: close_ma60, = asset.ma_60.df_idt.head(1)['MA'].values close_ma60r = close_ma60 / adj # 本周期ma60未除权价格 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]report_race.report() ts_code:{0[0]}; close_ma60r TypeError, set value = -99', log_args) close_ma60r = -99 # ----asset加入<df>中 data = { 'ts_code': ts_code, 'a_name': name, 'm1d_pct': m1d_pct, 'close': close_m, 'p1d_pct': p1d_pct, 'm2d_pct': m2d_pct, 'ma2': close_ma2r, 'p2d_pct': p2d_pct, 'm5d_pct': m5d_pct, 'ma5': close_ma5r, 'p5d_pct': p5d_pct, 'm10d_pct': m10d_pct, 'ma10': close_ma10r, 'p10d_pct': p10d_pct, 'm20d_pct': m20d_pct, 'ma20': close_ma20r, 'p20d_pct': p20d_pct, 'm60d_pct': m60d_pct, 'ma60': close_ma60r, 'p60d_pct': p60d_pct } df = df.append(data, ignore_index=True) # ----本周期、前周期排名及排位变化 df.loc[:, 'm1d_rank'] = df['m1d_pct'].rank(ascending=False, method='min') df.loc[:, 'p1d_rank'] = df['p1d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_1d'] = df['p1d_rank'] - df['m1d_rank'] df.loc[:, 'm2d_rank'] = df['m2d_pct'].rank(ascending=False, method='min') df.loc[:, 'p2d_rank'] = df['p2d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_2d'] = df['p2d_rank'] - df['m2d_rank'] df.loc[:, 'm5d_rank'] = df['m5d_pct'].rank(ascending=False, method='min') df.loc[:, 'p5d_rank'] = df['p5d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_5d'] = df['p5d_rank'] - df['m5d_rank'] df.loc[:, 'm10d_rank'] = df['m10d_pct'].rank(ascending=False, method='min') df.loc[:, 'p10d_rank'] = df['p10d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_10d'] = df['p10d_rank'] - df['m10d_rank'] df.loc[:, 'm20d_rank'] = df['m20d_pct'].rank(ascending=False, method='min') df.loc[:, 'p20d_rank'] = df['p20d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_20d'] = df['p20d_rank'] - df['m20d_rank'] df.loc[:, 'm60d_rank'] = df['m60d_pct'].rank(ascending=False, method='min') df.loc[:, 'p60d_rank'] = df['p60d_pct'].rank(ascending=False, method='min') df.loc[:, 'chg_60d'] = df['p60d_rank'] - df['m60d_rank'] df.set_index('ts_code', inplace=True) # =================报告基础================= workbook = xlw.Workbook(file_path) ws1 = workbook.add_worksheet('日报') # worksheet #1 fmt_std = workbook.add_format(d_std) fmt_wrap = workbook.add_format(d_wrap) fmt_rpt_title = workbook.add_format(d_rpt_title) fmt_head0 = workbook.add_format(d_head0) fmt_head1 = workbook.add_format(d_head1) fmt_center = workbook.add_format(d_center) # 居中 fmt_int = workbook.add_format(d_int) # 整数 fmt_f1d = workbook.add_format(d_f1d) # 1位小数 fmt_f2d = workbook.add_format(d_f2d) # 2位小数 fmt_f3d = workbook.add_format(d_f3d) # 3位小数 fmt_pct = workbook.add_format(d_pct) # 0% fmt_pct1d = workbook.add_format(d_pct1d) # 1.1% fmt_pct2d = workbook.add_format(d_pct2d) # 2.22% fmt_pct1d_g = workbook.add_format(d_pct1d_g) # 1.1% 灰底 # =================添加VBA================= file_bin = PurePath("rpt_racing.bin") path_bin = sub_path_rpt / 'bin' / file_bin workbook.add_vba_project(path_bin) # =================报告数据================= # ----标题栏 ws1.write_string('A1', trade_day_str + ' ' + 'Report Assets Racing', fmt_rpt_title) ws1.set_row(0, 19) # 第一行,标题栏行高 ws1.set_row(1, options={'hidden': True}) # 第二行,分隔行行高 # ----表头第0行 row_h0 = 2 column_h0 = 2 head_across(row_h0, column_h0, '1 Day') column_h0 = 6 head_across(row_h0, column_h0, '2 Days') column_h0 = 10 head_across(row_h0, column_h0, '5 Days') column_h0 = 14 head_across(row_h0, column_h0, '10 Days') column_h0 = 18 head_across(row_h0, column_h0, '20 Days') column_h0 = 22 head_across(row_h0, column_h0, '60 Days') # ----表头第1行 head2 = ('代码', '名称', 'chg%', 'C', 'rank', '+ -', 'chg%', 'ma', 'rank', '+ -', 'chg%', 'ma', 'rank', '+ -', 'chg%', 'ma', 'rank', '+ -', 'chg%', 'ma', 'rank', '+ -', 'chg%', 'ma', 'rank', '+ -') ws1.write_row('A4', head2, fmt_head1) # 标题栏第1行 # ----ts_code列 data = df.index.tolist() ws1.write_column(4, 0, data, fmt_center) # ----name列 data = df.a_name.tolist() ws1.write_column(4, 1, data, fmt_center) # ----chg%列 column_width = 8.38 data = df.m1d_pct.tolist() ws1.write_column(4, 2, data, fmt_pct1d_g) # 1 Day ws1.set_column(2, 2, width=column_width) data = df.m2d_pct.tolist() ws1.write_column(4, 6, data, fmt_pct1d_g) # 2 Days ws1.set_column(6, 6, width=column_width) data = df.m5d_pct.tolist() ws1.write_column(4, 10, data, fmt_pct1d_g) # 5 Days ws1.set_column(10, 10, width=column_width) data = df.m10d_pct.tolist() ws1.write_column(4, 14, data, fmt_pct1d_g) # 10 Days ws1.set_column(14, 14, width=column_width) data = df.m20d_pct.tolist() ws1.write_column(4, 18, data, fmt_pct1d_g) # 20 Days ws1.set_column(18, 18, width=column_width) data = df.m60d_pct.tolist() ws1.write_column(4, 22, data, fmt_pct1d_g) # 60 Days ws1.set_column(22, 22, width=column_width) # ----close及ma列 column_width = 8.38 data = df.close.tolist() ws1.write_column(4, 3, data, fmt_f2d) # 1 Day ws1.set_column(3, 3, width=column_width) data = df.ma2.tolist() ws1.write_column(4, 7, data, fmt_f2d) # 2 Days ws1.set_column(7, 7, width=column_width) data = df.ma5.tolist() ws1.write_column(4, 11, data, fmt_f2d) # 5 Days ws1.set_column(11, 11, width=column_width) data = df.ma10.tolist() ws1.write_column(4, 15, data, fmt_f2d) # 10 Days ws1.set_column(15, 15, width=column_width) data = df.ma20.tolist() ws1.write_column(4, 19, data, fmt_f2d) # 20 Days ws1.set_column(19, 19, width=column_width) data = df.ma60.tolist() ws1.write_column(4, 23, data, fmt_f2d) # 60 Days ws1.set_column(23, 23, width=column_width) # ----rank列 column_width = 5 data = df.m1d_rank.tolist() ws1.write_column(4, 4, data, fmt_int) # 1 Day ws1.set_column(4, 4, width=column_width) data = df.m2d_rank.tolist() ws1.write_column(4, 8, data, fmt_int) # 2 Days ws1.set_column(8, 8, width=column_width) data = df.m5d_rank.tolist() ws1.write_column(4, 12, data, fmt_int) # 5 Days ws1.set_column(12, 12, width=column_width) data = df.m10d_rank.tolist() ws1.write_column(4, 16, data, fmt_int) # 10 Days ws1.set_column(16, 16, width=column_width) data = df.m20d_rank.tolist() ws1.write_column(4, 20, data, fmt_int) # 20 Days ws1.set_column(20, 20, width=column_width) data = df.m60d_rank.tolist() ws1.write_column(4, 24, data, fmt_int) # 60 Days ws1.set_column(24, 24, width=column_width) # ----change列 column_width = 5 data = df.chg_1d.tolist() ws1.write_column(4, 5, data, fmt_int) # 1 Day ws1.set_column(5, 5, width=column_width) data = df.chg_2d.tolist() ws1.write_column(4, 9, data, fmt_int) # 2 Days ws1.set_column(9, 9, width=column_width) data = df.chg_5d.tolist() ws1.write_column(4, 13, data, fmt_int) # 5 Days ws1.set_column(13, 13, width=column_width) data = df.chg_10d.tolist() ws1.write_column(4, 17, data, fmt_int) # 10 Days ws1.set_column(17, 17, width=column_width) data = df.chg_20d.tolist() ws1.write_column(4, 21, data, fmt_int) # 20 Days ws1.set_column(21, 21, width=column_width) data = df.chg_60d.tolist() ws1.write_column(4, 25, data, fmt_int) # 60 Days ws1.set_column(25, 25, width=column_width) # =================添加按钮================= ws1.insert_button( "C3", { 'macro': 'sort_1D', 'caption': '1D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) ws1.insert_button( "G3", { 'macro': 'sort_2D', 'caption': '2D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) ws1.insert_button( "K3", { 'macro': 'sort_5D', 'caption': '5D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) ws1.insert_button( "O3", { 'macro': 'sort_10D', 'caption': '10D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) ws1.insert_button( "S3", { 'macro': 'sort_20D', 'caption': '20D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) ws1.insert_button( "W3", { 'macro': 'sort_60D', 'caption': '60D', 'width': 40, 'height': 15, 'x_offset': 2, 'y_offset': 2 }) # =================收尾格式================= ws1.set_column(0, 0, 9) # 代码 ws1.set_column(1, 1, 8) # 名称 ws1.set_landscape() # 页面横向 ws1.set_paper(9) # 设置A4纸 ws1.center_horizontally() # 居中 ws1.set_margins(0.1, 0.1, 0.1, 1) ws1.set_footer('&C&P of &N') # 设置页脚 ws1.repeat_rows(0, 3) # 重复打印行 ws1.repeat_columns(0, 1) # 重复打印列 ws1.freeze_panes(4, 2) # freeze 4行2列 ws1.fit_to_pages(1, 0) # 宽度放在1页中,长度不限 workbook.close() # print(df) # df.to_csv('临时report_race.csv', encoding='utf-8') pass
def rpt_d_basic(al_file): """ 报告:每日资产概览 al_file: <str> al_<al_file>.csv """ from st_board import Strategy from st_board import today_str # global raw_data # =================报告文件================= today_s = today_str() trade_day_str = raw_data.last_trade_day(today_s) file_name = PurePath('rpt_d_' + al_file + '_' + trade_day_str + '.xlsx') file_path = sub_path_rpt / file_name # =================初始化Strategy================= stg = Strategy('report_daily_basic') # dd = {'turnover_rate_f'} # 成交额 # stg.add_pool(desc='p10', al_file=al_file, assets_daily_data=dd, del_trsfed=None) stg.add_pool(desc='p10', al_file=al_file, assets_daily_data='basic', del_trsfed=None) p10 = stg.pools[10] # ------condition_0 pre_args1 = {'idt_type': 'ma', 'period': 20} pre_args2 = {'idt_type': 'maqs', 'period': 20} p10.add_condition(pre_args1, pre_args2, '>') # ------condition_1 pre_args1 = { 'idt_type': 'majh', 'long_n3': 60, 'medium_n2': 20, 'short_n1': 5 } pre_args2 = {'idt_type': 'maqs', 'period': 60} p10.add_condition(pre_args1, pre_args2, '>') # ------condition_2 pre_args1 = { 'idt_type': 'macd', # 日线macd 'long_n1': 26, 'short_n2': 12, 'dea_n3': 9 } pre_args2 = { 'idt_type': 'macd', # 周线macd 'long_n1': 130, 'short_n2': 60, 'dea_n3': 45 } p10.add_condition(pre_args1, pre_args2, '>') # ------condition_3 pre_args1 = { 'idt_type': 'jdxz', # 绝对吸资比例 'period': 10 } pre_args2 = { 'idt_type': 'jdxz', # 绝对吸资比例 'period': 250 } p10.add_condition(pre_args1, pre_args2, '>') # ------condition_4 pre_args1 = { 'idt_type': 'dktp', # 多空头排列 'short_n1': 5, 'medium_n2': 10, 'long_n3': 20 } pre_args2 = { 'idt_type': 'dktp', # 多空头排列 'source': 'vol', # 成交量 'short_n1': 5, 'medium_n2': 10, 'long_n3': 20 } p10.add_condition(pre_args1, pre_args2, '>') # ------condition_5 pre_args1 = { 'idt_type': 'maqs', # 量趋势变化 'period': 10, 'source': 'vol' } pre_args2 = { 'idt_type': 'maqs', # 量趋势变化 'period': 20, 'source': 'vol' } p10.add_condition(pre_args1, pre_args2, '>') stg.init_pools_cnds_matrix() stg.init_ref_assets() end_date = trade_day_str start_date = raw_data.previous_trade_day(end_date, 2) stg.update_cycles(start_date=start_date, end_date=end_date) # =================数据准备================= data = [] # [(数据1, 数据2, 数据3), (...)]存放用于报告显示的数据 X = 2 # 聚合的程度%限值 for asset in p10.assets.values(): ts_code = asset.ts_code name = asset.name # ----从an_<ts_code>.xml读入comment tree = load_xml(ts_code) if isinstance(tree, ET.ElementTree): root = tree.getroot() comment1 = root.find('comment1').find('content').text comment2 = root.find('comment2').find('content').text else: comment1 = '' comment2 = '' # ----20日归% try: ma20_last, = asset.ma_20.df_idt.head(1)['MA'].values by_price = asset.by_price ma20_gl = (by_price / ma20_last - 1) * 100 # close与ma_20的归离率 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; ma20_gl AttributeError, set value = -99', log_args) ma20_gl = -99 # ----20MA变化 try: maqs20, = asset.maqs_20.df_idt.head(1)['MAQS'].values maqs20 = maqs20 * 1000 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; maqs20 AttributeError, set value = -99', log_args) maqs20 = -999 # ----60MA变化 try: maqs60, = asset.maqs_60.df_idt.head(1)['MAQS'].values maqs60 = maqs60 * 1000 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]rpt_d_basic() ts_code:{0[0]}; maqs60 AttributeError, set value = -99', log_args) maqs60 = -999 # ----量20MA变化 try: maqs_vol_20, = asset.maqs_vol_20.df_idt.head(1)['MAQS'].values maqs_vol_20 = maqs_vol_20 * 1000 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]rpt_d_basic() ts_code:{0[0]}; maqs_vol_20 AttributeError, set value = -99', log_args) maqs_vol_20 = -99 # ----量10MA变化 try: maqs_vol_10, = asset.maqs_vol_10.df_idt.head(1)['MAQS'].values maqs_vol_10 = maqs_vol_10 * 1000 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]rpt_d_basic() ts_code:{0[0]}; maqs_vol_10 AttributeError, set value = -99', log_args) maqs_vol_10 = -99 # ----价聚合<x%天数的占比(最近20个交易日中) df = asset.majh_60_20_5.df_idt DAYS = 20 # 交易日窗口 try: sr = df.head(DAYS)['MAJH'] # 如果数据少于20个,有几个取几个 n = len(sr) if n > 0: n_meet = len(sr[sr < X]) jh_pct = n_meet / n # 聚合天数的占比 else: jh_pct = 0 except (AttributeError, TypeError): log_args = [asset.ts_code] add_log( 30, '[fn]rpt_d_basic() ts_code:{0[0]}; jh_pct AttributeError, set value = -0.99', log_args) jh_pct = -0.99 # ----吸资归离, 10D 与 250D try: jdxz10, = asset.jdxz_10.df_idt.head(1)['JDXZ'].values jdxz250, = asset.jdxz_250.df_idt.head(1)['JDXZ'].values xz_rate = jdxz10 / jdxz250 - 1 except Exception as e: log_args = [asset.ts_code, e] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; xz_rate except type:{0[1]} to catch', log_args) xz_rate = -99 # ----吸资10QS` ````` try: xz_current, xz_previous = asset.jdxz_10.df_idt.head( 2)['JDXZ'].values xzqs = (xz_current / xz_previous - 1) * 100 except Exception as e: log_args = [asset.ts_code, e] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; xzqs except type:{0[1]} to catch', log_args) xzqs = -99 # ----价多空头排列天数 try: p_dktp, = asset.dktp_5_10_20.df_idt.head(1)['DKTP'].values except Exception as e: log_args = [asset.ts_code, e] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; p_dktp except type:{0[1]} to catch', log_args) p_dktp = -99 # ----量多空头排列天数 try: v_dktp, = asset.dktp_vol_5_10_20.df_idt.head(1)['DKTP'].values except Exception as e: log_args = [asset.ts_code, e] add_log( 20, '[fn]rpt_d_basic() ts_code:{0[0]}; v_dktp except type:{0[1]} to catch', log_args) v_dktp = -99 # ----添加数据 data.append( (ts_code, name, comment1, comment2, ma20_gl, maqs20, maqs60, maqs_vol_10, maqs_vol_20, jh_pct, xz_rate, xzqs, p_dktp, v_dktp)) # =================报告基础================= workbook = xlw.Workbook(file_path) ws1 = workbook.add_worksheet('日报') # worksheet #1 fmt_std = workbook.add_format(d_std) fmt_wrap = workbook.add_format(d_wrap) fmt_rpt_title = workbook.add_format(d_rpt_title) fmt_center = workbook.add_format(d_center) # 居中 fmt_int = workbook.add_format(d_int) # 整数 fmt_f1d = workbook.add_format(d_f1d) # 1位小数 fmt_f2d = workbook.add_format(d_f2d) # 2位小数 fmt_f3d = workbook.add_format(d_f3d) # 3位小数 fmt_pct = workbook.add_format(d_pct) # 0% fmt_pct1d = workbook.add_format(d_pct1d) # 1.1% fmt_pct2d = workbook.add_format(d_pct2d) # 2.22% # 与data对应的显示格式 # ts_code 名称 备注 备注 20日归 maqs20 maqs60 formats = [ fmt_center, fmt_center, fmt_wrap, fmt_wrap, fmt_f2d, fmt_f2d, fmt_f2d ] # 量10QS 量20QS 聚合占比 吸资归离 吸资10QS 价多空排 量多空排 formats = formats + [ fmt_f2d, fmt_f2d, fmt_pct, fmt_f2d, fmt_f2d, fmt_int, fmt_int ] # =================报告数据================= # ----标题栏 ws1.write_string('A1', trade_day_str + ' ' + 'Report Daily Basic', fmt_rpt_title) ws1.set_row(0, 19) # 第一行,标题栏行高 ws1.set_row(1, options={'hidden': True}) # 第二行,分隔行行高 # ----表头 head = ('代码', '名称', '备注', '备注', '价20归%', '价20QS‰', '价60QS‰', '量10QS‰', '量20QS‰', '聚2%天比', '吸资归离', '吸资10QS', '价多空排', '量多空排') ws1.write_row('A3', head, fmt_center) ws1.write_comment('A1', '确保下载数据当日数据后再生成报表!') ws1.write_comment('E3', '(by_price / ma20_last - 1) * 100') ws1.write_comment('F3', 'maqs_20 * 1000') ws1.write_comment('G3', 'maqs_60 * 1000') ws1.write_comment('H3', 'maqs_vol_10 * 1000') ws1.write_comment('I3', 'maqs_vol_20 * 1000') ws1.write_comment('J3', '在20个交易日内,majh<' + str(X) + '%天数的占比 周期5, 10, 20') ws1.write_comment('K3', '10日吸资比 / 250日吸资比 -1') ws1.write_comment('L3', '10日吸资比变化率 * 100') ws1.write_comment('M3', '价多空头排列天数') ws1.write_comment('N3', '量多空头排列天数') # ----填充数据 row = 3 assert len(head) == len(formats) for item in data: for column in range(len(head)): ws1.write(row, column, item[column], formats[column]) row += 1 # =================收尾格式================= ws1.set_column(0, 0, 10.2) # 代码 ws1.set_column(1, 1, 8.2) # 名称 ws1.set_column(2, 3, 15) # 备注 max_column = len(head) - 1 max_row = row - 1 ws1.set_landscape() # 页面横向 ws1.set_paper(9) # 设置A4纸 ws1.center_horizontally() # 居中 ws1.set_margins(0.3, 0.3, 0.3, 1) ws1.set_footer('&C&P of &N') # 设置页脚 ws1.repeat_rows(0, 2) # 重复打印行 ws1.repeat_columns(0, 1) # 重复打印列 ws1.freeze_panes(3, 2) # freeze 3行2列 workbook.close() pass