Commit 68c1d166 authored by 李宗熹's avatar 李宗熹

修改objective

parent 9447fd90
...@@ -335,7 +335,7 @@ tamp_fund = get_tamp_fund() ...@@ -335,7 +335,7 @@ tamp_fund = get_tamp_fund()
class PortfolioDiagnose(object): class PortfolioDiagnose(object):
def __init__(self, client_type, portfolio, invest_amount, expect_return=0.15, def __init__(self, client_type, portfolio, invest_amount, expect_return=0.1,
expect_drawdown=0.15, index_id='000905.SH', invest_type='private', start_date=None, end_date=None): expect_drawdown=0.15, index_id='000905.SH', invest_type='private', start_date=None, end_date=None):
"""基金诊断 """基金诊断
...@@ -543,7 +543,7 @@ class PortfolioDiagnose(object): ...@@ -543,7 +543,7 @@ class PortfolioDiagnose(object):
else: else:
prod.drop(columns=proposal, inplace=True) prod.drop(columns=proposal, inplace=True)
prod.bfill(inplace=True) prod.dropna(how='all', inplace=True)
self.new_correlation = self.new_correlation.fillna(1).round(2) self.new_correlation = self.new_correlation.fillna(1).round(2)
self.new_correlation.columns = self.new_correlation.columns.map(lambda x: get_fund_name(x).values[0][0]) self.new_correlation.columns = self.new_correlation.columns.map(lambda x: get_fund_name(x).values[0][0])
self.new_correlation.index = self.new_correlation.index.map(lambda x: get_fund_name(x).values[0][0]) self.new_correlation.index = self.new_correlation.index.map(lambda x: get_fund_name(x).values[0][0])
...@@ -605,13 +605,12 @@ class PortfolioDiagnose(object): ...@@ -605,13 +605,12 @@ class PortfolioDiagnose(object):
try: try:
ef = EfficientFrontier(mu, S, weight_bounds=[w_low, 1], expected_drawdown=dd) ef = EfficientFrontier(mu, S, weight_bounds=[w_low, 1], expected_drawdown=dd)
# ef = EfficientFrontier(mu, S, weight_bounds=[0, 1], expected_drawdown=dd) # ef = EfficientFrontier(mu, S, weight_bounds=[0, 1], expected_drawdown=dd)
# ef.add_sector_constraints(propose_risk_mapper, risk_lower, risk_upper) ef.add_sector_constraints(propose_risk_mapper, risk_lower, risk_upper)
ef.efficient_return(target_return=self.expect_return, target_drawdown=self.expect_drawdown) ef.efficient_return(target_return=self.expect_return, target_drawdown=self.expect_drawdown)
clean_weights = ef.clean_weights() clean_weights = ef.clean_weights()
ef.portfolio_performance(verbose=True) ef.portfolio_performance(verbose=True)
self.new_weights = np.array(list(clean_weights.values())) self.new_weights = np.array(list(clean_weights.values()))
except Exception as e: except:
print(e)
self.new_weights = np.asarray([1/len(self.propose_portfolio.columns)] * len(self.propose_portfolio.columns)) self.new_weights = np.asarray([1/len(self.propose_portfolio.columns)] * len(self.propose_portfolio.columns))
print(self.new_weights) print(self.new_weights)
...@@ -708,10 +707,13 @@ class PortfolioDiagnose(object): ...@@ -708,10 +707,13 @@ class PortfolioDiagnose(object):
# 覆盖的基金名称 # 覆盖的基金名称
strategy_name_evaluate = "".join(uniqe_strategy_name)[:-1] strategy_name_evaluate = "".join(uniqe_strategy_name)[:-1]
try:
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 = "策略分散程度不高"
except ZeroDivisionError:
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
...@@ -750,7 +752,73 @@ class PortfolioDiagnose(object): ...@@ -750,7 +752,73 @@ class PortfolioDiagnose(object):
ret = [] ret = []
for k, v in data.items(): for k, v in data.items():
ret.append(sentence[k].format(*data[k]).replace(",;", ";")) ret.append(sentence[k].format(*data[k]).replace(",;", ";"))
return ret
# 旧组合累积收益df
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())
freq_max = group_order_df["freq"].max()
n_freq = freq_days(int(freq_max))
old_return_df = group_result_data["return_df"]
old_return_df["cum_return_ratio"] = old_return_df["cum_return_ratio"] - 1
# 原组合总市值, 区间收益, 年化收益, 波动率, 最大回撤, 夏普比率
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"]
old_max_drawdown = group_result_data["max_drawdown"]
old_sharpe = group_result_data["sharpe"]
# 指数收益
index_data = get_index_daily(self.index_id, self.start_date)
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
# 指数收益
index_return = index_return[index_return.index >= group_order_start_date]
start_index_return = index_return[" close"].values[0]
index_return["new_index_return"] = (index_return[" close"] - start_index_return) / (1 + start_index_return)
index_return_ratio = index_return["new_index_return"].values[-1]
index_return_ratio_year = annual_return(index_return["new_index_return"].values[-1],
index_return["new_index_return"], n_freq)
index_volatility = volatility(index_return["new_index_return"] + 1, n_freq)
index_drawdown = max_drawdown(index_return["new_index_return"] + 1)
index_sim = simple_return(index_return["new_index_return"]+1)
index_exc = excess_return(index_sim, BANK_RATE, n_freq)
index_sharpe = sharpe_ratio(index_exc, index_sim, n_freq)
# 收益对比数据
return_compare_df = pd.merge(index_return[["new_index_return"]], old_return_df[["cum_return_ratio"]],
right_index=True,
left_index=True)
return_compare_df["date"] = return_compare_df.index
return_compare_df["date"] = return_compare_df["date"].apply(lambda x: x.strftime("%Y-%m-%d"))
return_compare_df.iloc[1:-1, :]["date"] = ""
old_return_compare_result = {
"index": {"name": "中证500", "data": return_compare_df["new_index_return"].values*100},
"origin_combination": {"name": "原组合", "data": return_compare_df["cum_return_ratio"].values*100},
"xlabels": return_compare_df["date"].values
}
# 指标对比
old_indicator = {"group_name": "现有持仓组合", "return_ratio": round((old_return - 1) * 100, 2),
"return_ratio_year": round(old_return_ratio_year * 100, 2),
"volatility": round(old_volatility * 100, 2),
"max_drawdown": round(old_max_drawdown[0] * 100, 2), "sharpe": round(old_sharpe, 2)}
index_indicator = {"group_name": "中证500", "return_ratio": round(index_return_ratio * 100, 2),
"return_ratio_year": round(index_return_ratio_year * 100, 2),
"volatility": round(index_volatility * 100, 2),
"max_drawdown": round(index_drawdown[0] * 100, 2), "sharpe": round(index_sharpe, 2)}
old_indicator_compare = [old_indicator, index_indicator]
return ret, old_return_compare_result, old_indicator_compare
def new_evaluation(self, group_name, group_result, data_adaptor): def new_evaluation(self, group_name, group_result, data_adaptor):
try: try:
...@@ -793,7 +861,6 @@ class PortfolioDiagnose(object): ...@@ -793,7 +861,6 @@ class PortfolioDiagnose(object):
"substrategy": propose_fund_id_strategy_name_list[i], "substrategy": propose_fund_id_strategy_name_list[i],
"asset": propose_fund_asset[i]} "asset": propose_fund_asset[i]}
for i in range(len(propose_fund_id_list))} for i in range(len(propose_fund_id_list))}
# 调仓建议 # 调仓建议
suggestions_result = {} suggestions_result = {}
old_hold_fund_name_list = list(hold_info_df["fund_name"]) old_hold_fund_name_list = list(hold_info_df["fund_name"])
...@@ -857,7 +924,7 @@ class PortfolioDiagnose(object): ...@@ -857,7 +924,7 @@ class PortfolioDiagnose(object):
index_return_ratio_year = annual_return(index_return["new_index_return"].values[-1], index_return["new_index_return"], n_freq) index_return_ratio_year = annual_return(index_return["new_index_return"].values[-1], index_return["new_index_return"], n_freq)
index_volatility = volatility(index_return["new_index_return"]+1, n_freq) index_volatility = volatility(index_return["new_index_return"]+1, n_freq)
index_drawdown = max_drawdown(index_return["new_index_return"]+1) index_drawdown = max_drawdown(index_return["new_index_return"]+1)
index_sim = simple_return(propose_fund_return_limit_data["new_return"]+1) index_sim = simple_return(index_return["new_index_return"]+1)
index_exc = excess_return(index_sim, BANK_RATE, n_freq) index_exc = excess_return(index_sim, BANK_RATE, n_freq)
index_sharpe = sharpe_ratio(index_exc, index_sim, n_freq) index_sharpe = sharpe_ratio(index_exc, index_sim, n_freq)
...@@ -870,9 +937,9 @@ class PortfolioDiagnose(object): ...@@ -870,9 +937,9 @@ class PortfolioDiagnose(object):
return_compare_df["date"] = return_compare_df["date"].apply(lambda x: x.strftime("%Y-%m-%d")) return_compare_df["date"] = return_compare_df["date"].apply(lambda x: x.strftime("%Y-%m-%d"))
return_compare_df.iloc[1:-1,:]["date"] = "" return_compare_df.iloc[1:-1,:]["date"] = ""
return_compare_result = { return_compare_result = {
"new_combination": {"name": "新组合", "data": return_compare_df["new_return"].values}, "new_combination": {"name": "新组合", "data": return_compare_df["new_return"].values*100},
"index": {"name": "中证500", "data": return_compare_df["new_index_return"].values}, "index": {"name": "中证500", "data": return_compare_df["new_index_return"].values*100},
"origin_combination": {"name": "原组合", "data": return_compare_df["cum_return_ratio"].values}, "origin_combination": {"name": "原组合", "data": return_compare_df["cum_return_ratio"].values*100},
"xlabels": return_compare_df["date"].values "xlabels": return_compare_df["date"].values
} }
...@@ -885,6 +952,7 @@ class PortfolioDiagnose(object): ...@@ -885,6 +952,7 @@ class PortfolioDiagnose(object):
"volatility": round(index_volatility*100, 2), "max_drawdown": round(index_drawdown[0]*100, 2), "sharpe": round(index_sharpe, 2)} "volatility": round(index_volatility*100, 2), "max_drawdown": round(index_drawdown[0]*100, 2), "sharpe": round(index_sharpe, 2)}
indicator_compare = [new_indicator, old_indicator, index_indicator] indicator_compare = [new_indicator, old_indicator, index_indicator]
# 在保留{}的基础上,建议赎回{},并增配{}后,整体组合波动率大幅降低,最大回撤从{}降到不足{},年化收益率提升{}个点 # 在保留{}的基础上,建议赎回{},并增配{}后,整体组合波动率大幅降低,最大回撤从{}降到不足{},年化收益率提升{}个点
hold_fund = set(self.portfolio) - set(self.abandon_fund_score + self.abandon_fund_corr + self.no_data_fund) 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] hold_fund_name = [get_fund_name(x).values[0][0] for x in hold_fund]
...@@ -913,7 +981,7 @@ class PortfolioDiagnose(object): ...@@ -913,7 +981,7 @@ class PortfolioDiagnose(object):
repr(e) repr(e)
return None, None, None, None, None return None, None, None, None, None
def single_evaluation(self, fund_id, objective): def single_evaluation(self, fund_id, objective=False):
""" """
1、该基金整体表现优秀/良好/一般,收益能力优秀/良好/合格/较差,回撤控制能力优秀/良好/合格/较差,风险收益比例较高/一般/较低; 1、该基金整体表现优秀/良好/一般,收益能力优秀/良好/合格/较差,回撤控制能力优秀/良好/合格/较差,风险收益比例较高/一般/较低;
2、在收益方面,该基金年化收益能力高于/持平/低于同类基金平均水平,有x%区间跑赢大盘/指数,绝对收益能力优秀/一般; 2、在收益方面,该基金年化收益能力高于/持平/低于同类基金平均水平,有x%区间跑赢大盘/指数,绝对收益能力优秀/一般;
...@@ -1038,19 +1106,22 @@ class PortfolioDiagnose(object): ...@@ -1038,19 +1106,22 @@ class PortfolioDiagnose(object):
pass pass
evaluation_dict = {'name': fund_name, 'data': ret} evaluation_dict = {'name': fund_name, 'data': ret}
if objective: if objective:
if fund_id in self.abandon_fund_score + self.abandon_fund_corr: if fund_id in self.abandon_fund_score + self.abandon_fund_corr:
evaluation_dict['status'] = "换仓" evaluation_dict['status'] = "换仓"
elif fund_id in self.portfolio: elif fund_id in self.portfolio:
evaluation_dict['status'] = "保留" evaluation_dict['status'] = "保留"
else:
evaluation_dict['status'] = ""
return evaluation_dict return evaluation_dict
def old_portfolio_evaluation(self, ): def old_portfolio_evaluation(self, objective=False):
try: try:
result = [] result = []
for fund in self.portfolio: for fund in self.portfolio:
try: try:
result.append(self.single_evaluation(fund)) result.append(self.single_evaluation(fund, objective))
except IndexError: except IndexError:
continue continue
return result return result
......
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