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
89adaa4a
Commit
89adaa4a
authored
Dec 08, 2020
by
李宗熹
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
产品净值获取方式修改2
parent
b2420a78
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
86 additions
and
172 deletions
+86
-172
portfolio_diagnose.py
app/service/portfolio_diagnose.py
+86
-172
No files found.
app/service/portfolio_diagnose.py
View file @
89adaa4a
# -*- coding: UTF-8 -*-
"""
@author: Zongxi.Li
@file:portfolio_diagnose.py
@time:2020/12/07
"""
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
...
@@ -58,6 +52,23 @@ def replace_fund(manager, substrategy, fund_rank):
...
@@ -58,6 +52,23 @@ def replace_fund(manager, substrategy, fund_rank):
return
df
[
'fund_id'
]
.
values
[
0
]
return
df
[
'fund_id'
]
.
values
[
0
]
def
get_tamp_fund
():
"""获取探普产品池净值表
Returns:
"""
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT id FROM tamp_fund_info WHERE id LIKE 'HF
%
'"
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
# df = pd.read_sql(sql, con)
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_id'
])
# df.rename({'id': 'fund_id'}, axis=1, inplace=True)
return
df
def
search_rank
(
fund_rank
,
fund
,
metric
):
def
search_rank
(
fund_rank
,
fund
,
metric
):
"""查找基金在基金排名表中的指标
"""查找基金在基金排名表中的指标
...
@@ -113,7 +124,8 @@ def choose_good_evaluation(evaluation):
...
@@ -113,7 +124,8 @@ def choose_good_evaluation(evaluation):
if
v1
[
0
]
>
1
:
if
v1
[
0
]
>
1
:
del
evaluation
[
1
]
del
evaluation
[
1
]
if
v2
[
0
]
>
1
:
# if v2[0] > 1:
if
v2
:
del
evaluation
[
2
]
del
evaluation
[
2
]
if
v3
[
0
]
>
1
:
if
v3
[
0
]
>
1
:
del
evaluation
[
3
]
del
evaluation
[
3
]
...
@@ -133,7 +145,8 @@ def choose_bad_evaluation(evaluation):
...
@@ -133,7 +145,8 @@ def choose_bad_evaluation(evaluation):
if
v1
[
0
]
<
2
:
if
v1
[
0
]
<
2
:
del
evaluation
[
1
]
del
evaluation
[
1
]
if
v2
[
0
]
<
2
:
# if v2[0] < 2:
if
v2
:
del
evaluation
[
2
]
del
evaluation
[
2
]
if
v3
[
0
]
<
2
:
if
v3
[
0
]
<
2
:
del
evaluation
[
3
]
del
evaluation
[
3
]
...
@@ -144,17 +157,13 @@ def choose_bad_evaluation(evaluation):
...
@@ -144,17 +157,13 @@ def choose_bad_evaluation(evaluation):
def
get_fund_rank
():
def
get_fund_rank
():
"""获取基金指标排名
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_product
:
tamp_product_session
=
tamp_product
.
session
:return: 基金指标排名表
"""
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT * FROM fund_rank"
sql
=
"SELECT * FROM fund_rank"
# df = pd.read_sql(sql, con)
# df = pd.read_sql(sql, con)
# df = pd.read_csv('fund_rank.csv', encoding='gbk')
# df = pd.read_csv('fund_rank.csv', encoding='gbk')
cur
=
tamp_
fund
_session
.
execute
(
sql
)
cur
=
tamp_
product
_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'index'
,
'fund_id'
,
'range_return'
,
'annual_return'
,
'max_drawdown'
,
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'index'
,
'fund_id'
,
'range_return'
,
'annual_return'
,
'max_drawdown'
,
'sharp_ratio'
,
'volatility'
,
'sortino_ratio'
,
'downside_risk'
,
'sharp_ratio'
,
'volatility'
,
'sortino_ratio'
,
'downside_risk'
,
...
@@ -164,73 +173,28 @@ def get_fund_rank():
...
@@ -164,73 +173,28 @@ def get_fund_rank():
return
df
return
df
def
get_index_daily
(
index_id
,
start_date
):
def
get_index_daily
(
index_id
):
"""获取指数
日更
数据
"""获取指数数据
Args:
Args:
index_id: 指数ID
index_id: 指数ID
start_date: 数据开始时间
Returns:与组合净值形式相同的表
Returns:与组合净值形式相同的表
"""
"""
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_product
:
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_product
:
tamp_product_session
=
tamp_product
.
session
tamp_product_session
=
tamp_product
.
session
sql
=
"SELECT ts_code, trade_date, close FROM index_daily "
\
sql
=
"SELECT ts_code, trade_date, close FROM index_daily WHERE ts_code='{}'"
.
format
(
index_id
)
"WHERE ts_code='{}' AND trade_date>'{}'"
.
format
(
index_id
,
start_date
)
# df = pd.read_sql(sql, con).dropna(how='any')
# df = pd.read_sql(sql, con).dropna(how='any')
cur
=
tamp_product_session
.
execute
(
sql
)
cur
=
tamp_product_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_id'
,
'end_date'
,
'adj_nav'
])
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'ts_code'
,
'trade_date'
,
' close'
])
# df.rename({'ts_code': 'fund_id', 'trade_date': 'end_date', 'close': 'adj_nav'}, axis=1, inplace=True)
df
.
rename
({
'ts_code'
:
'fund_id'
,
'trade_date'
:
'end_date'
,
'close'
:
'adj_nav'
},
axis
=
1
,
inplace
=
True
)
df
[
'end_date'
]
=
pd
.
to_datetime
(
df
[
'end_date'
])
df
.
set_index
(
'end_date'
,
drop
=
True
,
inplace
=
True
)
df
.
sort_index
(
inplace
=
True
,
ascending
=
True
)
df
=
rename_col
(
df
,
index_id
)
return
df
def
get_index_monthly
(
index_id
,
start_date
):
"""获取指数月度数据
Args:
index_id: 指数ID
start_date: 数据开始时间
Returns:与组合净值形式相同的表
"""
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT ts_code, trade_date, pct_chg FROM index_monthly "
\
"WHERE ts_code='{}' AND trade_date>'{}'"
.
format
(
index_id
,
start_date
)
# df = pd.read_sql(sql, con).dropna(how='any')
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_id'
,
'end_date'
,
'pct_chg'
])
df
[
'end_date'
]
=
pd
.
to_datetime
(
df
[
'end_date'
])
df
[
'end_date'
]
=
pd
.
to_datetime
(
df
[
'end_date'
])
df
.
set_index
(
'end_date'
,
drop
=
True
,
inplace
=
True
)
df
.
set_index
(
'end_date'
,
drop
=
True
,
inplace
=
True
)
df
.
sort_index
(
inplace
=
True
,
ascending
=
True
)
df
.
sort_index
(
inplace
=
True
,
ascending
=
True
)
df
=
rename_col
(
df
,
index_id
)
df
=
rename_col
(
df
,
index_id
)
return
df
def
get_tamp_fund
():
"""获取探普产品池净值表
Returns:
"""
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT id FROM tamp_fund_info WHERE id LIKE 'HF
%
'"
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
# df = pd.read_sql(sql, con)
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_id'
])
# df.rename({'id': 'fund_id'}, axis=1, inplace=True)
return
df
return
df
...
@@ -313,11 +277,11 @@ def get_radar_data(fund):
...
@@ -313,11 +277,11 @@ def get_radar_data(fund):
def
get_fund_name
(
fund
):
def
get_fund_name
(
fund
):
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_
fund
:
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_
product
:
tamp_
fund_session
=
tamp_fund
.
session
tamp_
product_session
=
tamp_product
.
session
sql
=
"SELECT fund_short_name FROM fund_info WHERE id='{}'"
.
format
(
fund
)
sql
=
"SELECT fund_short_name FROM fund_info WHERE id='{}'"
.
format
(
fund
)
# df = pd.read_sql(sql, con)
# df = pd.read_sql(sql, con)
cur
=
tamp_
fund
_session
.
execute
(
sql
)
cur
=
tamp_
product
_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
return
df
return
df
...
@@ -330,17 +294,14 @@ tamp_fund = get_tamp_fund()
...
@@ -330,17 +294,14 @@ tamp_fund = get_tamp_fund()
class
PortfolioDiagnose
(
object
):
class
PortfolioDiagnose
(
object
):
def
__init__
(
self
,
client_type
,
portfolio
,
invest_amount
,
expect_return
=
0.2
,
def
__init__
(
self
,
client_type
,
portfolio
,
invest_amount
,
expect_return
=
None
,
expect_drawdown
=
0.1
,
index_id
=
'000905.SH'
,
invest_type
=
'private'
,
start_date
=
None
,
end_date
=
None
):
expect_drawdown
=
None
,
index_id
=
'000905.SH'
,
invest_type
=
'private'
,
start_date
=
None
,
end_date
=
None
):
"""基金诊断
"""基金诊断
Args:
Args:
client_type: 客户类型:1:保守型, 2:稳健型, 3:平衡型, 4:成长型, 5:进取型
client_type: 客户类型:1:保守型, 2:稳健型, 3:平衡型, 4:成长型, 5:进取型
portfolio: 投资组合:[基金1, 基金2, 基金3...]
portfolio: 投资组合:[基金1, 基金2, 基金3...]
invest_amount: 投资金额:10000000元
invest_amount: 投资金额:10000000元
expect_return: 期望收益
expect_drawdown: 期望回撤
index_id: 指数ID
invest_type: 投资类型:public, private, ...
invest_type: 投资类型:public, private, ...
start_date: 诊断所需净值的开始日期
start_date: 诊断所需净值的开始日期
end_date: 诊断所需净值的结束日期
end_date: 诊断所需净值的结束日期
...
@@ -390,7 +351,6 @@ class PortfolioDiagnose(object):
...
@@ -390,7 +351,6 @@ class PortfolioDiagnose(object):
result
=
fund_info
[
fund_info
[
'fund_id'
]
==
portfolio
[
0
]]
result
=
fund_info
[
fund_info
[
'fund_id'
]
==
portfolio
[
0
]]
manager
=
str
(
result
[
'manager'
]
.
values
)
manager
=
str
(
result
[
'manager'
]
.
values
)
strategy
=
result
[
'substrategy'
]
.
values
strategy
=
result
[
'substrategy'
]
.
values
replaced_fund
=
replace_fund
(
manager
,
strategy
,
fund_rank
)
replaced_fund
=
replace_fund
(
manager
,
strategy
,
fund_rank
)
if
replaced_fund
is
not
None
:
if
replaced_fund
is
not
None
:
...
@@ -422,7 +382,7 @@ class PortfolioDiagnose(object):
...
@@ -422,7 +382,7 @@ class PortfolioDiagnose(object):
self
.
no_data_fund
.
append
(
portfolio
[
idx
+
1
])
self
.
no_data_fund
.
append
(
portfolio
[
idx
+
1
])
continue
continue
if
replaced_fund
:
if
replaced_fund
is
not
None
:
prod1
=
get_nav
(
replaced_fund
,
self
.
start_date
,
invest_type
=
self
.
invest_type
)
prod1
=
get_nav
(
replaced_fund
,
self
.
start_date
,
invest_type
=
self
.
invest_type
)
self
.
replace_pair
[
portfolio
[
idx
+
1
]]
=
replaced_fund
self
.
replace_pair
[
portfolio
[
idx
+
1
]]
=
replaced_fund
self
.
freq_list
.
append
(
get_frequency
(
prod1
))
self
.
freq_list
.
append
(
get_frequency
(
prod1
))
...
@@ -503,6 +463,7 @@ class PortfolioDiagnose(object):
...
@@ -503,6 +463,7 @@ class PortfolioDiagnose(object):
# if proposal_z_score > 80 and proposal_strategy in add_strategy:
# if proposal_z_score > 80 and proposal_strategy in add_strategy:
if
proposal_z_score
>
60
:
if
proposal_z_score
>
60
:
proposal_nav
=
get_tamp_nav
(
proposal
,
self
.
start_date
,
invest_type
=
self
.
invest_type
)
proposal_nav
=
get_tamp_nav
(
proposal
,
self
.
start_date
,
invest_type
=
self
.
invest_type
)
# 忽略净值周期大于周更的产品
# 忽略净值周期大于周更的产品
if
get_frequency
(
proposal_nav
)
<=
52
:
if
get_frequency
(
proposal_nav
)
<=
52
:
...
@@ -515,7 +476,6 @@ class PortfolioDiagnose(object):
...
@@ -515,7 +476,6 @@ class PortfolioDiagnose(object):
prod
=
pd
.
merge
(
prod
,
proposal_nav
,
how
=
'outer'
,
on
=
'end_date'
)
.
astype
(
float
)
prod
=
pd
.
merge
(
prod
,
proposal_nav
,
how
=
'outer'
,
on
=
'end_date'
)
.
astype
(
float
)
prod
.
sort_index
(
inplace
=
True
)
prod
.
sort_index
(
inplace
=
True
)
prod
.
ffill
(
inplace
=
True
)
prod
.
ffill
(
inplace
=
True
)
prod
.
bfill
(
inplace
=
True
)
prod
=
resample
(
prod
,
get_trade_cal
(),
min
(
self
.
freq_list
))
prod
=
resample
(
prod
,
get_trade_cal
(),
min
(
self
.
freq_list
))
self
.
new_correlation
=
cal_correlation
(
prod
)
self
.
new_correlation
=
cal_correlation
(
prod
)
...
@@ -550,55 +510,37 @@ class PortfolioDiagnose(object):
...
@@ -550,55 +510,37 @@ class PortfolioDiagnose(object):
end3
=
time
.
time
()
end3
=
time
.
time
()
print
(
"遍历产品池获取候选推荐时间:"
,
end3
-
end2
)
print
(
"遍历产品池获取候选推荐时间:"
,
end3
-
end2
)
# propose_portfolio.to_csv('test_portfolio.csv', encoding='gbk')
# propose_portfolio.to_csv('test_portfolio.csv', encoding='gbk')
mu
=
expected_returns
.
mean_historical_return
(
self
.
propose_portfolio
,
frequency
=
min
(
self
.
freq_list
))
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
))
S
=
risk_models
.
sample_cov
(
self
.
propose_portfolio
,
frequency
=
min
(
self
.
freq_list
))
dd
=
expected_returns
.
drawdown_from_prices
(
self
.
propose_portfolio
)
dd
=
expected_returns
.
drawdown_from_prices
(
self
.
propose_portfolio
)
# if self.client_type == 1:
# if self.client_type == 1:
# proposal_risk = [[x, get_risk_level(search_rank(fund_rank, x, metric='substrategy'))] for x in
# proposal_risk = [[x, get_risk_level(search_rank(fund_rank, x, metric='substrategy'))] for x in
# self.propose_portfolio.columns]
# propose_portfolio.columns]
# self.proposal_fund = list(filter(lambda x: x[1] != 'H', proposal_risk))
# self.proposal_fund = list(filter(lambda x: x[1] != 'H', proposal_risk))
# drop_fund_list = list(filter(lambda x: x[1] == 'H', proposal_risk))
# drop_fund_list = [x[0] for x in drop_fund_list]
# drop_fund_list = list(filter(lambda x: x[1] = 'H', proposal_risk))
# self.propose_portfolio.drop(drop_fund_list, axis=1, inplace=True)
# proposal_portfolio = list((set(self.portfolio) - set(self.no_data_fund) - set(self.replace_pair.keys())) | \
# mu = expected_returns.mean_historical_return(self.propose_portfolio, frequency=min(self.freq_list))
# (set(self.proposal_fund) | set(self.replace_pair.values())))
# S = risk_models.sample_cov(self.propose_portfolio, frequency=min(self.freq_list))
# propose_portfolio.drop()
# dd = expected_returns.drawdown_from_prices(self.propose_portfolio)
propose_risk_mapper
=
dict
()
propose_risk_mapper
=
dict
()
for
fund
in
self
.
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'
)))
propose_risk_mapper
[
fund
]
=
str
(
get_risk_level
(
search_rank
(
fund_rank
,
fund
,
metric
=
'substrategy'
)))
if
self
.
client_type
==
1
:
# risk_upper = {"H": 0.0}
risk_upper
=
{
"H"
:
0.0
}
# risk_lower = {"L": 0.6, "M": 0.4}
risk_lower
=
{
"L"
:
0.0
}
elif
self
.
client_type
==
2
:
w_low
=
1e6
/
self
.
invest_amount
risk_upper
=
{
"H"
:
0.0
}
ef
=
EfficientFrontier
(
mu
,
S
,
expected_drawdown
=
dd
)
risk_lower
=
{
"L"
:
0.0
}
# ef.add_sector_constraints(propose_risk_mapper, risk_lower, risk_upper)
elif
self
.
client_type
==
3
:
# weights = ef.nonconvex_objective(deviation_risk_parity, ef.cov_matrix)
risk_upper
=
{
"H"
:
0.0
}
ef
.
efficient_return
(
0.3
)
risk_lower
=
{
"L"
:
0.0
}
elif
self
.
client_type
==
4
:
risk_upper
=
{
"H"
:
0.0
}
risk_lower
=
{
"L"
:
0.0
}
elif
self
.
client_type
==
5
:
risk_upper
=
{
"H"
:
0.0
}
risk_lower
=
{
"L"
:
0.0
}
else
:
risk_upper
=
{
"H"
:
0.0
}
risk_lower
=
{
"L"
:
0.0
}
raise
ValueError
w_low
=
1000000
/
self
.
invest_amount
# ef = EfficientFrontier(mu, S, weight_bounds=[w_low, 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
.
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
()))
self
.
new_weights
[
self
.
new_weights
<
w_low
]
=
0
print
(
clean_weights
)
print
(
clean_weights
)
print
(
self
.
new_weights
)
end4
=
time
.
time
()
end4
=
time
.
time
()
print
(
"模型计算一次时间:"
,
end4
-
end3
)
print
(
"模型计算一次时间:"
,
end4
-
end3
)
# S = np.asmatrix(S)
# S = np.asmatrix(S)
...
@@ -622,7 +564,7 @@ class PortfolioDiagnose(object):
...
@@ -622,7 +564,7 @@ class PortfolioDiagnose(object):
# self.proposal_weights = calcu_w(w_origin, S, risk_target)
# self.proposal_weights = calcu_w(w_origin, S, risk_target)
def
return_compare
(
self
):
def
return_compare
(
self
):
index_data
=
get_index_daily
(
self
.
index_id
,
self
.
start_date
)
index_data
=
get_index_daily
(
self
.
index_id
)
index_data
=
pd
.
merge
(
index_data
,
self
.
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
index_return
=
index_data
.
iloc
[:,
:]
/
index_data
.
iloc
[
0
,
:]
-
1
# origin_fund_return = origin_portfolio.iloc[:, :] / origin_portfolio.iloc[0, :] - 1
# origin_fund_return = origin_portfolio.iloc[:, :] / origin_portfolio.iloc[0, :] - 1
...
@@ -668,7 +610,7 @@ class PortfolioDiagnose(object):
...
@@ -668,7 +610,7 @@ class PortfolioDiagnose(object):
# 正收益基金数量
# 正收益基金数量
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
:
...
@@ -737,6 +679,7 @@ class PortfolioDiagnose(object):
...
@@ -737,6 +679,7 @@ class PortfolioDiagnose(object):
return
ret
return
ret
def
new_evaluation
(
self
,
group_name
,
group_result
,
data_adaptor
):
def
new_evaluation
(
self
,
group_name
,
group_result
,
data_adaptor
):
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
)
hold_info_df
=
pd
.
DataFrame
(
hold_info
)
...
@@ -744,7 +687,7 @@ class PortfolioDiagnose(object):
...
@@ -744,7 +687,7 @@ class PortfolioDiagnose(object):
data_adaptor
.
user_customer_order_df
[
"folio_name"
]
==
group_name
]
data_adaptor
.
user_customer_order_df
[
"folio_name"
]
==
group_name
]
group_order_start_date
=
pd
.
to_datetime
(
group_order_df
[
"confirm_share_date"
]
.
min
())
group_order_start_date
=
pd
.
to_datetime
(
group_order_df
[
"confirm_share_date"
]
.
min
())
# 原组合总市值, 区间收益, 年化收益, 波动率, 最大回撤,
夏普比率
# 原组合总市值, 区间收益, 年化收益, 波动率, 最大回撤,
夏普比率
total_asset
=
round
(
hold_info_df
[
"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"
]
...
@@ -767,11 +710,9 @@ class PortfolioDiagnose(object):
...
@@ -767,11 +710,9 @@ class PortfolioDiagnose(object):
# 基金名称,策略分级
# 基金名称,策略分级
propose_fund_id_name_list
=
[
propose_fund_df
[
propose_fund_df
[
"fund_id"
]
==
fund_id
][
"fund_name"
]
.
values
[
0
]
for
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
]
fund_id
in
propose_fund_id_list
]
propose_fund_id_strategy_name_list
=
[
propose_fund_id_strategy_name_list
=
[
dict_substrategy
[
int
(
propose_fund_df
[
propose_fund_df
[
"fund_id"
]
==
fund_id
][
"substrategy"
]
.
values
[
0
])]
for
dict_substrategy
[
int
(
propose_fund_df
[
propose_fund_df
[
"fund_id"
]
==
fund_id
][
"substrategy"
]
.
values
[
0
])]
for
fund_id
in
propose_fund_id_list
]
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_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
]:
propose_info
=
{
propose_fund_id_strategy_name_list
[
i
]:
{
"fund_name"
:
propose_fund_id_name_list
[
i
],
{
"fund_name"
:
propose_fund_id_name_list
[
i
],
...
@@ -813,50 +754,46 @@ class PortfolioDiagnose(object):
...
@@ -813,50 +754,46 @@ class PortfolioDiagnose(object):
# 新组合累积收益df
# 新组合累积收益df
propose_fund_return_limit_data
=
propose_fund_return
[
propose_fund_return
.
index
>=
group_order_start_date
]
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
]
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
)
/
(
propose_fund_return_limit_data
[
"new_return"
]
=
(
propose_fund_return_limit_data
[
"return"
]
-
start_return
)
/
(
1
+
start_return
)
1
+
start_return
)
# 新组合累积收益
# 新组合累积收益
new_return_ratio
=
propose_fund_return_limit_data
[
"new_return"
]
.
values
[
-
1
]
new_return_ratio
=
propose_fund_return_limit_data
[
"new_return"
]
.
values
[
-
1
]
# 新组合区间年化收益率
# 新组合区间年化收益率
freq_max
=
group_order_df
[
"freq"
]
.
max
()
freq_max
=
group_order_df
[
"freq"
]
.
max
()
n_freq
=
freq_days
(
int
(
freq_max
))
n_freq
=
freq_days
(
int
(
freq_max
))
new_return_ratio_year
=
annual_return
(
propose_fund_return_limit_data
[
"new_return"
]
.
values
[
-
1
],
new_return_ratio_year
=
annual_return
(
propose_fund_return_limit_data
[
"new_return"
]
.
values
[
-
1
],
propose_fund_return_limit_data
,
n_freq
)
propose_fund_return_limit_data
,
n_freq
)
# 新组合波动率
# 新组合波动率
new_volatility
=
volatility
(
propose_fund_return_limit_data
[
"new_return"
]
+
1
,
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
)
new_drawdown
=
max_drawdown
(
propose_fund_return_limit_data
[
"new_return"
]
+
1
)
# 新组合夏普比率
# 新组合夏普比率
sim
=
simple_return
(
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
)
exc
=
excess_return
(
sim
,
BANK_RATE
,
n_freq
)
new_sharpe
=
sharpe_ratio
(
exc
,
sim
,
n_freq
)
new_sharpe
=
sharpe_ratio
(
exc
,
sim
,
n_freq
)
# 指数收益
# 指数收益
index_return
=
index_return
[
index_return
.
index
>=
group_order_start_date
]
index_return
=
index_return
[
index_return
.
index
>=
group_order_start_date
]
start_index_return
=
index_return
[
"
adj_nav
"
]
.
values
[
0
]
start_index_return
=
index_return
[
"
close
"
]
.
values
[
0
]
index_return
[
"new_index_return"
]
=
(
index_return
[
"
adj_nav
"
]
-
start_index_return
)
/
(
1
+
start_index_return
)
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
=
index_return
[
"new_index_return"
]
.
values
[
-
1
]
index_return_ratio_year
=
annual_return
(
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_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
(
propose_fund_return_limit_data
[
"new_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
)
# 收益对比数据
# 收益对比数据
return_compare_df
=
pd
.
merge
(
index_return
[[
"new_index_return"
]],
old_return_df
[[
"cum_return_ratio"
]],
return_compare_df
=
pd
.
merge
(
index_return
[[
"new_index_return"
]],
old_return_df
[[
"cum_return_ratio"
]],
right_index
=
True
,
right_index
=
True
,
left_index
=
True
)
left_index
=
True
)
return_compare_df
=
pd
.
merge
(
return_compare_df
,
propose_fund_return_limit_data
[
"new_return"
],
right_index
=
True
,
return_compare_df
=
pd
.
merge
(
return_compare_df
,
propose_fund_return_limit_data
[
"new_return"
],
right_index
=
True
,
left_index
=
True
)
left_index
=
True
)
return_compare_df
[
"date"
]
=
return_compare_df
.
index
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
[
"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
},
"index"
:
{
"name"
:
"中证500"
,
"data"
:
return_compare_df
[
"new_index_return"
]
.
values
},
"index"
:
{
"name"
:
"中证500"
,
"data"
:
return_compare_df
[
"new_index_return"
]
.
values
},
...
@@ -865,20 +802,15 @@ class PortfolioDiagnose(object):
...
@@ -865,20 +802,15 @@ class PortfolioDiagnose(object):
}
}
# 指标对比
# 指标对比
old_indicator
=
{
"group_name"
:
"现有持仓组合"
,
"return_ratio"
:
round
((
old_return
-
1
)
*
100
,
2
),
old_indicator
=
{
"group_name"
:
"现有持仓组合"
,
"return_ratio"
:
round
((
old_return
-
1
)
*
100
,
2
),
"return_ratio_year"
:
round
(
old_return_ratio_year
*
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
)}
"volatility"
:
round
(
old_volatility
*
100
,
2
),
new_indicator
=
{
"group_name"
:
"建议优化组合"
,
"return_ratio"
:
round
(
new_return_ratio
*
100
,
2
),
"return_ratio_year"
:
round
(
new_return_ratio_year
*
100
,
2
),
"max_drawdown"
:
round
(
old_max_drawdown
[
0
]
*
100
,
2
),
"sharpe"
:
round
(
old_sharpe
,
2
)}
"volatility"
:
round
(
new_volatility
*
100
,
2
),
"max_drawdown"
:
round
(
new_drawdown
[
0
]
*
100
,
2
),
"sharpe"
:
round
(
new_sharpe
,
2
)}
new_indicator
=
{
"group_name"
:
"建议优化组合"
,
"return_ratio"
:
round
(
new_return_ratio
*
100
,
2
),
index_indicator
=
{
"group_name"
:
"中证500"
,
"return_ratio"
:
round
(
index_return_ratio
*
100
,
2
),
"return_ratio_year"
:
round
(
index_return_ratio_year
*
100
,
2
),
"return_ratio_year"
:
round
(
new_return_ratio_year
*
100
,
2
),
"volatility"
:
round
(
index_volatility
*
100
,
2
),
"max_drawdown"
:
round
(
index_drawdown
[
0
]
*
100
,
2
),
"sharpe"
:
round
(
index_sharpe
,
2
)}
"volatility"
:
round
(
new_volatility
*
100
,
2
),
"max_drawdown"
:
round
(
new_drawdown
[
0
]
*
100
,
2
),
"sharpe"
:
round
(
new_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
)}
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
]
...
@@ -928,16 +860,6 @@ class PortfolioDiagnose(object):
...
@@ -928,16 +860,6 @@ class PortfolioDiagnose(object):
70
<=
z_score
<
80
,
70
<=
z_score
<
80
,
z_score
<
70
],
[
0
,
1
,
2
])
.
item
()
z_score
<
70
],
[
0
,
1
,
2
])
.
item
()
index_return_monthly
=
get_index_monthly
(
self
.
index_id
,
self
.
start_date
)
fund_nav
=
get_tamp_nav
(
fund_id
,
self
.
start_date
,
invest_type
=
self
.
invest_type
)
fund_nav_monthly
=
fund_nav
.
groupby
([
fund_nav
.
index
.
year
,
fund_nav
.
index
.
month
])
.
tail
(
1
)
fund_nav_monthly
=
rename_col
(
fund_nav_monthly
,
fund_id
)
fund_return_monthly
=
simple_return
(
fund_nav_monthly
[
fund_id
]
.
astype
(
float
))
index_return_monthly
.
index
=
index_return_monthly
.
index
.
strftime
(
'
%
Y-
%
m'
)
fund_return_monthly
.
index
=
fund_return_monthly
.
index
.
strftime
(
'
%
Y-
%
m'
)
compare
=
pd
.
merge
(
index_return_monthly
,
fund_return_monthly
,
how
=
'inner'
,
left_index
=
True
,
right_index
=
True
)
fund_win_rate
=
((
compare
[
fund_id
]
-
compare
[
'pct_chg'
])
>
0
)
.
sum
()
return_rank
=
search_rank
(
fund_rank
,
fund_id
,
metric
=
'annual_return_rank'
)
return_rank
=
search_rank
(
fund_rank
,
fund_id
,
metric
=
'annual_return_rank'
)
return_level
=
np
.
select
([
return_rank
>=
0.8
,
return_level
=
np
.
select
([
return_rank
>=
0.8
,
0.7
<=
return_rank
<
0.8
,
0.7
<=
return_rank
<
0.8
,
...
@@ -961,7 +883,7 @@ class PortfolioDiagnose(object):
...
@@ -961,7 +883,7 @@ class PortfolioDiagnose(object):
sharp_rank
<
0.6
],
[
0
,
1
,
2
])
.
item
()
sharp_rank
<
0.6
],
[
0
,
1
,
2
])
.
item
()
data
=
{
1
:
[
total_level
,
return_level
,
drawdown_level
,
sharp_level
],
data
=
{
1
:
[
total_level
,
return_level
,
drawdown_level
,
sharp_level
],
2
:
[
return_triple
,
str
(
fund_win_rate
)
,
return_bool
],
2
:
[
return_triple
,
"12"
,
return_bool
],
3
:
[
drawdown_triple
,
drawdown_triple
,
format
(
drawdown_value
,
'.2
%
'
),
drawdown_triple
],
3
:
[
drawdown_triple
,
drawdown_triple
,
format
(
drawdown_value
,
'.2
%
'
),
drawdown_triple
],
4
:
[
return_bool
,
drawdown_bool
,
drawdown_bool
,
return_bool
,
drawdown_bool
]}
4
:
[
return_bool
,
drawdown_bool
,
drawdown_bool
,
return_bool
,
drawdown_bool
]}
...
@@ -998,7 +920,7 @@ class PortfolioDiagnose(object):
...
@@ -998,7 +920,7 @@ class PortfolioDiagnose(object):
sentence
=
{
sentence
=
{
1
:
"该基金整体表现
%
s,收益能力
%
s,回撤控制能力
%
s,风险收益比例
%
s;
\n
"
,
1
:
"该基金整体表现
%
s,收益能力
%
s,回撤控制能力
%
s,风险收益比例
%
s;
\n
"
,
2
:
"在收益方面,该基金年化收益能力
%
s同类基金平均水平,有
%
s
个
区间跑赢指数,绝对收益能力
%
s;
\n
"
,
2
:
"在收益方面,该基金年化收益能力
%
s同类基金平均水平,有
%
s区间跑赢指数,绝对收益能力
%
s;
\n
"
,
3
:
"在风险方面,该基金抵御风险能力
%
s,在同类基金中处于
%
s等水平,最大回撤为
%
s,
%
s同类基金平均水平;
\n
"
,
3
:
"在风险方面,该基金抵御风险能力
%
s,在同类基金中处于
%
s等水平,最大回撤为
%
s,
%
s同类基金平均水平;
\n
"
,
4
:
"该基金收益
%
s的同时回撤
%
s,也就是说,该基金在用
%
s风险换取
%
s收益,存在
%
s风险;
\n
"
,
4
:
"该基金收益
%
s的同时回撤
%
s,也就是说,该基金在用
%
s风险换取
%
s收益,存在
%
s风险;
\n
"
,
5
:
"基金经理,投资年限
%
s年,经验丰富;投资能力较强,生涯中共管理过
%
s只基金,历任的
%
s只基金平均业绩在同类中处于上游水平,其中
%
s只排名在前
%
s;生涯年化回报率
%
s,同期大盘只有
%
s;"
}
5
:
"基金经理,投资年限
%
s年,经验丰富;投资能力较强,生涯中共管理过
%
s只基金,历任的
%
s只基金平均业绩在同类中处于上游水平,其中
%
s只排名在前
%
s;生涯年化回报率
%
s,同期大盘只有
%
s;"
}
...
@@ -1020,14 +942,6 @@ class PortfolioDiagnose(object):
...
@@ -1020,14 +942,6 @@ class PortfolioDiagnose(object):
ret
.
append
(
single_sentence
)
ret
.
append
(
single_sentence
)
i
+=
1
i
+=
1
fund_name
=
get_fund_name
(
fund_id
)
.
values
[
0
][
0
]
fund_name
=
get_fund_name
(
fund_id
)
.
values
[
0
][
0
]
if
not
ret
:
try
:
default_evaluation
=
pd
.
read_csv
(
"evaluation.csv"
,
encoding
=
'utf-8'
,
names
=
[
'fund_id'
,
'eval'
])
ret
.
append
(
'1、'
+
default_evaluation
[
default_evaluation
[
'fund_id'
]
==
fund_id
][
'eval'
]
.
values
[
0
])
except
Exception
:
pass
evaluation_dict
=
{
'name'
:
fund_name
,
'data'
:
ret
}
evaluation_dict
=
{
'name'
:
fund_name
,
'data'
:
ret
}
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'
]
=
"换仓"
...
@@ -1076,4 +990,4 @@ if __name__ == '__main__':
...
@@ -1076,4 +990,4 @@ if __name__ == '__main__':
print
(
'旧组合相关性:'
,
portfolio_diagnose
.
old_correlation
)
print
(
'旧组合相关性:'
,
portfolio_diagnose
.
old_correlation
)
print
(
'新组合相关性:'
,
portfolio_diagnose
.
new_correlation
)
print
(
'新组合相关性:'
,
portfolio_diagnose
.
new_correlation
)
print
(
'旧组合个基评价:'
,
portfolio_diagnose
.
old_portfolio_evaluation
())
print
(
'旧组合个基评价:'
,
portfolio_diagnose
.
old_portfolio_evaluation
())
print
(
'新组合个基评价:'
,
portfolio_diagnose
.
propose_fund_evaluation
())
print
(
'新组合个基评价:'
,
portfolio_diagnose
.
propose_fund_evaluation
())
\ No newline at end of file
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