1
0
mirror of https://github.com/microsoft/qlib.git synced 2026-07-16 09:11:00 +08:00

release-0.5.0 (#1)

* init commit

* change the version number

* rich the docs&fix cache docs

* update index readme

* Modify cache class name

* Modify sharpe to information_ratio

* Modify Group- to Group

* add the description of graphical results & fix the backtest docs

* fix docs in details

* update docs

* Update introduction.rst

* Update README.md

* Update introduction.rst

* Update introduction.rst

* Update introduction.rst

* Update installation.rst

* Update installation.rst

* Update initialization.rst

* Update getdata.rst

* Update integration.rst

* Update initialization.rst

* Update getdata.rst

* Update estimator.rst

Modify some typos.

* Update README.md

Modify the typos.

* Update initialization.rst

* Update data.rst

* Update report.rst

* Update estimator.rst

* Update cumulative_return.py

* Update model.rst

* Update rank_label.py

* Update cumulative_return.py

* Update strategy.rst

* Update getdata.rst

* Update backtest.rst

* Update integration.rst

* Update getdata.rst

* Update introduction.rst

* Update introduction.rst

* Update README.md

* Update report.rst

* Update integration.rst

Fix typos

* Update installation.rst

Fix typos

* Update getdata.rst

* Update initialization.rst

Fix typos.

* add quick start docs&fix detials

* fix estimator docs & fix strategy docs

* fix the cahce in data.rst

* update documents

* Fix Corr && Rsquare

* fix data retrival example to csi300 & fix a data bug

* fix filter bug

* Fix data collector

* Modift model args

* add the log & fix README.md\quick.rst

* add enviroment depend & add intoduction of qlib-server online mode

* fix image center fomat & set log_only of docs is True

* fix README.md format

* update data preparation & readme logo image

* get_data support version

* Modify analysis names

* Modify analysis graph

* update report.rst & data.rst

* commmit estimator for merge

* minimal requirements

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update README.md

* Update READEME.md

* Update READEME.md

* update estimator

* Fix doc urls

* fix get_data.py docstring

* update test_get_data.py

* Upate docs

* Upate docs

* Upate docs

Co-authored-by: bxdd <bxddream@gmail.com>
Co-authored-by: zhupr <zhu.pengrong@foxmail.com>
Co-authored-by: Wendi Li <wendili.academic@qq.com>
Co-authored-by: Dingsu Wang <dingsu.wang@gmail.com>
Co-authored-by: bxdd <45119470+bxdd@users.noreply.github.com>
Co-authored-by: cslwqxx <cslwqxx@users.noreply.github.com>
This commit is contained in:
you-n-g
2020-09-23 23:01:39 -05:00
committed by GitHub
parent 99ebd87cba
commit de9e13b171
82 changed files with 1580 additions and 1145 deletions

View File

@@ -121,7 +121,7 @@ class Estimator(object):
else:
raise ValueError("unexpected mode: %s" % self.ex_config.mode)
analysis = self.backtest()
self.logger.info(analysis)
print(analysis)
self.logger.info(
"experiment id: {}, experiment name: {}".format(self.ex.experiment.current_run._id, self.ex_config.name)
)
@@ -182,8 +182,8 @@ class Estimator(object):
# analysis["pred_long"] = risk_analysis(long_short_reports["long"])
# analysis["pred_short"] = risk_analysis(long_short_reports["short"])
# analysis["pred_long_short"] = risk_analysis(long_short_reports["long_short"])
analysis["sub_bench"] = risk_analysis(report_normal["return"] - report_normal["bench"])
analysis["sub_cost"] = risk_analysis(report_normal["return"] - report_normal["bench"] - report_normal["cost"])
analysis["excess_return_without_cost"] = risk_analysis(report_normal["return"] - report_normal["bench"])
analysis["excess_return_with_cost"] = risk_analysis(report_normal["return"] - report_normal["bench"] - report_normal["cost"])
analysis_df = pd.concat(analysis) # type: pd.DataFrame
TimeInspector.log_cost_time(
"Finished generating analysis," " average turnover is: {0:.4f}.".format(report_normal["turnover"].mean())

View File

@@ -1,7 +1,6 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# coding=utf-8
import argparse
import importlib

View File

@@ -27,14 +27,15 @@ def risk_analysis(r, N=252):
r : pandas.Series
daily return series
N: int
scaler for annualizing sharpe ratio (day: 250, week: 50, month: 12)
scaler for annualizing information_ratio (day: 250, week: 50, month: 12)
"""
mean = r.mean()
std = r.std(ddof=1)
annual = mean * N
sharpe = mean / std * np.sqrt(N)
mdd = (r.cumsum() - r.cumsum().cummax()).min()
data = {"mean": mean, "std": std, "annual": annual, "sharpe": sharpe, "mdd": mdd}
annualized_return = mean * N
information_ratio = mean / std * np.sqrt(N)
max_drawdown = (r.cumsum() - r.cumsum().cummax()).min()
data = {"mean": mean, "std": std, "annualized_return": annualized_return,
"information_ratio": information_ratio, "max_drawdown": max_drawdown}
res = pd.Series(data, index=data.keys()).to_frame("risk")
return res

View File

@@ -279,7 +279,7 @@ class Operator(object):
self.show(id, path, bench)
def show(self, id, path, bench="SH000905"):
"""show the newly report (mean, std, sharpe, annual)
"""show the newly report (mean, std, information_ratio, annualized_return)
Parameters
----------
@@ -299,14 +299,14 @@ class Operator(object):
report["bench"] = bench
analysis_result = {}
r = (report["return"] - report["bench"]).dropna()
analysis_result["sub_bench"] = risk_analysis(r)
analysis_result["excess_return_without_cost"] = risk_analysis(r)
r = (report["return"] - report["bench"] - report["cost"]).dropna()
analysis_result["sub_cost"] = risk_analysis(r)
analysis_result["excess_return_with_cost"] = risk_analysis(r)
print("Result:")
print("sub_bench:")
print(analysis_result["sub_bench"])
print("sub_cost:")
print(analysis_result["sub_cost"])
print("excess_return_without_cost:")
print(analysis_result["excess_return_without_cost"])
print("excess_return_with_cost:")
print(analysis_result["excess_return_with_cost"])
def run():

View File

@@ -53,7 +53,7 @@ class User:
def showReport(self, benchmark="SH000905"):
"""
show the newly report (mean, std, sharpe, annual)
show the newly report (mean, std, information_ratio, annualized_return)
Parameter
benchmark : string
bench that to be compared, 'SH000905' for csi500
@@ -61,14 +61,14 @@ class User:
bench = D.features([benchmark], ["$change"], disk_cache=True).loc[benchmark, "$change"]
report = self.account.report.generate_report_dataframe()
report["bench"] = bench
analysis_result = {"pred": {}, "sub_bench": {}, "sub_cost": {}}
analysis_result = {"pred": {}, "excess_return_without_cost": {}, "excess_return_with_cost": {}}
r = (report["return"] - report["bench"]).dropna()
analysis_result["sub_bench"][0] = risk_analysis(r)
analysis_result["excess_return_without_cost"][0] = risk_analysis(r)
r = (report["return"] - report["bench"] - report["cost"]).dropna()
analysis_result["sub_cost"][0] = risk_analysis(r)
analysis_result["excess_return_with_cost"][0] = risk_analysis(r)
self.logger.info("Result of porfolio:")
self.logger.info("sub_bench:")
self.logger.info(analysis_result["sub_bench"][0])
self.logger.info("sub_cost:")
self.logger.info(analysis_result["sub_cost"][0])
self.logger.info("excess_return_without_cost:")
self.logger.info(analysis_result["excess_return_without_cost"][0])
self.logger.info("excess_return_with_cost:")
self.logger.info(analysis_result["excess_return_with_cost"][0])
return report

View File

@@ -1,7 +1,7 @@
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
GRAPH_NAME_LISt = [
GRAPH_NAME_LIST = [
"analysis_position.report_graph",
"analysis_position.score_ic_graph",
"analysis_position.cumulative_return_graph",

View File

@@ -35,7 +35,7 @@ def _group_return(
# Group
t_df = pd.DataFrame(
{
"Group-%d"
"Group%d"
% (i + 1): pred_label_drop.groupby(level="datetime")["label"].apply(
lambda x: x[len(x) // N * i : len(x) // N * (i + 1)].mean()
)
@@ -45,11 +45,11 @@ def _group_return(
t_df.index = pd.to_datetime(t_df.index)
# Long-Short
t_df["long-short"] = t_df["Group-1"] - t_df["Group-%d" % N]
t_df["long-short"] = t_df["Group1"] - t_df["Group%d" % N]
# Long-Average
t_df["long-average"] = (
t_df["Group-1"] - pred_label.groupby(level="datetime")["label"].mean()
t_df["Group1"] - pred_label.groupby(level="datetime")["label"].mean()
)
t_df = t_df.dropna(how="all") # for days which does not contain label

View File

@@ -228,11 +228,11 @@ def cumulative_return_graph(
Graph desc:
- Axis X: Trading day
- Axis Y:
- Above axis Y: (((Ref($close, -1)/$close - 1) * weight).sum() / weight.sum()).cumsum()
- Above axis Y: `(((Ref($close, -1)/$close - 1) * weight).sum() / weight.sum()).cumsum()`
- Below axis Y: Daily weight sum
- In the sell graph, y < 0 stands for profit; in other cases, y > 0 stands for profit.
- In the buy_minus_sell graph, the y value of the weight graph at the bottom is buy_weight + sell_weight.
- In each graph, the red line in the histogram on the right represents the average.
- In the **sell** graph, `y < 0` stands for profit; in other cases, `y > 0` stands for profit.
- In the **buy_minus_sell** graph, the **y** value of the **weight** graph at the bottom is `buy_weight + sell_weight`.
- In each graph, the **red line** in the histogram on the right represents the average.
:param position: position data
:param report_normal:
@@ -250,7 +250,7 @@ def cumulative_return_graph(
:param label_data: `D.features` result; index is `pd.MultiIndex`, index name is [`instrument`, `datetime`]; columns names is [`label`].
**The ``label`` T is the change from T to T+1**, it is recommended to use ``close``, example: D.features(D.instruments('csi500'), ['Ref($close, -1)/$close-1'])
**The label T is the change from T to T+1**, it is recommended to use ``close``, example: `D.features(D.instruments('csi500'), ['Ref($close, -1)/$close-1'])`
.. code-block:: python

View File

@@ -99,7 +99,7 @@ def rank_label_graph(
:param position: position data; **qlib.contrib.backtest.backtest.backtest** result
:param label_data: **D.features** result; index is **pd.MultiIndex**, index name is **[instrument, datetime]**; columns names is **[label]**.
**The ``label`` T is the change from T to T+1**, it is recommended to use ``close``, example: D.features(D.instruments('csi500'), ['Ref($close, -1)/$close-1'])
**The label T is the change from T to T+1**, it is recommended to use ``close``, example: `D.features(D.instruments('csi500'), ['Ref($close, -1)/$close-1'])`
.. code-block:: python

View File

@@ -32,10 +32,10 @@ def _get_risk_analysis_data_with_report(
# analysis["pred_long_short"] = risk_analysis(report_long_short_df["long_short"])
if not report_normal_df.empty:
analysis["sub_bench"] = risk_analysis(
analysis["excess_return_without_cost"] = risk_analysis(
report_normal_df["return"] - report_normal_df["bench"]
)
analysis["sub_cost"] = risk_analysis(
analysis["excess_return_with_cost"] = risk_analysis(
report_normal_df["return"]
- report_normal_df["bench"]
- report_normal_df["cost"]
@@ -97,7 +97,7 @@ def _get_monthly_risk_analysis_with_report(report_normal_df: pd.DataFrame) -> pd
def _get_monthly_analysis_with_feature(
monthly_df: pd.DataFrame, feature: str = "annual"
monthly_df: pd.DataFrame, feature: str = "annualized_return"
) -> pd.DataFrame:
"""
@@ -156,7 +156,7 @@ def _get_monthly_risk_analysis_figure(report_normal_df: pd.DataFrame) -> Iterabl
# report_long_short_df=report_long_short_df,
)
for _feature in ["annual", "mdd", "sharpe", "std"]:
for _feature in ["annualized_return", "max_drawdown", "information_ratio", "std"]:
_temp_df = _get_monthly_analysis_with_feature(_monthly_df, _feature)
yield ScatterGraph(
_temp_df,
@@ -200,8 +200,8 @@ def risk_analysis_graph(
# analysis['pred_long'] = risk_analysis(report_long_short_df['long'])
# analysis['pred_short'] = risk_analysis(report_long_short_df['short'])
# analysis['pred_long_short'] = risk_analysis(report_long_short_df['long_short'])
analysis['sub_bench'] = risk_analysis(report_normal_df['return'] - report_normal_df['bench'])
analysis['sub_cost'] = risk_analysis(report_normal_df['return'] - report_normal_df['bench'] - report_normal_df['cost'])
analysis['excess_return_without_cost'] = risk_analysis(report_normal_df['return'] - report_normal_df['bench'])
analysis['excess_return_with_cost'] = risk_analysis(report_normal_df['return'] - report_normal_df['bench'] - report_normal_df['cost'])
analysis_df = pd.concat(analysis)
analysis_position.risk_analysis_graph(analysis_df, report_normal_df)
@@ -213,17 +213,17 @@ def risk_analysis_graph(
.. code-block:: python
risk
sub_bench mean 0.000662
std 0.004487
annual 0.166720
sharpe 2.340526
mdd -0.080516
sub_cost mean 0.000577
std 0.004482
annual 0.145392
sharpe 2.043494
mdd -0.083584
risk
excess_return_without_cost mean 0.000692
std 0.005374
annualized_return 0.174495
information_ratio 2.045576
max_drawdown -0.079103
excess_return_with_cost mean 0.000499
std 0.005372
annualized_return 0.125625
information_ratio 1.473152
max_drawdown -0.088263
:param report_normal_df: **df.index.name** must be **date**, df.columns must contain **return**, **turnover**, **cost**, **bench**

View File

@@ -61,26 +61,26 @@ class OptimizationConfig(object):
"pred_long",
"pred_long_short",
"pred_short",
"sub_bench",
"sub_cost",
"excess_return_without_cost",
"excess_return_with_cost",
"model",
]:
raise ValueError(
"report_type should be one of pred_long, pred_long_short, pred_short, sub_bench, sub_cost and model"
"report_type should be one of pred_long, pred_long_short, pred_short, excess_return_without_cost, excess_return_with_cost and model"
)
self.report_factor = config.get("report_factor", "sharpe")
self.report_factor = config.get("report_factor", "information_ratio")
if self.report_factor not in [
"annual",
"sharpe",
"mdd",
"annualized_return",
"information_ratio",
"max_drawdown",
"mean",
"std",
"model_score",
"model_pearsonr",
]:
raise ValueError(
"report_factor should be one of annual, sharpe, mdd, mean, std, model_pearsonr and model_score"
"report_factor should be one of annualized_return, information_ratio, max_drawdown, mean, std, model_pearsonr and model_score"
)
self.optim_type = config.get("optim_type", "max")