Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in
Toggle navigation
F
fund_report
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
彭熊
fund_report
Commits
6c75e21f
Commit
6c75e21f
authored
Dec 03, 2020
by
pengxiong@wealthgrow.cn
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'origin/dev' into dev
parents
28776226
70bd37f1
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
101 additions
and
38 deletions
+101
-38
portfolio_diagnose.py
app/service/portfolio_diagnose.py
+100
-37
result_service.py
app/service/result_service.py
+1
-1
No files found.
app/service/portfolio_diagnose.py
View file @
6c75e21f
# -*- 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'
:
'
%.2
f'
%
return_score
},
{
'name'
:
'抗风险能力'
,
'data'
:
'
%.2
f'
%
downside_score
},
{
'name'
:
'极端风险'
,
'data'
:
'
%.2
f'
%
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
()
# 由于数据不足半年而被替换为相同基金经理和策略的原基金和替换基金的映射
...
...
@@ -478,14 +473,14 @@ class PortfolioDiagnose(object):
dd
=
expected_returns
.
drawdown_from_prices
(
propose_portfolio
)
# if self.client_type == 1:
# proposal_risk = [[x, get_risk_level(search_rank(fund_rank, x, metric='substrategy'))] for x in
# propose_portfolio.columns]
# self.proposal_fund = list(filter(lambda x: x[1] != 'H', proposal_risk))
# proposal_risk = [[x, get_risk_level(search_rank(fund_rank, x, metric='substrategy'))] for x in
# propose_portfolio.columns]
# self.proposal_fund = list(filter(lambda x: x[1] != 'H', proposal_risk))
# drop_fund_list = list(filter(lambda x: x[1] = 'H', proposal_risk))
# proposal_portfolio = list((set(self.portfolio) - set(self.no_data_fund) - set(self.replace_pair.keys())) | \
# (set(self.proposal_fund) | set(self.replace_pair.values())))
# propose_portfolio.drop()
# drop_fund_list = list(filter(lambda x: x[1] = 'H', proposal_risk))
# proposal_portfolio = list((set(self.portfolio) - set(self.no_data_fund) - set(self.replace_pair.keys())) | \
# (set(self.proposal_fund) | set(self.replace_pair.values())))
# propose_portfolio.drop()
propose_risk_mapper
=
dict
()
for
fund
in
propose_portfolio
.
columns
:
...
...
@@ -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,29 +585,28 @@ 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
]
...
...
@@ -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
=
[]
...
...
app/service/result_service.py
View file @
6c75e21f
...
...
@@ -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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment