Commit d488e753 authored by 李宗熹's avatar 李宗熹

新组合评价

parent f1613008
......@@ -292,6 +292,9 @@ class PortfolioDiagnose(object):
self.new_correlation = None
self.old_weights = None
self.new_weights = None
self.origin_portfolio = None
self.abandoned_portfolio = None
self.propose_portfolio = None
def get_portfolio(self, ):
"""获取组合净值表
......@@ -341,7 +344,7 @@ class PortfolioDiagnose(object):
if replaced_fund is not None:
prod1 = get_nav(replaced_fund, self.start_date, invest_type=self.invest_type)
self.replace_pair[portfolio[0]] = replaced_fund
self.replace_pair[portfolio[idx + 1]] = replaced_fund
self.freq_list.append(get_frequency(prod1))
prod1 = rename_col(prod1, replaced_fund)
else:
......@@ -457,20 +460,20 @@ class PortfolioDiagnose(object):
def optimize(self, ):
import time
start = time.time()
origin_portfolio = self.get_portfolio()
self.origin_portfolio = self.get_portfolio()
end1 = time.time()
print("原始组合数据获取时间:", end1 - start)
abandoned_portfolio = self.abandon(origin_portfolio)
self.abandoned_portfolio = self.abandon(self.origin_portfolio)
end2 = time.time()
print("计算换仓基金时间:", end2 - end1)
propose_portfolio = self.proposal(abandoned_portfolio)
self.propose_portfolio = self.proposal(self.abandoned_portfolio)
end3 = time.time()
print("遍历产品池获取候选推荐时间:", end3 - end2)
# propose_portfolio.to_csv('test_portfolio.csv', encoding='gbk')
mu = expected_returns.mean_historical_return(propose_portfolio, frequency=min(self.freq_list))
S = risk_models.sample_cov(propose_portfolio, frequency=min(self.freq_list))
dd = expected_returns.drawdown_from_prices(propose_portfolio)
mu = expected_returns.mean_historical_return(self.propose_portfolio, frequency=min(self.freq_list))
S = risk_models.sample_cov(self.propose_portfolio, frequency=min(self.freq_list))
dd = expected_returns.drawdown_from_prices(self.propose_portfolio)
# if self.client_type == 1:
# proposal_risk = [[x, get_risk_level(search_rank(fund_rank, x, metric='substrategy'))] for x in
......@@ -483,7 +486,7 @@ class PortfolioDiagnose(object):
# propose_portfolio.drop()
propose_risk_mapper = dict()
for fund in propose_portfolio.columns:
for fund in self.propose_portfolio.columns:
propose_risk_mapper[fund] = str(get_risk_level(search_rank(fund_rank, fund, metric='substrategy')))
# risk_upper = {"H": 0.0}
......@@ -522,13 +525,10 @@ class PortfolioDiagnose(object):
def return_compare(self):
index_data = get_index_daily(self.index_id)
origin_portfolio = self.get_portfolio()
abandoned_portfolio = self.abandon(origin_portfolio)
propose_portfolio = self.proposal(abandoned_portfolio)
index_data = pd.merge(index_data, propose_portfolio, how='inner', left_index=True, right_index=True)
index_data = pd.merge(index_data, self.propose_portfolio, how='inner', left_index=True, right_index=True)
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
propose_fund_return = self.propose_portfolio.iloc[:, :] / self.propose_portfolio.iloc[0, :] - 1
propose_fund_return['return'] = propose_fund_return.T.iloc[:, :].apply(lambda x: np.dot(self.new_weights, x))
return index_return, propose_fund_return
......@@ -541,17 +541,17 @@ class PortfolioDiagnose(object):
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)]
z_score = fund_rank_data["z_score"].mean()
drawdown_rank = fund_rank_data["max_drawdown_rank"].mean()
return_rank_df = fund_rank_data["annual_return_rank"]
z_score_level = np.select([z_score >= 80,
70 <= z_score < 80,
z_score < 70], [0, 1, 2]).item()
70 <= z_score < 80,
z_score < 70], [0, 1, 2]).item()
drawdown_level = np.select([drawdown_rank >= 0.8,
0.7 <= drawdown_rank < 0.8,
0.6 <= drawdown_rank < 0.7,
......@@ -563,9 +563,10 @@ 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"])
......@@ -585,28 +586,29 @@ 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 = ";"
num_fund = len(self.portfolio)
evaluate_enum = [["优秀", "良好", "一般"],
["优秀", "良好", "合格", "较差"]]
["优秀", "良好", "合格", "较差"]]
z_score_evaluate = evaluate_enum[0][z_score_level]
drawdown_evaluate = evaluate_enum[1][drawdown_level]
......@@ -759,23 +761,30 @@ class PortfolioDiagnose(object):
indicator_compare = [new_indicator, odl_indicator]
sentence = "在保留{}的基础上,建议赎回{},并增配{}后,整体组合波动率大幅降低,最大回撤从{}降到不足{},年化收益率提升{}个点"
hold_fund = set(self.portfolio) - set(self.abandon_fund_score + self.abandon_fund_corr)
# 在保留{}的基础上,建议赎回{},并增配{}后,整体组合波动率大幅降低,最大回撤从{}降到不足{},年化收益率提升{}个点
hold_fund = set(self.portfolio) - set(self.abandon_fund_score + self.abandon_fund_corr + self.no_data_fund)
hold_fund_name = [get_fund_name(x).values[0][0] for x in hold_fund]
abandon_fund = (self.abandon_fund_score + self.abandon_fund_corr)
abandon_fund_name = [get_fund_name(x).values[0][0] for x in abandon_fund]
proposal_fund = self.proposal_fund
proposal_fund_name = [get_fund_name(x).values[0][0] for x in proposal_fund]
sentence= ""
sentence = []
if hold_fund is not None:
sentence.join("在保留".join(hold_fund) + "的基础上,")
sentence.append("在保留" + "".join([i + "," for i in hold_fund_name]).rstrip(",") + "的基础上")
if abandon_fund is not None:
sentence.join("建议赎回".join(abandon_fund) + ",")
sentence.append("建议赎回" + "".join([i + "," for i in abandon_fund_name]).rstrip(","))
if proposal_fund is not None:
sentence.join("增配".join(proposal_fund) + "后,")
sentence.append("增配" + "".join([i + "," for i in proposal_fund_name]).rstrip(",") + "后")
if new_volatility < old_volatility * 0.9:
sentence.append("整体组合波动率大幅降低")
if new_drawdown < old_max_drawdown:
sentence.join("整体组合波动率大幅降低,")
sentence.append("最大回撤从{:.2%}降到不足{:.2%}".format(old_max_drawdown[0], new_drawdown[0]))
if new_return_ratio_year > old_return_ratio_year:
sentence.join("年化收益率提升{}个点。".format(round(new_return_ratio_year-old_return_ratio_year, 1)))
return suggestions_result, suggestions_result_asset, return_compare_result, indicator_compare, sentence
sentence.append("年化收益率提升{:.2f}个点".format((new_return_ratio_year - old_return_ratio_year) * 100))
whole_sentence = ",".join(sentence).lstrip(",") + "。"
return suggestions_result, suggestions_result_asset, whole_sentence
def single_evaluation(self, fund_id):
"""
......
from sqlalchemy import create_engine
# db = create_engine(
# 'mysql+pymysql://tamp_fund:@imeng408@tamper.mysql.polardb.rds.aliyuncs.com:3306/tamp_fund?charset=utf8mb4',
# pool_size=50,
......@@ -43,7 +39,7 @@ def get_nav(fund, start_date, rollback=False, invest_type='public'):
"WHERE ts_code='{}'".format(fund)
cur = tamp_product_session.execute(sql)
data = cur.fetchall()
df = pd.DataFrame(list(data), columns=['ts_code', 'end_date', 'adj_nav']).dropna(how='any')
df = pd.DataFrame(list(data), columns=['fund_id', 'end_date', 'adj_nav']).dropna(how='any')
df.rename({'ts_code': 'fund_id'}, axis=1, inplace=True)
else:
sql = "SELECT fund_id, price_date, cumulative_nav FROM fund_nav " \
......
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