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:
@@ -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())
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
# coding=utf-8
|
||||
|
||||
import argparse
|
||||
import importlib
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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**
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user