Example #1
0
def summary_release_2_docx(title, img_meta_dic_list, stg_run_id=None, enable_clean_cache=True):
    """
    生成 预测成功率趋势报告
    :param title:
    :param img_meta_dic_list:
    :param stg_run_id:
    :param enable_clean_cache:
    :return:
    """
    logger.debug('生成报告开始')
    # 生成 docx 文件
    document = docx.Document()
    # 设置默认字体
    document.styles['Normal'].font.name = '微软雅黑'
    document.styles['Normal']._element.rPr.rFonts.set(docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')
    # 创建自定义段落样式(第一个参数为样式名, 第二个参数为样式类型, 1为段落样式, 2为字符样式, 3为表格样式)
    UserStyle1 = document.styles.add_style('UserStyle1', 1)
    # 设置字体尺寸
    UserStyle1.font.size = docx.shared.Pt(40)
    # 设置字体颜色
    UserStyle1.font.color.rgb = docx.shared.RGBColor(0xff, 0xde, 0x00)
    # 居中文本
    UserStyle1.paragraph_format.alignment = docx.enum.text.WD_ALIGN_PARAGRAPH.CENTER
    # 设置中文字体
    UserStyle1.font.name = '微软雅黑'
    UserStyle1._element.rPr.rFonts.set(docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')

    # 文件内容
    document.add_heading(title, 0).alignment = docx.enum.text.WD_ALIGN_PARAGRAPH.CENTER
    document.add_paragraph('')
    document.add_paragraph('')
    heading_size = 1
    for num, info_dic in enumerate(img_meta_dic_list, start=1):
        trade_date_last_train = info_dic['trade_date_last_train']
        trade_date_end = info_dic['trade_date_end']
        document.add_heading(
            f"{num}、{date_2_str(trade_date_last_train)} - {date_2_str(trade_date_end)}", heading_size)
        split_point_list = info_dic['split_point_list']
        if split_point_list is None:
            p = document.add_paragraph(f"{num}.1) 日期区间段1个:\n")
            p.add_run(f'\t1) {date_2_str(trade_date_last_train)} ~ {date_2_str(trade_date_end)}\n')
        else:
            p = document.add_paragraph(f"{num}.1) 日期区间段{len(split_point_list) - 1}个:\n")
            for num2, (point1, point2) in enumerate(
                    iter_2_range(split_point_list, has_left_outer=False, has_right_outer=False), start=1):
                p.add_run(f'\t{num2}) {date_2_str(point1)} ~ {date_2_str(point2)}\n')

        document.add_paragraph(f"{num}.2) 模型路径:\n\t{info_dic['module_file_path']}")
        document.add_paragraph(f"{num}.3) 取样状态(random_state):\n\t{info_dic['predict_test_random_state']}")
        document.add_paragraph(f"{num}.4) 展示数据长度:\n\t{info_dic['in_range_count']}")
        document.add_paragraph(f"{num}.5) 预测准确率趋势图:")
        document.add_picture(info_dic['img_file_path'])

    file_name = f"{title}.docx"
    file_path = os.path.join(get_report_folder_path(stg_run_id), file_name)
    document.save(file_path)
    if enable_clean_cache:
        clean_cache()
    logger.debug('生成报告结束。%s', file_path)
    return file_path
Example #2
0
def summary_md_2_docx(
    md_df: pd.DataFrame,
    percentiles=[0.2, 0.33, 0.5, 0.66, 0.8],
    risk_free=0.03,
    close_key=None,
    enable_show_plot=True,
    enable_save_plot=False,
    name=None,
    func_kwargs_dic={},
    enable_clean_cache=True,
):
    """
    汇总展示数据分析结果,同时以 dict 形式返回各项指标分析结果
    第一个返回值,df的各项分析结果
    第二个返回值,各个列的各项分析结果
    :param md_df:
    :param percentiles:分为数信息
    :param risk_free:无风险收益率
    :param close_key:对哪些列的数据执行统计
    :param enable_show_plot:显示plot
    :param enable_save_plot:保存plot
    :param name:
    :param func_kwargs_dic:
    :param enable_clean_cache:
    :return:
    """
    ret_dic, each_col_dic, file_path_dic = summary_md(
        md_df,
        percentiles=percentiles,
        risk_free=risk_free,
        close_key=close_key,
        enable_show_plot=enable_show_plot,
        enable_save_plot=enable_save_plot,
        name=name,
        func_kwargs_dic=func_kwargs_dic)

    logger.debug('file_path_dic')
    for num, (k, v) in enumerate(file_path_dic.items(), start=1):
        if isinstance(v, dict):
            for num2, (k2, v2) in enumerate(v.items(), start=1):
                if isinstance(v2, dict):
                    for num3, (k3, v3) in enumerate(v2.items(), start=1):
                        logger.debug("%d.%d.%d) %s %s %s -> %s", num, num2,
                                     num3, k, k2, k3, v3)
                else:
                    logger.debug("%d.%d) %s %s -> %s", num, num2, k, k2, v2)
        else:
            logger.debug("%d) %s -> %s", num, k, v)

    # 生成 docx 文档将所需变量
    heading_title = f'数据分析报告 {date_2_str(min(md_df.index))} - {date_2_str(max(md_df.index))} ({md_df.shape[0]} days)'

    # 生成 docx 文件
    document = docx.Document()
    # 设置默认字体
    document.styles['Normal'].font.name = '微软雅黑'
    document.styles['Normal']._element.rPr.rFonts.set(
        docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')
    # 创建自定义段落样式(第一个参数为样式名, 第二个参数为样式类型, 1为段落样式, 2为字符样式, 3为表格样式)
    UserStyle1 = document.styles.add_style('UserStyle1', 1)
    # 设置字体尺寸
    UserStyle1.font.size = docx.shared.Pt(40)
    # 设置字体颜色
    UserStyle1.font.color.rgb = docx.shared.RGBColor(0xff, 0xde, 0x00)
    # 居中文本
    UserStyle1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
    # 设置中文字体
    UserStyle1.font.name = '微软雅黑'
    UserStyle1._element.rPr.rFonts.set(docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')

    # 文件内容
    document.add_heading(heading_title,
                         0).alignment = WD_ALIGN_PARAGRAPH.CENTER
    document.add_paragraph('')
    document.add_paragraph('')
    heading_count = 1
    if 'warning' in ret_dic:
        document.add_heading(f'{heading_count}、警告信息(Warning)', 1)
        warning_list = ret_dic['warning']
        p = document.add_paragraph('')
        for msg in warning_list:
            r = p.add_run(msg)
            # r.bold = True
            r.font.color.rgb = RGBColor(0xaf, 0x26, 0x26)
            p.add_run('\n')

        heading_count += 1
        document.add_page_break()

    if 'rr' in file_path_dic:
        document.add_heading(f'{heading_count}、行情曲线', 1)
        # 增加图片(此处使用相对位置)
        document.add_picture(
            file_path_dic['rr'])  # , width=docx.shared.Inches(1.25)
        heading_count += 1
        # 添加分页符
        document.add_page_break()

    if 'hist' in file_path_dic:
        document.add_heading(f'{heading_count}、Histgram 分布图', 1)
        document.add_picture(file_path_dic['hist'])
        heading_count += 1

    if 'rr_quantile' in ret_dic:
        document.add_heading(f'{heading_count}、分位数信息(Quantile)', 1)
        rr_quantile_df = ret_dic['rr_quantile']
        format_by_col = {_: FORMAT_2_PERCENT for _ in rr_quantile_df.columns}
        df_2_table(document,
                   rr_quantile_df,
                   format_by_col=format_by_col,
                   max_col_count=5)
        heading_count += 1
        document.add_page_break()

    if 'hist_future_n_rr' in file_path_dic:
        document.add_heading(f'{heading_count}、未来N日收益率最高最低值分布图', 1)
        quantile_dic = ret_dic['hist_future_n_rr']['quantile_dic']
        for num, ((n_day, col_name), file_path) in enumerate(
                file_path_dic['hist_future_n_rr'].items(), start=1):
            document.add_heading(
                f'{heading_count}.{num}) 未来 {n_day} 日 {col_name} 收益率最高最低值分布图',
                2)
            document.add_picture(file_path)
            document.add_heading(f'{heading_count}.{num}.1) 分位数信息', 3)
            data_df = quantile_dic[(n_day, col_name)]
            df_2_table(
                document,
                data_df,
                format_by_index={_: FORMAT_2_PERCENT
                                 for _ in data_df.index})
            document.add_heading(f'{heading_count}.{num}.2) 三分类标签分布比例', 3)
            for (min_pct, max_pct
                 ), distribution_rate_df in ret_dic['label_distribution'][(
                     n_day, col_name)].items():
                file_path = file_path_dic['label_distribution'][(
                    n_day, col_name)][(min_pct, max_pct)]
                document.add_picture(file_path)
                distribution_rate_df.rename(columns={
                    1: f'1 under {min_pct * 100:.2f}%',
                    2: f'2 over {max_pct * 100:.2f}%'
                },
                                            inplace=True)
                df_2_table(document,
                           distribution_rate_df,
                           format_by_index={
                               _: FORMAT_2_PERCENT
                               for _ in distribution_rate_df.index
                           })

            document.add_page_break()

        heading_count += 1

    if 'drawdown' in file_path_dic:
        document.add_heading(f'{heading_count}、行情回撤曲线', 1)
        document.add_picture(file_path_dic['drawdown'])
        heading_count += 1
        document.add_page_break()

    if 'scatter_matrix' in file_path_dic:
        document.add_heading(f'{heading_count}、散点图矩阵图(Scatter Matrix)', 1)
        document.add_picture(file_path_dic['scatter_matrix'])
        heading_count += 1
        document.add_page_break()

    if 'correlation' in file_path_dic:
        document.add_heading(f'{heading_count}、相关性矩阵图(Correlation)', 1)
        document.add_picture(file_path_dic['correlation'])
        heading_count += 1
        document.add_page_break()

    if 'stats' in file_path_dic:
        document.add_heading(f'{heading_count}、绩效统计数据(Porformance stat)', 1)
        stats_df = ret_dic['stats'].stats
        stats_df_2_docx_table(stats_df, document)
        heading_count += 1
        document.add_page_break()

    # 逐列分析
    col_name = close_key
    # 文件内容
    heading_title = f'{col_name} 数据分析结果'
    document.add_heading(heading_title,
                         0).alignment = WD_ALIGN_PARAGRAPH.CENTER
    document.add_paragraph('')
    document.add_paragraph('')
    heading_count = 1

    if 'rr_quantile' in ret_dic:
        document.add_heading(f'{heading_count}、分位数信息(Quantile)', 1)
        data_df = each_col_dic[col_name]['rr_quantile']
        format_by_col = {_: FORMAT_2_PERCENT for _ in data_df.columns}
        df_2_table(document,
                   data_df,
                   format_by_col=format_by_col,
                   max_col_count=5)
        heading_count += 1

    if f'{col_name} hist' in file_path_dic:
        document.add_heading(f'{heading_count}、Histgram 分布图', 1)
        document.add_picture(file_path_dic[f'{col_name} hist'])
        heading_count += 1
        document.add_page_break()

    # 保存文件
    file_name = f"MD{' ' if name is None else ' ' + name} " \
        f"{date_2_str(min(md_df.index))} - {date_2_str(max(md_df.index))} " \
        f"({md_df.shape[0]} days) {datetime_2_str(datetime.datetime.now(), STR_FORMAT_DATETIME_4_FILE_NAME)}.docx"
    file_path = os.path.join(get_report_folder_path(), file_name)
    document.save(file_path)
    if enable_clean_cache:
        clean_cache()

    return file_path
Example #3
0
def summary_stg_2_docx(stg_run_id=None,
                       enable_save_plot=True,
                       enable_show_plot=False,
                       enable_clean_cache=True,
                       doc_file_path=None):
    """
    生成策略分析报告
    :param stg_run_id:
    :param enable_save_plot:
    :param enable_show_plot:
    :param enable_clean_cache:
    :param doc_file_path: 可以是目录 或 文件名路径
    :return:
    """
    info = get_stg_run_info(stg_run_id)
    stg_run_id = info.stg_run_id
    stg_name = info.stg_name
    run_mode = RunMode(info.run_mode)
    kwargs = {
        "enable_show_plot": enable_show_plot,
        "enable_save_plot": enable_save_plot,
        "run_mode": run_mode,
        "stg_run_id": stg_run_id
    }
    if run_mode == RunMode.Backtest_FixPercent:
        sum_df, symbol_rr_dic = get_rr_with_md(stg_run_id, compound_rr=True)
    else:
        sum_df, symbol_rr_dic = get_rr_with_md(stg_run_id, compound_rr=False)

    if sum_df is None or sum_df.shape[0] == 0:
        logger.warning('stg_run_id=%d 没有获取到 sum_df', stg_run_id)
        file_path = None
        return file_path

    ret_dic, each_col_dic, file_path_dic = summary_rr(sum_df, **kwargs)

    _, file_path = show_trade(**kwargs)
    file_path_dic['trade'] = file_path
    df, file_path = show_cash_and_margin(**kwargs)
    file_path_dic['cash_and_margin'] = file_path

    # 生成 docx 文档将所需变量
    heading_title = f'策略分析报告[{stg_run_id} {stg_name}] ' \
        f'{date_2_str(min(sum_df.index))} - {date_2_str(max(sum_df.index))} ({sum_df.shape[0]} days)'

    # 生成 docx 文件
    document = docx.Document()
    # 设置默认字体
    document.styles['Normal'].font.name = '微软雅黑'
    document.styles['Normal']._element.rPr.rFonts.set(
        docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')
    # 创建自定义段落样式(第一个参数为样式名, 第二个参数为样式类型, 1为段落样式, 2为字符样式, 3为表格样式)
    UserStyle1 = document.styles.add_style('UserStyle1', 1)
    # 设置字体尺寸
    UserStyle1.font.size = docx.shared.Pt(40)
    # 设置字体颜色
    UserStyle1.font.color.rgb = docx.shared.RGBColor(0xff, 0xde, 0x00)
    # 居中文本
    UserStyle1.paragraph_format.alignment = WD_ALIGN_PARAGRAPH.CENTER
    # 设置中文字体
    UserStyle1.font.name = '微软雅黑'
    UserStyle1._element.rPr.rFonts.set(docx.oxml.ns.qn('w:eastAsia'), '微软雅黑')

    # 文件内容
    document.add_heading(heading_title,
                         0).alignment = WD_ALIGN_PARAGRAPH.CENTER
    document.add_paragraph('')
    document.add_paragraph('')
    heading_count = 1
    document.add_heading(f'{heading_count}、策略回测收益曲线', 1)
    # 增加图片(此处使用相对位置)
    document.add_picture(
        file_path_dic['rr'])  # , width=docx.shared.Inches(1.25)
    heading_count += 1
    # 添加分页符
    document.add_page_break()

    document.add_heading(f'{heading_count}、策略回撤曲线', 1)
    document.add_picture(file_path_dic['drawdown'])
    heading_count += 1
    document.add_page_break()

    if run_mode != RunMode.Backtest_FixPercent:
        document.add_heading(f'{heading_count}、现金与仓位堆叠图', 1)
        document.add_picture(file_path_dic['cash_and_margin'])
        heading_count += 1
        document.add_page_break()

    document.add_heading(f'{heading_count}、散点图矩阵图(Scatter Matrix)', 1)
    document.add_picture(file_path_dic['scatter_matrix'])
    heading_count += 1
    document.add_page_break()

    document.add_heading(f'{heading_count}、相关性矩阵图(Correlation)', 1)
    document.add_picture(file_path_dic['correlation'])
    heading_count += 1
    document.add_page_break()

    document.add_heading(f'{heading_count}、绩效统计数据(Porformance stat)', 1)
    stats_df = ret_dic['stats'].stats
    stats_df_2_docx_table(stats_df, document)
    heading_count += 1
    document.add_page_break()

    # 交易记录
    document.add_heading(f'{heading_count}、买卖点记录', 1)
    document.add_picture(file_path_dic['trade'])
    heading_count += 1
    document.add_page_break()

    # 保存文件
    if doc_file_path is not None:
        if os.path.isdir(doc_file_path):
            folder_path, file_name = doc_file_path, ''
        else:
            folder_path, file_name = os.path.split(doc_file_path)
    else:
        folder_path, file_name = get_report_folder_path(stg_run_id), ''

    if folder_path != '' and not os.path.exists(folder_path):
        os.makedirs(folder_path)

    if file_name == '':
        try:
            calc_mode_str = CalcMode(
                json.loads(
                    info.trade_agent_params_list)[0]['calc_mode']).name + " "
        except:
            calc_mode_str = " "

        # run_mode_str = run_mode.name + " "
        file_name = f"{stg_run_id} {stg_name} {calc_mode_str}" \
            f"{date_2_str(min(sum_df.index))} - {date_2_str(max(sum_df.index))} ({sum_df.shape[0]} days) " \
            f"{datetime_2_str(datetime.datetime.now(), STR_FORMAT_DATETIME_4_FILE_NAME)}.docx"
        file_path = os.path.join(folder_path, file_name)
    else:
        file_path = doc_file_path

    document.save(file_path)
    if enable_clean_cache:
        clean_cache()

    return file_path