Commit 70bd37f1 authored by 赵杰's avatar 赵杰

新组合结果

parent b04cf3b2
# -*- coding: UTF-8 -*-
# """
# @author: Zongxi.Li
# @file:portfolio_copy.py
# @time:2020/12/03
# """
from app.utils.fund_rank import * from app.utils.fund_rank import *
from app.utils.risk_parity import * from app.utils.risk_parity import *
from app.pypfopt import risk_models from app.pypfopt import risk_models
...@@ -547,17 +541,17 @@ class PortfolioDiagnose(object): ...@@ -547,17 +541,17 @@ class PortfolioDiagnose(object):
past_month = (current_year - start_year) * 12 + current_month - start_month past_month = (current_year - start_year) * 12 + current_month - start_month
# 投入成本(万元) # 投入成本(万元)
input_cost = round(group_result[group_name]["total_cost"] / 10000, 2) input_cost = round(group_result[group_name]["total_cost"]/10000, 2)
# 整体盈利(万元) # 整体盈利(万元)
total_profit = round(group_result[group_name]["cumulative_profit"] / 10000, 2) total_profit = round(group_result[group_name]["cumulative_profit"]/10000, 2)
# 整体表现 回撤能力 # 整体表现 回撤能力
fund_rank_data = fund_rank[fund_rank["fund_id"].isin(self.portfolio)] fund_rank_data = fund_rank[fund_rank["fund_id"].isin(self.portfolio)]
z_score = fund_rank_data["z_score"].mean() z_score = fund_rank_data["z_score"].mean()
drawdown_rank = fund_rank_data["max_drawdown_rank"].mean() drawdown_rank = fund_rank_data["max_drawdown_rank"].mean()
return_rank_df = fund_rank_data["annual_return_rank"] return_rank_df = fund_rank_data["annual_return_rank"]
z_score_level = np.select([z_score >= 80, z_score_level = np.select([z_score >= 80,
70 <= z_score < 80, 70 <= z_score < 80,
z_score < 70], [0, 1, 2]).item() z_score < 70], [0, 1, 2]).item()
drawdown_level = np.select([drawdown_rank >= 0.8, drawdown_level = np.select([drawdown_rank >= 0.8,
0.7 <= drawdown_rank < 0.8, 0.7 <= drawdown_rank < 0.8,
0.6 <= drawdown_rank < 0.7, 0.6 <= drawdown_rank < 0.7,
...@@ -569,14 +563,13 @@ class PortfolioDiagnose(object): ...@@ -569,14 +563,13 @@ class PortfolioDiagnose(object):
num = len(fund_rank_re) num = len(fund_rank_re)
fund_id_rank_list = list(fund_rank_re["fund_id"]) fund_id_rank_list = list(fund_rank_re["fund_id"])
for f_id in fund_id_rank_list: for f_id in fund_id_rank_list:
name = data_adaptor.user_customer_order_df[data_adaptor.user_customer_order_df["fund_id"] == f_id][ name = data_adaptor.user_customer_order_df[data_adaptor.user_customer_order_df["fund_id"] == f_id]["fund_name"].values[0]
"fund_name"].values[0]
return_rank_evaluate = return_rank_evaluate + name + "、" return_rank_evaluate = return_rank_evaluate + name + "、"
return_rank_evaluate = return_rank_evaluate[:-1] + "等" + str(num) + "只产品稳健,对组合的收益率贡献明显," return_rank_evaluate = return_rank_evaluate[:-1] +"等" + str(num) + "只产品稳健,对组合的收益率贡献明显,"
# 正收益基金数量 # 正收益基金数量
group_hold_data = pd.DataFrame(group_result[group_name]["group_hoding_info"]) group_hold_data = pd.DataFrame(group_result[group_name]["group_hoding_info"])
profit_positive_num = group_hold_data[group_hold_data["profit"] > 0]["profit"].count() profit_positive_num = group_hold_data[group_hold_data["profit"]>0]["profit"].count()
if profit_positive_num > 0: if profit_positive_num > 0:
profit_positive_evaluate = str(profit_positive_num) + "只基金取的正收益," profit_positive_evaluate = str(profit_positive_num) + "只基金取的正收益,"
else: else:
...@@ -592,29 +585,28 @@ class PortfolioDiagnose(object): ...@@ -592,29 +585,28 @@ class PortfolioDiagnose(object):
else: else:
no_data_fund_evaluate = ";" no_data_fund_evaluate = ";"
group_order_df = data_adaptor.user_customer_order_df[ group_order_df = data_adaptor.user_customer_order_df[data_adaptor.user_customer_order_df["folio_name"] == group_name]
data_adaptor.user_customer_order_df["folio_name"] == group_name]
strategy_list = group_order_df["substrategy"] strategy_list = group_order_df["substrategy"]
uniqe_strategy = list(strategy_list.unique()) uniqe_strategy = list(strategy_list.unique())
uniqe_strategy_name = [dict_substrategy[int(x)] + "、" for x in uniqe_strategy] uniqe_strategy_name = [dict_substrategy[int(x)] + "、" for x in uniqe_strategy]
# 覆盖的基金名称 # 覆盖的基金名称
strategy_name_evaluate = "".join(uniqe_strategy_name)[:-1] strategy_name_evaluate = "".join(uniqe_strategy_name)[:-1]
if len(uniqe_strategy) / float(len(strategy_list)) > 0.6:
if len(uniqe_strategy)/float(len(strategy_list)) > 0.6:
strategy_distribution_evaluate = "策略上有一定分散" strategy_distribution_evaluate = "策略上有一定分散"
else: else:
strategy_distribution_evaluate = "策略分散程度不高" strategy_distribution_evaluate = "策略分散程度不高"
# 相关性 # 相关性
if len(self.abandon_fund_corr) > 0: if len(self.abandon_fund_corr) > 0:
fund_corr_name = [str(group_order_df[group_order_df["fund_id"] == f_id]["fund_name"].values[0]) + "和" for fund_corr_name = [str(group_order_df[group_order_df["fund_id"] == f_id]["fund_name"].values[0]) + "和" for f_id in self.abandon_fund_corr]
f_id in self.abandon_fund_corr]
fund_corr_evaluate = "".join(fund_corr_name)[:-1] + "相关性较高,建议调整组合配比;" fund_corr_evaluate = "".join(fund_corr_name)[:-1] + "相关性较高,建议调整组合配比;"
else: else:
fund_corr_evaluate = ";" fund_corr_evaluate = ";"
num_fund = len(self.portfolio) num_fund = len(self.portfolio)
evaluate_enum = [["优秀", "良好", "一般"], evaluate_enum = [["优秀", "良好", "一般"],
["优秀", "良好", "合格", "较差"]] ["优秀", "良好", "合格", "较差"]]
z_score_evaluate = evaluate_enum[0][z_score_level] z_score_evaluate = evaluate_enum[0][z_score_level]
drawdown_evaluate = evaluate_enum[1][drawdown_level] drawdown_evaluate = evaluate_enum[1][drawdown_level]
...@@ -648,9 +640,13 @@ class PortfolioDiagnose(object): ...@@ -648,9 +640,13 @@ class PortfolioDiagnose(object):
group_result_data = group_result[group_name] group_result_data = group_result[group_name]
hold_info = group_result_data["group_hoding_info"] hold_info = group_result_data["group_hoding_info"]
hold_info_df = pd.DataFrame(hold_info)
group_order_df = data_adaptor.user_customer_order_df[
data_adaptor.user_customer_order_df["folio_name"] == group_name]
group_order_start_date = pd.to_datetime(group_order_df["confirm_share_date"].min())
# 原组合总市值, 区间收益, 年化收益, 波动率, 最大回撤, 夏普比率 # 原组合总市值, 区间收益, 年化收益, 波动率, 最大回撤, 夏普比率
total_asset = round(pd.DataFrame(hold_info)["market_values"].sum(), 2) total_asset = round(hold_info_df["market_values"].sum(), 2)
old_return = group_result_data["cumulative_return"] old_return = group_result_data["cumulative_return"]
old_return_ratio_year = group_result_data["return_ratio_year"] old_return_ratio_year = group_result_data["return_ratio_year"]
old_volatility = group_result_data["volatility"] old_volatility = group_result_data["volatility"]
...@@ -668,15 +664,77 @@ class PortfolioDiagnose(object): ...@@ -668,15 +664,77 @@ class PortfolioDiagnose(object):
data = cur.fetchall() data = cur.fetchall()
product_df = pd.DataFrame(list(data), columns=['fund_id', 'fund_name', 'freq', 'substrategy']) product_df = pd.DataFrame(list(data), columns=['fund_id', 'fund_name', 'freq', 'substrategy'])
propose_fund_df = product_df[product_df["fund_id"].isin(propose_fund_id_list)] propose_fund_df = product_df[product_df["fund_id"].isin(propose_fund_id_list)]
propose_fund_id_list_name = [] # 基金名称,策略分级
sentence = "在保留{}的基础上,建议赎回{},并增配{}后,整体组合波动率大幅降低,最大回撤从{}降到不足{},年化收益率提升{}个点" # 基金名称,策略分级
hold_fund = "".join(set(self.portfolio) - set(self.abandon_fund_score + self.abandon_fund_corr)) propose_fund_id_name_list = [propose_fund_df[propose_fund_df["fund_id"] == fund_id]["fund_name"].values[0] for
abandon_fund = "".join(self.abandon_fund_score + self.abandon_fund_corr) fund_id in propose_fund_id_list]
proposal_fund = "".join(self.proposal_fund) propose_fund_id_strategy_name_list = [dict_substrategy[int(propose_fund_df[propose_fund_df["fund_id"] == fund_id]["substrategy"].values[0])] for
data = [hold_fund, abandon_fund, proposal_fund, old_max_drawdown] fund_id in propose_fund_id_list]
return sentence % data propose_fund_asset = [round(self.new_weights[i] * total_asset, 2) for i in range(len(propose_fund_id_name_list))]
propose_info = {propose_fund_id_strategy_name_list[i]:
{"fund_name": propose_fund_id_name_list[i],
"substrategy": propose_fund_id_strategy_name_list[i],
"asset": propose_fund_asset[i]}
for i in range(len(propose_fund_id_list))}
# 调仓建议
suggestions_result = {}
old_hold_fund_name_list = list(hold_info_df["fund_name"])
for hold in hold_info:
suggestions = {}
if hold["fund_strategy_name"] not in suggestions_result.keys():
suggestions_result[hold["fund_strategy_name"]] = {}
suggestions["fund_strategy_name"] = hold["fund_strategy_name"]
suggestions["fund_name"] = hold["fund_name"]
suggestions["before_optimization"] = hold["market_values"]
suggestions["after_optimization"] = 0
if suggestions["fund_strategy_name"] in propose_fund_id_strategy_name_list:
suggestions["after_optimization"] = 0
suggestions_result[hold["fund_strategy_name"]][suggestions["fund_name"]] = suggestions
for key, value in propose_info.items():
if value["fund_name"] not in old_hold_fund_name_list:
suggestions = {}
if key not in suggestions_result.keys():
suggestions_result[key] = {}
suggestions["fund_strategy_name"] = value["substrategy"]
suggestions["fund_name"] = value["fund_name"]
suggestions["before_optimization"] = 0
suggestions["after_optimization"] = value["asset"]
suggestions_result[key][suggestions["fund_name"]] = suggestions
suggestions_result_asset = {"before": total_asset, "after": total_asset}
# 旧组合累积收益
old_return_df = group_result_data["return_df"]
old_return_df["cum_return_ratio"] = old_return_df["cum_return_ratio"] - 1
# 新组合累积收益
propose_fund_return_limit_data = propose_fund_return[propose_fund_return.index >= group_order_start_date]
start_return = propose_fund_return_limit_data['return'].values[0]
propose_fund_return_limit_data["new_return"] = (propose_fund_return_limit_data["return"] - start_return)/(1+start_return)
# 指数收益
index_return = index_return[index_return.index >= group_order_start_date]
start_index_return = index_return[self.index_id].values[0]
index_return["new_index_return"] = (index_return[self.index_id] - start_index_return) / (1 + start_index_return)
# 新组合区间年化收益率
freq_max = group_order_df["freq"].max()
n_freq = freq_days(int(freq_max))
new_return_ratio_year = annual_return(propose_fund_return_limit_data["new_return"].values[-1], propose_fund_return_limit_data, n_freq)
# 新组合波动率
new_volatility_ = volatility(propose_fund_return_limit_data["new_return"]+1, n_freq)
# 新组合最大回撤
new_drawdown = max_drawdown(propose_fund_return_limit_data["new_return"]+1)
# 新组合夏普比率
sim = simple_return(propose_fund_return_limit_data["new_return"]+1)
exc = excess_return(sim, BANK_RATE, n_freq)
new_sharpe = sharpe_ratio(exc, sim, n_freq)
return suggestions_result, suggestions_result_asset
def single_evaluation(self, fund_id): def single_evaluation(self, fund_id):
""" """
......
...@@ -159,7 +159,7 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor): ...@@ -159,7 +159,7 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor):
index_result = self.signal_fund_profit_result(index_df[index_df.index >= pd.to_datetime(first_trade_date)], index_result = self.signal_fund_profit_result(index_df[index_df.index >= pd.to_datetime(first_trade_date)],
"index") "index")
folio_report_data["index_result"] = index_result folio_report_data["index_result"] = index_result
folio_report_data["return_df"] = resample_df
self.group_result_data[folio] = folio_report_data self.group_result_data[folio] = folio_report_data
return self.group_result_data return self.group_result_data
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment