Commit 6c75e21f authored by pengxiong@wealthgrow.cn's avatar pengxiong@wealthgrow.cn

Merge remote-tracking branch 'origin/dev' into dev

parents 28776226 70bd37f1
# -*- coding: UTF-8 -*-
# """
# @author: Zongxi.Li
# @file:portfolio_copy.py
# @time:2020/12/03
# """
from app.utils.fund_rank import *
from app.utils.risk_parity import *
from app.pypfopt import risk_models
......@@ -233,7 +227,7 @@ def get_radar_data(fund):
sharpe_score = df['sharp_ratio_rank'].values[0] * 100
total_score = df['z_score'].values[0]
fund_name = get_fund_name(fund).values[0][0]
# print(fund_name)
return {'name': fund_name, 'data': [{'name': '绝对收益', 'data': '%.2f' % return_score},
{'name': '抗风险能力', 'data': '%.2f' % downside_score},
{'name': '极端风险', 'data': '%.2f' % drawdown_score},
......@@ -285,7 +279,8 @@ class PortfolioDiagnose(object):
self.end_date = end_date
if self.end_date is None:
self.end_date = datetime.datetime.now() - datetime.timedelta(days=1)
self.end_date = datetime.datetime(datetime.date.today().year,
datetime.date.today().month, 1) - datetime.timedelta(1)
self.start_date = cal_date(self.end_date, 'Y', 1)
self.replace_pair = dict() # 由于数据不足半年而被替换为相同基金经理和策略的原基金和替换基金的映射
......@@ -534,9 +529,7 @@ class PortfolioDiagnose(object):
index_return = index_data.iloc[:, :] / index_data.iloc[0, :] - 1
# origin_fund_return = origin_portfolio.iloc[:, :] / origin_portfolio.iloc[0, :] - 1
propose_fund_return = propose_portfolio.iloc[:, :] / propose_portfolio.iloc[0, :] - 1
print(self.new_weights)
propose_fund_return['return'] = propose_fund_return.T.iloc[:, :].apply(lambda x: np.dot(self.new_weights, x))
propose_fund_return.to_csv('new_port.csv', encoding='gbk')
return index_return, propose_fund_return
def old_evaluation(self, group_name, group_result, data_adaptor):
......@@ -570,14 +563,13 @@ class PortfolioDiagnose(object):
num = len(fund_rank_re)
fund_id_rank_list = list(fund_rank_re["fund_id"])
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][
"fund_name"].values[0]
name = data_adaptor.user_customer_order_df[data_adaptor.user_customer_order_df["fund_id"] == f_id]["fund_name"].values[0]
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"])
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:
profit_positive_evaluate = str(profit_positive_num) + "只基金取的正收益,"
else:
......@@ -593,22 +585,21 @@ class PortfolioDiagnose(object):
else:
no_data_fund_evaluate = ";"
group_order_df = data_adaptor.user_customer_order_df[
data_adaptor.user_customer_order_df["folio_name"] == group_name]
group_order_df = data_adaptor.user_customer_order_df[data_adaptor.user_customer_order_df["folio_name"] == group_name]
strategy_list = group_order_df["substrategy"]
uniqe_strategy = list(strategy_list.unique())
uniqe_strategy_name = [dict_substrategy[int(x)] + "、" for x in uniqe_strategy]
# 覆盖的基金名称
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 = "策略上有一定分散"
else:
strategy_distribution_evaluate = "策略分散程度不高"
# 相关性
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
f_id in self.abandon_fund_corr]
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]
fund_corr_evaluate = "".join(fund_corr_name)[:-1] + "相关性较高,建议调整组合配比;"
else:
fund_corr_evaluate = ";"
......@@ -649,9 +640,13 @@ class PortfolioDiagnose(object):
group_result_data = group_result[group_name]
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_ratio_year = group_result_data["return_ratio_year"]
old_volatility = group_result_data["volatility"]
......@@ -669,13 +664,77 @@ class PortfolioDiagnose(object):
data = cur.fetchall()
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_id_list_name = [] # 基金名称,策略分级
# hold_fund = set(self.portfolio) - set(self.abandon_fund)
# abandon_fund = self.abandon_fund
# proposal_fund = self.proposal_fund
# data = [hold_fund, abandon_fund, proposal_fund]
# return data
# 基金名称,策略分级
propose_fund_id_name_list = [propose_fund_df[propose_fund_df["fund_id"] == fund_id]["fund_name"].values[0] for
fund_id in propose_fund_id_list]
propose_fund_id_strategy_name_list = [dict_substrategy[int(propose_fund_df[propose_fund_df["fund_id"] == fund_id]["substrategy"].values[0])] for
fund_id in propose_fund_id_list]
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):
"""
......@@ -779,12 +838,16 @@ class PortfolioDiagnose(object):
ret = []
i = 1
for k, v in evaluation.items():
print(k, v)
single_sentence = str(i) + "." + sentence[k] % translate_single(content, k, v)
single_sentence = str(i) + "、" + sentence[k] % translate_single(content, k, v)
ret.append(single_sentence)
i += 1
fund_name = get_fund_name(fund_id).values[0][0]
return {'name': fund_name, 'data': ret}
evaluation_dict = {'name': fund_name, 'data': ret}
if fund_id in self.abandon_fund_score + self.abandon_fund_corr:
evaluation_dict['status'] = "换仓"
elif fund_id in self.portfolio:
evaluation_dict['status'] = "保留"
return evaluation_dict
def old_portfolio_evaluation(self, ):
result = []
......
......@@ -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")
folio_report_data["index_result"] = index_result
folio_report_data["return_df"] = resample_df
self.group_result_data[folio] = folio_report_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