| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | ##################################################### | 
					
						
							|  |  |  | # Copyright (c) Xuanyi Dong [GitHub D-X-Y], 2021.02 # | 
					
						
							|  |  |  | ##################################################### | 
					
						
							| 
									
										
										
										
											2021-03-14 13:44:51 +00:00
										 |  |  | # python exps/trading/organize_results.py           # | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | ##################################################### | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  | import os, re, sys, argparse | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | import numpy as np | 
					
						
							|  |  |  | from typing import List, Text | 
					
						
							|  |  |  | from collections import defaultdict, OrderedDict | 
					
						
							|  |  |  | from pathlib import Path | 
					
						
							|  |  |  | from pprint import pprint | 
					
						
							|  |  |  | import ruamel.yaml as yaml | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lib_dir = (Path(__file__).parent / ".." / ".." / "lib").resolve() | 
					
						
							|  |  |  | if str(lib_dir) not in sys.path: | 
					
						
							|  |  |  |     sys.path.insert(0, str(lib_dir)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-30 09:17:05 +00:00
										 |  |  | from config_utils import arg_str2bool | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | import qlib | 
					
						
							|  |  |  | from qlib.config import REG_CN | 
					
						
							|  |  |  | from qlib.workflow import R | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-11 21:45:20 +08:00
										 |  |  | from utils.qlib_utils import QResult | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-04-12 15:42:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-22 13:41:07 +08:00
										 |  |  | def compare_results( | 
					
						
							|  |  |  |     heads, values, names, space=10, separate="& ", verbose=True, sort_key=False | 
					
						
							|  |  |  | ): | 
					
						
							| 
									
										
										
										
											2021-03-06 06:38:34 -08:00
										 |  |  |     for idx, x in enumerate(heads): | 
					
						
							| 
									
										
										
										
											2021-03-17 13:05:29 +00:00
										 |  |  |         assert x == heads[0], "[{:}] \n{:}\nvs\n{:}".format(idx, x, heads[0]) | 
					
						
							| 
									
										
										
										
											2021-03-22 11:24:50 +08:00
										 |  |  |     new_head = QResult.full_str("Name", space) + separate + heads[0] | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     info_str_dict = dict(head=new_head, lines=[]) | 
					
						
							| 
									
										
										
										
											2021-03-06 06:38:34 -08:00
										 |  |  |     for name, value in zip(names, values): | 
					
						
							| 
									
										
										
										
											2021-03-22 11:24:50 +08:00
										 |  |  |         xline = QResult.full_str(name, space) + separate + value | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |         info_str_dict["lines"].append(xline) | 
					
						
							|  |  |  |     if verbose: | 
					
						
							| 
									
										
										
										
											2021-03-19 04:13:35 +00:00
										 |  |  |         print("\nThere are {:} algorithms.".format(len(values))) | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |         print(info_str_dict["head"]) | 
					
						
							|  |  |  |         if sort_key: | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |             lines = sorted( | 
					
						
							|  |  |  |                 list(zip(values, info_str_dict["lines"])), | 
					
						
							|  |  |  |                 key=lambda x: float(x[0].split(" ")[0]), | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |             lines = [x[1] for x in lines] | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             lines = info_str_dict["lines"] | 
					
						
							|  |  |  |         for xline in lines: | 
					
						
							| 
									
										
										
										
											2021-03-22 13:41:07 +08:00
										 |  |  |             print(xline + "\\\\") | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     return info_str_dict | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def filter_finished(recorders): | 
					
						
							|  |  |  |     returned_recorders = dict() | 
					
						
							|  |  |  |     not_finished = 0 | 
					
						
							|  |  |  |     for key, recorder in recorders.items(): | 
					
						
							|  |  |  |         if recorder.status == "FINISHED": | 
					
						
							|  |  |  |             returned_recorders[key] = recorder | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             not_finished += 1 | 
					
						
							|  |  |  |     return returned_recorders, not_finished | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  | def query_info(save_dir, verbose, name_filter, key_map): | 
					
						
							| 
									
										
										
										
											2021-03-11 03:09:55 +00:00
										 |  |  |     R.set_uri(save_dir) | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |     experiments = R.list_experiments() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     if verbose: | 
					
						
							|  |  |  |         print("There are {:} experiments.".format(len(experiments))) | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |     qresults = [] | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |     for idx, (key, experiment) in enumerate(experiments.items()): | 
					
						
							| 
									
										
										
										
											2021-03-06 06:38:34 -08:00
										 |  |  |         if experiment.id == "0": | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-04-12 15:42:43 +08:00
										 |  |  |         if ( | 
					
						
							|  |  |  |             name_filter is not None | 
					
						
							|  |  |  |             and re.fullmatch(name_filter, experiment.name) is None | 
					
						
							|  |  |  |         ): | 
					
						
							| 
									
										
										
										
											2021-03-28 22:26:06 -07:00
										 |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |         recorders = experiment.list_recorders() | 
					
						
							|  |  |  |         recorders, not_finished = filter_finished(recorders) | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |         if verbose: | 
					
						
							|  |  |  |             print( | 
					
						
							|  |  |  |                 "====>>>> {:02d}/{:02d}-th experiment {:9s} has {:02d}/{:02d} finished recorders.".format( | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |                     idx + 1, | 
					
						
							|  |  |  |                     len(experiments), | 
					
						
							|  |  |  |                     experiment.name, | 
					
						
							|  |  |  |                     len(recorders), | 
					
						
							|  |  |  |                     len(recorders) + not_finished, | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |         result = QResult(experiment.name) | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |         for recorder_id, recorder in recorders.items(): | 
					
						
							| 
									
										
										
										
											2021-03-06 06:38:34 -08:00
										 |  |  |             result.update(recorder.list_metrics(), key_map) | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |             result.append_path( | 
					
						
							|  |  |  |                 os.path.join(recorder.uri, recorder.experiment_id, recorder.id) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-17 13:05:29 +00:00
										 |  |  |         if not len(result): | 
					
						
							|  |  |  |             print("There are no valid recorders for {:}".format(experiment)) | 
					
						
							|  |  |  |             continue | 
					
						
							| 
									
										
										
										
											2021-03-22 11:24:50 +08:00
										 |  |  |         else: | 
					
						
							| 
									
										
										
										
											2021-03-22 13:41:07 +08:00
										 |  |  |             print( | 
					
						
							|  |  |  |                 "There are {:} valid recorders for {:}".format( | 
					
						
							|  |  |  |                     len(recorders), experiment.name | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |         qresults.append(result) | 
					
						
							|  |  |  |     return qresults | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     parser = argparse.ArgumentParser("Show Results") | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |         "--save_dir", | 
					
						
							|  |  |  |         type=str, | 
					
						
							|  |  |  |         nargs="+", | 
					
						
							| 
									
										
										
										
											2021-03-19 04:13:35 +00:00
										 |  |  |         default=[], | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |         help="The checkpoint directory.", | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--verbose", | 
					
						
							| 
									
										
										
										
											2021-03-30 09:17:05 +00:00
										 |  |  |         type=arg_str2bool, | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |         default=False, | 
					
						
							|  |  |  |         help="Print detailed log information or not.", | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-03-28 22:26:06 -07:00
										 |  |  |     parser.add_argument( | 
					
						
							|  |  |  |         "--name_filter", type=str, default=".*", help="Filter experiment names." | 
					
						
							|  |  |  |     ) | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |     args = parser.parse_args() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     print("Show results of {:}".format(args.save_dir)) | 
					
						
							| 
									
										
										
										
											2021-03-19 04:13:35 +00:00
										 |  |  |     if not args.save_dir: | 
					
						
							|  |  |  |         raise ValueError("Receive no input directory for [args.save_dir]") | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-06 06:13:22 -08:00
										 |  |  |     provider_uri = "~/.qlib/qlib_data/cn_data" | 
					
						
							|  |  |  |     qlib.init(provider_uri=provider_uri, region=REG_CN) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |     """
 | 
					
						
							|  |  |  |     key_map = { | 
					
						
							|  |  |  |         # "RMSE": "RMSE", | 
					
						
							|  |  |  |         "IC": "IC", | 
					
						
							|  |  |  |         "ICIR": "ICIR", | 
					
						
							|  |  |  |         "Rank IC": "Rank_IC", | 
					
						
							|  |  |  |         "Rank ICIR": "Rank_ICIR", | 
					
						
							|  |  |  |         # "excess_return_with_cost.annualized_return": "Annualized_Return", | 
					
						
							|  |  |  |         # "excess_return_with_cost.information_ratio": "Information_Ratio", | 
					
						
							|  |  |  |         # "excess_return_with_cost.max_drawdown": "Max_Drawdown", | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     key_map = dict() | 
					
						
							|  |  |  |     for xset in ("train", "valid", "test"): | 
					
						
							|  |  |  |         key_map["{:}-mean-IC".format(xset)] = "IC ({:})".format(xset) | 
					
						
							|  |  |  |         key_map["{:}-mean-ICIR".format(xset)] = "ICIR ({:})".format(xset) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     all_qresults = [] | 
					
						
							| 
									
										
										
										
											2021-03-08 03:22:20 +00:00
										 |  |  |     for save_dir in args.save_dir: | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |         qresults = query_info(save_dir, args.verbose, args.name_filter, key_map) | 
					
						
							|  |  |  |         all_qresults.extend(qresults) | 
					
						
							|  |  |  |     names, head_strs, value_strs = [], [], [] | 
					
						
							|  |  |  |     for result in all_qresults: | 
					
						
							|  |  |  |         head_str, value_str = result.info(list(key_map.values()), verbose=args.verbose) | 
					
						
							|  |  |  |         head_strs.append(head_str) | 
					
						
							|  |  |  |         value_strs.append(value_str) | 
					
						
							|  |  |  |         names.append(result.name) | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |     compare_results( | 
					
						
							| 
									
										
										
										
											2021-03-31 10:33:37 +00:00
										 |  |  |         head_strs, | 
					
						
							|  |  |  |         value_strs, | 
					
						
							|  |  |  |         names, | 
					
						
							| 
									
										
										
										
											2021-03-30 09:17:05 +00:00
										 |  |  |         space=18, | 
					
						
							| 
									
										
										
										
											2021-03-18 16:02:55 +08:00
										 |  |  |         verbose=True, | 
					
						
							|  |  |  |         sort_key=True, | 
					
						
							|  |  |  |     ) |