cnhkmcp 2.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- cnhkmcp/__init__.py +125 -0
- cnhkmcp/untracked/APP/.gitignore +32 -0
- cnhkmcp/untracked/APP/MODULAR_STRUCTURE.md +112 -0
- cnhkmcp/untracked/APP/README.md +309 -0
- cnhkmcp/untracked/APP/Tranformer/Transformer.py +2192 -0
- cnhkmcp/untracked/APP/Tranformer/ace.log +0 -0
- cnhkmcp/untracked/APP/Tranformer/ace_lib.py +1489 -0
- cnhkmcp/untracked/APP/Tranformer/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates.json +1786 -0
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_candidates_/321/207/320/264/342/225/221/321/204/342/225/233/320/233.json +654 -0
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_error.json +261 -0
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_success.json +170 -0
- cnhkmcp/untracked/APP/Tranformer/output/Alpha_generated_expressions_/321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/277/321/207/320/253/342/224/244/321/206/320/236/320/265/321/210/342/225/234/342/225/234/321/205/320/225/320/265Machine_lib.json +22 -0
- cnhkmcp/untracked/APP/Tranformer/parsetab.py +60 -0
- cnhkmcp/untracked/APP/Tranformer/template_summary.txt +408 -0
- cnhkmcp/untracked/APP/Tranformer/transformer_config.json +7 -0
- cnhkmcp/untracked/APP/Tranformer/validator.py +889 -0
- cnhkmcp/untracked/APP/ace.log +65 -0
- cnhkmcp/untracked/APP/ace_lib.py +1489 -0
- cnhkmcp/untracked/APP/blueprints/__init__.py +6 -0
- cnhkmcp/untracked/APP/blueprints/feature_engineering.py +347 -0
- cnhkmcp/untracked/APP/blueprints/idea_house.py +221 -0
- cnhkmcp/untracked/APP/blueprints/inspiration_house.py +432 -0
- cnhkmcp/untracked/APP/blueprints/paper_analysis.py +570 -0
- cnhkmcp/untracked/APP/custom_templates/templates.json +1257 -0
- cnhkmcp/untracked/APP/give_me_idea/BRAIN_Alpha_Template_Expert_SystemPrompt.md +400 -0
- cnhkmcp/untracked/APP/give_me_idea/ace_lib.py +1489 -0
- cnhkmcp/untracked/APP/give_me_idea/alpha_data_specific_template_master.py +247 -0
- cnhkmcp/untracked/APP/give_me_idea/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP/give_me_idea/what_is_Alpha_template.md +11 -0
- cnhkmcp/untracked/APP/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP/hkSimulator/ace.log +0 -0
- cnhkmcp/untracked/APP/hkSimulator/ace_lib.py +1476 -0
- cnhkmcp/untracked/APP/hkSimulator/autosim_20251205_145240.log +0 -0
- cnhkmcp/untracked/APP/hkSimulator/autosim_20251215_030103.log +0 -0
- cnhkmcp/untracked/APP/hkSimulator/autosimulator.py +447 -0
- cnhkmcp/untracked/APP/hkSimulator/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP/mirror_config.txt +20 -0
- cnhkmcp/untracked/APP/operaters.csv +129 -0
- cnhkmcp/untracked/APP/requirements.txt +53 -0
- cnhkmcp/untracked/APP/run_app.bat +28 -0
- cnhkmcp/untracked/APP/run_app.sh +34 -0
- cnhkmcp/untracked/APP/setup_tsinghua.bat +39 -0
- cnhkmcp/untracked/APP/setup_tsinghua.sh +43 -0
- cnhkmcp/untracked/APP/simulator/alpha_submitter.py +404 -0
- cnhkmcp/untracked/APP/simulator/simulator_wqb.py +618 -0
- cnhkmcp/untracked/APP/ssrn-3332513.pdf +109188 -19
- cnhkmcp/untracked/APP/static/brain.js +528 -0
- cnhkmcp/untracked/APP/static/decoder.js +1540 -0
- cnhkmcp/untracked/APP/static/feature_engineering.js +1729 -0
- cnhkmcp/untracked/APP/static/idea_house.js +937 -0
- cnhkmcp/untracked/APP/static/inspiration.js +465 -0
- cnhkmcp/untracked/APP/static/inspiration_house.js +868 -0
- cnhkmcp/untracked/APP/static/paper_analysis.js +390 -0
- cnhkmcp/untracked/APP/static/script.js +2942 -0
- cnhkmcp/untracked/APP/static/simulator.js +597 -0
- cnhkmcp/untracked/APP/static/styles.css +3127 -0
- cnhkmcp/untracked/APP/static/usage_widget.js +508 -0
- cnhkmcp/untracked/APP/templates/alpha_inspector.html +511 -0
- cnhkmcp/untracked/APP/templates/feature_engineering.html +960 -0
- cnhkmcp/untracked/APP/templates/idea_house.html +564 -0
- cnhkmcp/untracked/APP/templates/index.html +911 -0
- cnhkmcp/untracked/APP/templates/inspiration_house.html +861 -0
- cnhkmcp/untracked/APP/templates/paper_analysis.html +91 -0
- cnhkmcp/untracked/APP/templates/simulator.html +343 -0
- cnhkmcp/untracked/APP/templates/transformer_web.html +580 -0
- cnhkmcp/untracked/APP/usage.md +351 -0
- cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/ace_lib.py +1489 -0
- cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/brain_alpha_inspector.py +712 -0
- cnhkmcp/untracked/APP//321/207/342/225/235/320/250/321/205/320/230/320/226/321/204/342/225/225/320/220/321/211/320/221/320/243/321/206/320/261/320/265/helpful_functions.py +180 -0
- cnhkmcp/untracked/APP//321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/231/320/243/321/205/342/225/235/320/220/321/206/320/230/320/241.py +2393 -0
- cnhkmcp/untracked/arXiv_API_Tool_Manual.md +490 -0
- cnhkmcp/untracked/arxiv_api.py +229 -0
- cnhkmcp/untracked/forum_functions.py +998 -0
- cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/forum_functions.py +407 -0
- cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/platform_functions.py +2415 -0
- cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272/user_config.json +31 -0
- cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/210/320/276/320/271AI/321/210/320/277/342/225/227/321/210/342/224/220/320/251/321/204/342/225/225/320/272/321/206/320/246/320/227/321/206/320/261/320/263/321/206/320/255/320/265/321/205/320/275/320/266/321/204/342/225/235/320/252/321/204/342/225/225/320/233/321/210/342/225/234/342/225/234/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270.md +101 -0
- cnhkmcp/untracked/mcp/321/206/320/246/320/227/321/204/342/225/227/342/225/242/321/210/320/276/342/225/221/321/205/320/255/320/253/321/207/320/231/320/2302_/321/205/320/266/320/222/321/206/320/256/320/254/321/205/320/236/320/257/321/207/320/231/320/230/321/205/320/240/320/277/321/205/320/232/320/270/321/204/342/225/225/320/235/321/204/342/225/221/320/226/321/206/342/225/241/320/237/321/210/320/267/320/230/321/205/320/251/320/270/321/205/342/226/221/342/226/222/321/210/320/277/320/245/321/210/342/224/220/320/251/321/204/342/225/225/320/272//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +190 -0
- cnhkmcp/untracked/platform_functions.py +2886 -0
- cnhkmcp/untracked/sample_mcp_config.json +11 -0
- cnhkmcp/untracked/user_config.json +31 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/320/237/320/222/321/210/320/220/320/223/321/206/320/246/320/227/321/206/320/261/320/263_BRAIN_Alpha_Test_Requirements_and_Tips.md +202 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Alpha_explaination_workflow.md +56 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_6_Tips_Datafield_Exploration_Guide.md +194 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_BRAIN_Alpha_Improvement_Workflow.md +101 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_Dataset_Exploration_Expert_Manual.md +436 -0
- cnhkmcp/untracked//321/207/320/264/342/225/221/321/204/342/225/233/320/233/321/205/342/225/226/320/265/321/204/342/225/234/320/254/321/206/342/225/241/320/221_daily_report_workflow.md +128 -0
- cnhkmcp/untracked//321/211/320/225/320/235/321/207/342/225/234/320/276/321/205/320/231/320/235/321/210/342/224/220/320/240/321/210/320/261/320/234/321/206/320/230/320/241_/321/205/320/276/320/231/321/210/320/263/320/225/321/205/342/224/220/320/225/321/210/320/266/320/221/321/204/342/225/233/320/255/321/210/342/225/241/320/246/321/205/320/234/320/225.py +190 -0
- cnhkmcp-2.0.1.dist-info/METADATA +187 -0
- cnhkmcp-2.0.1.dist-info/RECORD +95 -0
- cnhkmcp-2.0.1.dist-info/WHEEL +5 -0
- cnhkmcp-2.0.1.dist-info/entry_points.txt +2 -0
- cnhkmcp-2.0.1.dist-info/licenses/LICENSE +21 -0
- cnhkmcp-2.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
import pandas as pd
|
|
6
|
+
from pandas.io.formats.style import Styler
|
|
7
|
+
|
|
8
|
+
brain_api_url = os.environ.get("BRAIN_API_URL", "https://api.worldquantbrain.com")
|
|
9
|
+
brain_url = os.environ.get("BRAIN_URL", "https://platform.worldquantbrain.com")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def make_clickable_alpha_id(alpha_id: str) -> str:
|
|
13
|
+
"""
|
|
14
|
+
Create a clickable HTML link for an alpha ID.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
alpha_id (str): The ID of the alpha.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
str: An HTML string containing a clickable link to the alpha's page on the platform.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
url = brain_url + "/alpha/"
|
|
24
|
+
return f'<a href="{url}{alpha_id}">{alpha_id}</a>'
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def prettify_result(
|
|
28
|
+
result: list, detailed_tests_view: bool = False, clickable_alpha_id: bool = False
|
|
29
|
+
) -> Union[pd.DataFrame, Styler]:
|
|
30
|
+
"""
|
|
31
|
+
Combine and format simulation results into a single DataFrame for analysis.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
result (list): A list of dictionaries containing simulation results.
|
|
35
|
+
detailed_tests_view (bool, optional): If True, include detailed test results. Defaults to False.
|
|
36
|
+
clickable_alpha_id (bool, optional): If True, make alpha IDs clickable. Defaults to False.
|
|
37
|
+
|
|
38
|
+
Returns:
|
|
39
|
+
pandas.DataFrame or pandas.io.formats.style.Styler: A DataFrame containing formatted results,
|
|
40
|
+
optionally with clickable alpha IDs.
|
|
41
|
+
"""
|
|
42
|
+
list_of_is_stats = [result[x]["is_stats"] for x in range(len(result)) if result[x]["is_stats"] is not None]
|
|
43
|
+
is_stats_df = pd.concat(list_of_is_stats).reset_index(drop=True)
|
|
44
|
+
is_stats_df = is_stats_df.sort_values("fitness", ascending=False)
|
|
45
|
+
|
|
46
|
+
expressions = {
|
|
47
|
+
result[x]["alpha_id"]: (
|
|
48
|
+
{
|
|
49
|
+
"selection": result[x]["simulate_data"]["selection"],
|
|
50
|
+
"combo": result[x]["simulate_data"]["combo"],
|
|
51
|
+
}
|
|
52
|
+
if result[x]["simulate_data"]["type"] == "SUPER"
|
|
53
|
+
else result[x]["simulate_data"]["regular"]
|
|
54
|
+
)
|
|
55
|
+
for x in range(len(result))
|
|
56
|
+
if result[x]["is_stats"] is not None
|
|
57
|
+
}
|
|
58
|
+
expression_df = pd.DataFrame(list(expressions.items()), columns=["alpha_id", "expression"])
|
|
59
|
+
|
|
60
|
+
list_of_is_tests = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
|
|
61
|
+
is_tests_df = pd.concat(list_of_is_tests, sort=True).reset_index(drop=True)
|
|
62
|
+
is_tests_df = is_tests_df[is_tests_df["result"] != "WARNING"]
|
|
63
|
+
if detailed_tests_view:
|
|
64
|
+
cols = ["limit", "result", "value"]
|
|
65
|
+
is_tests_df["details"] = is_tests_df[cols].to_dict(orient="records")
|
|
66
|
+
is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="details").reset_index()
|
|
67
|
+
else:
|
|
68
|
+
is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="result").reset_index()
|
|
69
|
+
|
|
70
|
+
alpha_stats = pd.merge(is_stats_df, expression_df, on="alpha_id")
|
|
71
|
+
alpha_stats = pd.merge(alpha_stats, is_tests_df, on="alpha_id")
|
|
72
|
+
alpha_stats = alpha_stats.drop(columns=alpha_stats.columns[(alpha_stats == "PENDING").any()])
|
|
73
|
+
alpha_stats.columns = alpha_stats.columns.str.replace("(?<=[a-z])(?=[A-Z])", "_", regex=True).str.lower()
|
|
74
|
+
if clickable_alpha_id:
|
|
75
|
+
return alpha_stats.style.format({"alpha_id": lambda x: make_clickable_alpha_id(str(x))})
|
|
76
|
+
return alpha_stats
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def concat_pnl(result: list) -> pd.DataFrame:
|
|
80
|
+
"""
|
|
81
|
+
Combine PnL results from multiple alphas into a single DataFrame.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
result (list): A list of dictionaries containing simulation results with PnL data.
|
|
85
|
+
|
|
86
|
+
Returns:
|
|
87
|
+
pandas.DataFrame: A DataFrame containing combined PnL data for all alphas.
|
|
88
|
+
"""
|
|
89
|
+
list_of_pnls = [result[x]["pnl"] for x in range(len(result)) if result[x]["pnl"] is not None]
|
|
90
|
+
pnls_df = pd.concat(list_of_pnls).reset_index()
|
|
91
|
+
|
|
92
|
+
return pnls_df
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def concat_is_tests(result: list) -> pd.DataFrame:
|
|
96
|
+
"""
|
|
97
|
+
Combine in-sample test results from multiple alphas into a single DataFrame.
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
result (list): A list of dictionaries containing simulation results with in-sample test data.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
pandas.DataFrame: A DataFrame containing combined in-sample test results for all alphas.
|
|
104
|
+
"""
|
|
105
|
+
is_tests_list = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
|
|
106
|
+
is_tests_df = pd.concat(is_tests_list, sort=True).reset_index(drop=True)
|
|
107
|
+
return is_tests_df
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def save_simulation_result(result: dict) -> None:
|
|
111
|
+
"""
|
|
112
|
+
Save the simulation result to a JSON file in the 'simulation_results' folder.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
result (dict): A dictionary containing the simulation result for an alpha.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
alpha_id = result["id"]
|
|
119
|
+
region = result["settings"]["region"]
|
|
120
|
+
folder_path = "simulation_results/"
|
|
121
|
+
file_path = os.path.join(folder_path, f"{alpha_id}_{region}")
|
|
122
|
+
|
|
123
|
+
os.makedirs(folder_path, exist_ok=True)
|
|
124
|
+
|
|
125
|
+
with open(file_path, "w") as file:
|
|
126
|
+
json.dump(result, file)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
def save_pnl(pnl_df: pd.DataFrame, alpha_id: str, region: str) -> None:
|
|
130
|
+
"""
|
|
131
|
+
Save the PnL data for an alpha to a CSV file in the 'alphas_pnl' folder.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
pnl_df (pandas.DataFrame): The DataFrame containing PnL data.
|
|
135
|
+
alpha_id (str): The ID of the alpha.
|
|
136
|
+
region (str): The region for which the PnL data was generated.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
folder_path = "alphas_pnl/"
|
|
140
|
+
file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
|
|
141
|
+
os.makedirs(folder_path, exist_ok=True)
|
|
142
|
+
|
|
143
|
+
pnl_df.to_csv(file_path)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
def save_yearly_stats(yearly_stats: pd.DataFrame, alpha_id: str, region: str):
|
|
147
|
+
"""
|
|
148
|
+
Save the yearly statistics for an alpha to a CSV file in the 'yearly_stats' folder.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
yearly_stats (pandas.DataFrame): The DataFrame containing yearly statistics.
|
|
152
|
+
alpha_id (str): The ID of the alpha.
|
|
153
|
+
region (str): The region for which the statistics were generated.
|
|
154
|
+
"""
|
|
155
|
+
|
|
156
|
+
folder_path = "yearly_stats/"
|
|
157
|
+
file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
|
|
158
|
+
os.makedirs(folder_path, exist_ok=True)
|
|
159
|
+
|
|
160
|
+
yearly_stats.to_csv(file_path, index=False)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def expand_dict_columns(data: pd.DataFrame) -> pd.DataFrame:
|
|
164
|
+
"""
|
|
165
|
+
Expand dictionary columns in a DataFrame into separate columns.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
data (pandas.DataFrame): The input DataFrame with dictionary columns.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
pandas.DataFrame: A new DataFrame with expanded columns.
|
|
172
|
+
"""
|
|
173
|
+
dict_columns = list(filter(lambda x: isinstance(data[x].iloc[0], dict), data.columns))
|
|
174
|
+
new_columns = pd.concat(
|
|
175
|
+
[data[col].apply(pd.Series).rename(columns=lambda x: f"{col}_{x}") for col in dict_columns],
|
|
176
|
+
axis=1,
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
data = pd.concat([data, new_columns], axis=1)
|
|
180
|
+
return data
|