Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Highfreq Backtest with the Model/Rule/RL Strategy #408

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
update port_ana_record
  • Loading branch information
bxdd committed Apr 28, 2021
commit 49cdaf8f5da528daeb2b0a967073c275388e95ad
1 change: 1 addition & 0 deletions qlib/contrib/backtest/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ def update_report(self, trade_start_time, trade_end_time, trade_exchange):

# finish today's updation
# reset the daily variables
self.rtn = 0
self.ct = 0
self.to = 0

Expand Down
2 changes: 1 addition & 1 deletion qlib/contrib/backtest/backtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

def backtest(start_time, end_time, trade_strategy, trade_env, benchmark, account):

trade_account = Account(init_cash=account)
trade_account = Account(init_cash=account, benchmark=benchmark, start_time=start_time, end_time=end_time)
trade_env.reset(start_time=start_time, end_time=end_time, trade_account=trade_account)
trade_strategy.reset(start_time=start_time, end_time=end_time)

Expand Down
55 changes: 32 additions & 23 deletions qlib/workflow/record_temp.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# Licensed under the MIT License.

import re
import warnings
import pandas as pd
from pathlib import Path
from pprint import pprint
Expand Down Expand Up @@ -223,18 +224,23 @@ class PortAnaRecord(SignalRecord):

artifact_path = "portfolio_analysis"

def __init__(self, recorder, config, **kwargs):
def __init__(self, recorder, config, risk_analysis_dep, **kwargs):
"""
config["strategy"] : dict
define the strategy class as well as the kwargs.
config["env"] : dict
define the env class as well as the kwargs.
config["backtest"] : dict
define the backtest kwargs.
risk_analysis_dep : int
risk analyze the dep'th env report
"""
super().__init__(recorder=recorder, **kwargs)

self.strategy_config = config["strategy"]
self.env_config = config["env"]
self.backtest_config = config["backtest"]
self.risk_analysis_dep = risk_analysis_dep

def generate(self, **kwargs):
# check previously stored prediction results
Expand All @@ -245,31 +251,34 @@ def generate(self, **kwargs):

# custom strategy and get backtest
report_list = normal_backtest(env=self.env_config, strategy=self.strategy_config, **self.backtest_config)
for report_id, (report_normal, positions_normal) in enumerate(report_list):
for report_dep, (report_normal, positions_normal) in enumerate(report_list):
if report_dict is None:
if self.risk_analysis_dep == report_dep:
warnings.warn(f"the report in dep {risk_analysis_dep} is None, please set the corresponding env with `generate_report==True`")
continue
self.recorder.save_objects(**{f"report_normal_{report_id}.pkl": report_normal}, artifact_path=PortAnaRecord.get_path())
self.recorder.save_objects(**{f"positions_norma_{report_id}l.pkl": positions_normal}, artifact_path=PortAnaRecord.get_path())

self.recorder.save_objects(**{f"report_normal_{report_dep}.pkl": report_normal}, artifact_path=PortAnaRecord.get_path())
self.recorder.save_objects(**{f"positions_norma_{report_dep}l.pkl": positions_normal}, artifact_path=PortAnaRecord.get_path())
# analysis
analysis = dict()
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
# log metrics
self.recorder.log_metrics(**flatten_dict(analysis_df["risk"].unstack().T.to_dict()))
# save results
self.recorder.save_objects(**{f"port_analysis.pkl_{report_id}": analysis_df}, artifact_path=PortAnaRecord.get_path())
logger.info(
f"Portfolio analysis record 'port_analysis_{report_id}.pkl' has been saved as the artifact of the Experiment {self.recorder.experiment_id}"
)
# print out results
pprint("The following are analysis results of the excess return without cost.")
pprint(analysis["excess_return_without_cost"])
pprint("The following are analysis results of the excess return with cost.")
pprint(analysis["excess_return_with_cost"])
self.risk_analysis_dep == report_dep:
analysis = dict()
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
# log metrics
self.recorder.log_metrics(**flatten_dict(analysis_df["risk"].unstack().T.to_dict()))
# save results
self.recorder.save_objects(**{f"port_analysis.pkl_{report_dep}": analysis_df}, artifact_path=PortAnaRecord.get_path())
logger.info(
f"Portfolio analysis record 'port_analysis_{report_dep}.pkl' has been saved as the artifact of the Experiment {self.recorder.experiment_id}"
)
# print out results
pprint("The following are analysis results of the excess return without cost.")
pprint(analysis["excess_return_without_cost"])
pprint("The following are analysis results of the excess return with cost.")
pprint(analysis["excess_return_with_cost"])

def list(self):
return [
Expand Down