microsoft / qlib

Qlib is an AI-oriented quantitative investment platform that aims to realize the potential, empower research, and create value using AI technologies in quantitative investment, from exploring ideas to implementing productions. Qlib supports diverse machine learning modeling paradigms. including supervised learning, market dynamics modeling, and RL.
https://qlib.readthedocs.io/en/latest/
MIT License
15.2k stars 2.6k forks source link

AttributeError: module 'qlib.contrib.report' has no attribute 'cumulative_return_graph' #394

Open liu100286 opened 3 years ago

liu100286 commented 3 years ago

🐛 Bug Description

To Reproduce

Steps to reproduce the behavior:

Copyright (c) Microsoft Corporation.

Licensed under the MIT License.

import sys from pathlib import Path

import qlib import pandas as pd from qlib.config import REG_CN from qlib.contrib.model.gbdt import LGBModel from qlib.contrib.data.handler import Alpha158 from qlib.contrib.strategy.strategy import TopkDropoutStrategy from qlib.contrib.evaluate import risk_analysis, backtest, long_short_backtest from qlib.contrib.evaluate import (backtest as normal_backtest,risk_analysis,) from qlib.utils import exists_qlib_data, init_instance_by_config, flatten_dict from qlib.workflow import R from qlib.workflow.record_temp import SignalRecord, PortAnaRecord from qlib.tests.data import GetData

if name == "main":

# use default data
provider_uri = "~/.qlib/qlib_data/cn_data"  # target_dir
if not exists_qlib_data(provider_uri):
    print(f"Qlib data is not found in {provider_uri}")
    GetData().qlib_data(target_dir=provider_uri, region=REG_CN)

qlib.init(provider_uri=provider_uri, region=REG_CN)

market = "csi300"
# market=["SH000903"]
benchmark = "SH000300"

###################################
# train model
###################################
data_handler_config = {
    "start_time": "2008-01-01",
    "end_time": "2020-08-01",
    "fit_start_time": "2008-01-01",
    "fit_end_time": "2014-12-31",
    "instruments": market,
}

task = {
    "model": {
        "class": "LGBModel",
        "module_path": "qlib.contrib.model.gbdt",
        "kwargs": {
            "loss": "mse",
            "colsample_bytree": 0.8879,
            "learning_rate": 0.0421,
            "subsample": 0.8789,
            "lambda_l1": 205.6999,
            "lambda_l2": 580.9768,
            "max_depth": 8,
            "num_leaves": 210,
            "num_threads": 20,
        },
    },
    "dataset": {
        "class": "DatasetH",
        "module_path": "qlib.data.dataset",
        "kwargs": {
            "handler": {
                "class": "Alpha158",
                "module_path": "qlib.contrib.data.handler",
                "kwargs": data_handler_config,
            },
            "segments": {
                "train": ("2008-01-01", "2014-12-31"),
                "valid": ("2015-01-01", "2016-12-31"),
                "test": ("2017-01-01", "2020-08-01"),
            },
        },
    },
}

port_analysis_config = {
    "strategy": {
        "class": "TopkDropoutStrategy",
        "module_path": "qlib.contrib.strategy.strategy",
        "kwargs": {
            "topk": 50,
            "n_drop": 5,
        },
    },
    "backtest": {
        "verbose": False,
        "limit_threshold": 0.095,
        "account": 100000000,
        "benchmark": benchmark,
        "deal_price": "close",
        "open_cost": 0.0005,
        "close_cost": 0.0015,
        "min_cost": 5,
        "return_order": True,
    },
}

# model initialization
model = init_instance_by_config(task["model"])
dataset = init_instance_by_config(task["dataset"])

# NOTE: This line is optional
# It demonstrates that the dataset can be used standalone.
example_df = dataset.prepare("train")
print(example_df.head())

# start exp
with R.start(experiment_name="backtest_analysis"):
    R.log_params(**flatten_dict(task))
    model.fit(dataset)
    R.save_objects(**{"params.pkl": model})

    # prediction
    recorder = R.get_recorder()
    ba_rid = recorder.id
    sr = SignalRecord(model, dataset, recorder)
    sr.generate()

    # backtest. If users want to use backtest based on their own prediction,
    # please refer to https://qlib.readthedocs.io/en/latest/component/recorder.html#record-template.
    print("===PortAnaRecord===")
    par = PortAnaRecord(recorder, port_analysis_config)
    par.generate()

    # from qlib.contrib.report import analysis_model, analysis_position

    # recorder = R.get_recorder(ba_rid, experiment_name="backtest_analysis")
    import qlib.contrib.report as qcr
    from qlib.contrib.report import analysis_model, analysis_position
    from qlib.data import D

    pred_df = recorder.load_object("pred.pkl")
    pred_df_dates = pred_df.index.get_level_values(level='datetime')
    report_normal_df = recorder.load_object("portfolio_analysis/report_normal.pkl")
    positions = recorder.load_object("portfolio_analysis/positions_normal.pkl")
    analysis_df = recorder.load_object("portfolio_analysis/port_analysis.pkl")

    # from qlib.contrib.strategy import TopkDropoutStrategy

    # backtest parameters
    bparas = {}
    bparas['limit_threshold'] = 0.095
    bparas["benchmark"] = benchmark

    bparas['account'] = 1000000000

    sparas = {}
    sparas['topk'] = 50
    sparas['n_drop'] = 5
    strategy = TopkDropoutStrategy(**sparas)
    print("strategy : " , strategy)
    bparas['class'] = strategy

    report_normal_df, positions = backtest(pred_df, **bparas)
    # <qlib.contrib.strategy.strategy.TopkDropoutStrategy object at 0x7f4347ba3f28>

    pred_df_dates = pred_df.index.get_level_values(level='datetime')
    features_df = D.features(D.instruments('csi300'), ['Ref($close, -1)/$close - 1'], pred_df_dates.min(),
                             pred_df_dates.max())
    features_df.columns = ['label']
    print(qcr.GRAPH_NAME_LIST)
    qcr.cumulative_return_graph(positions, report_normal_df, features_df)

Execute the above code!!!

Expected Behavior

Screenshot

['analysis_position.report_graph', 'analysis_position.score_ic_graph', 'analysis_position.cumulative_return_graph', 'analysis_position.risk_analysis_graph', 'analysis_position.rank_label_graph', 'analysis_model.model_performance_graph'] [5151:MainThread](2021-04-19 12:38:55,455) ERROR - qlib.workflow - [utils.py:35] - An exception has been raised[AttributeError: module 'qlib.contrib.report' has no attribute 'cumulative_return_graph']. File "examples/workflow_by_code.py", line 171, in qcr.cumulative_return_graph(positions, report_normal_df, features_df) AttributeError: module 'qlib.contrib.report' has no attribute 'cumulative_return_graph'

Note: User could run cd scripts && python collect_info.py all under project directory to get system information and paste them here directly.

Additional Notes

Derek-Wds commented 3 years ago

Hi @liu100286 , thanks for the bug report. Have you tried this command: qcr.analysis_position.cumulative_return_graph(positions, report_normal_df, features_df). It seems that you are missing one of the folders in the path while calling the cumulative_return_graph function.

Sorry for the misunderstanding in the documents. We will update the related docs soon.

liu100286 commented 3 years ago

ok,thanks. I see an example from the https://qlib.readthedocs.io/en/latest/reference/api.html?highlight=cumulative_return_graph.