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
37f8c2ae
Commit
37f8c2ae
authored
Feb 05, 2021
by
赵杰
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
日期
parent
da973885
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
115 additions
and
31 deletions
+115
-31
portfolio_diagnose.py
app/service/portfolio_diagnose.py
+81
-15
result_service_v2.py
app/service/result_service_v2.py
+4
-4
monthReportV2.1.html
app/templates/v2/monthReportV2.1.html
+8
-1
jinjia2html_v2.py
app/utils/jinjia2html_v2.py
+22
-11
No files found.
app/service/portfolio_diagnose.py
View file @
37f8c2ae
...
@@ -440,6 +440,47 @@ def get_fund_name(fund, fund_type=1):
...
@@ -440,6 +440,47 @@ def get_fund_name(fund, fund_type=1):
return
df
return
df
def
get_fund_substrategy
(
fund
,
fund_type
=
1
):
try
:
if
fund_type
==
0
:
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT fund_short_name FROM tx_fund_info WHERE `id`='{}'"
.
format
(
fund
)
# df = pd.read_sql(sql, con)
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
return
str
(
df
.
values
[
0
][
0
])
elif
fund_type
==
1
or
fund_type
==
2
:
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT fund_short_name FROM fund_info WHERE id='{}'"
.
format
(
fund
)
# df = pd.read_sql(sql, con)
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
if
len
(
df
)
==
0
:
with
TAMP_SQL
(
tamp_product_engine
)
as
tamp_product
:
tamp_product_session
=
tamp_product
.
session
sql
=
"SELECT fund_short_name FROM fund_info WHERE id='{}'"
.
format
(
fund
)
# df = pd.read_sql(sql, con)
cur
=
tamp_product_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
return
str
(
df
.
values
[
0
][
0
])
else
:
with
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_fund_session
=
tamp_fund
.
session
sql
=
"SELECT fund_name FROM ifa_imported_fund_info WHERE id='{}'"
.
format
(
fund
)
# df = pd.read_sql(sql, con)
cur
=
tamp_fund_session
.
execute
(
sql
)
data
=
cur
.
fetchall
()
df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_short_name'
])
return
str
(
df
.
values
[
0
][
0
])
except
:
return
"-1"
# 获取排名信息
# 获取排名信息
fund_rank
=
get_fund_rank
()
fund_rank
=
get_fund_rank
()
tx_fund_rank
=
get_fund_rank
(
0
)
tx_fund_rank
=
get_fund_rank
(
0
)
...
@@ -1016,7 +1057,7 @@ class PortfolioDiagnose(object):
...
@@ -1016,7 +1057,7 @@ class PortfolioDiagnose(object):
return
ret
,
old_return_compare_result
,
old_indicator_compare
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
,
fund_type_dict
):
try
:
try
:
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"
]
...
@@ -1038,20 +1079,45 @@ class PortfolioDiagnose(object):
...
@@ -1038,20 +1079,45 @@ class PortfolioDiagnose(object):
# propose_fund_id_list = list(propose_fund_return.columns)
# propose_fund_id_list = list(propose_fund_return.columns)
propose_fund_id_list
=
list
(
self
.
proposal_fund
)
propose_fund_id_list
=
list
(
self
.
proposal_fund
)
# propose_fund_id_list.remove("return")
# propose_fund_id_list.remove("return")
with
TAMP_SQL
(
tamp_product_engine
)
as
tamp_product
:
if
fund_tye_dict
is
None
:
with
TAMP_SQL
(
tamp_product_engine
)
as
tamp_product
,
TAMP_SQL
(
tamp_fund_engine
)
as
tamp_fund
:
tamp_product_session
=
tamp_product
.
session
tamp_product_session
=
tamp_product
.
session
sql_product
=
"select distinct `id`, `fund_short_name`, `nav_frequency`, `substrategy` from `fund_info`"
tamp_fund_session
=
tamp_fund
.
session
sql_product
=
"""select distinct `id`, `fund_short_name`, `nav_frequency`, `substrategy` from `fund_info` where `id` in {}"""
.
format
(
str
(
tuple
(
propose_fund_id_list
)))
cur
=
tamp_product_session
.
execute
(
sql_product
)
cur
=
tamp_product_session
.
execute
(
sql_product
)
cur2
=
tamp_fund_session
.
execute
(
sql_product
)
data
=
cur
.
fetchall
()
data
=
cur
.
fetchall
()
product_df
=
pd
.
DataFrame
(
list
(
data
),
columns
=
[
'fund_id'
,
'fund_name'
,
'freq'
,
'substrategy'
])
data2
=
cur2
.
fetchall
()
product_df
=
pd
.
DataFrame
(
list
(
data
)
+
list
(
data2
),
columns
=
[
'fund_id'
,
'fund_name'
,
'freq'
,
'substrategy'
])
propose_fund_df
=
product_df
[
product_df
[
"fund_id"
]
.
isin
(
propose_fund_id_list
)]
propose_fund_df
=
product_df
[
product_df
[
"fund_id"
]
.
isin
(
propose_fund_id_list
)]
for
index
,
row
in
propose_fund_df
.
iterrows
():
if
math
.
isnan
(
row
[
"freq"
]):
propose_fund_df
.
loc
[
index
,
"freq"
]
=
2
if
math
.
isnan
(
row
[
"substrategy"
]):
propose_fund_df
.
loc
[
index
,
"substrategy"
]
=
5010
# 基金名称,策略分级
# 基金名称,策略分级
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
=
[
dict_substrategy
(
propose_fund_df
[
propose_fund_df
[
"fund_id"
]
==
fund_id
][
"substrategy"
]
.
values
[
0
])
for
propose_fund_id_strategy_name_list
=
[
get_substrategy_name
(
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
))]
else
:
propose_fund_id_name_list
=
[
get_fund_name
(
fund_id
,
fund_tye_dict
[
fund_id
])
.
values
[
0
][
0
]
for
fund_id
in
propose_fund_id_list
]
propose_fund_id_strategy_name_list
=
[
get_substrategy_name
(
get_fund_substrategy
(
fund_id
,
fund_tye_dict
[
fund_id
]))
for
fund_id
in
propose_fund_id_list
]
propose_fund_asset
=
[
round
(
portfolio_diagnose
.
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
],
...
@@ -1214,7 +1280,7 @@ class PortfolioDiagnose(object):
...
@@ -1214,7 +1280,7 @@ class PortfolioDiagnose(object):
if
fund_id_type
==
0
:
if
fund_id_type
==
0
:
rank_df
=
tx_fund_rank
rank_df
=
tx_fund_rank
else
:
else
:
rank_df
=
tx_
fund_rank
rank_df
=
fund_rank
z_score
=
search_rank
(
rank_df
,
fund_id
,
metric
=
'z_score'
)
z_score
=
search_rank
(
rank_df
,
fund_id
,
metric
=
'z_score'
)
total_level
=
np
.
select
([
z_score
>=
80
,
total_level
=
np
.
select
([
z_score
>=
80
,
...
...
app/service/result_service_v2.py
View file @
37f8c2ae
...
@@ -21,8 +21,8 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor):
...
@@ -21,8 +21,8 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor):
total_result_data
=
{}
total_result_data
=
{}
group_result_data
=
{}
group_result_data
=
{}
def
__init__
(
self
,
user_id
,
customer_id
):
def
__init__
(
self
,
user_id
,
customer_id
,
end_date
=
str
(
datetime
.
datetime
.
now
()
.
date
())
):
super
()
.
__init__
(
user_id
,
customer_id
)
super
()
.
__init__
(
user_id
,
customer_id
,
end_date
=
end_date
)
# 组合结果数据
# 组合结果数据
def
calculate_group_result_data
(
self
):
def
calculate_group_result_data
(
self
):
...
@@ -480,10 +480,10 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor):
...
@@ -480,10 +480,10 @@ class UserCustomerResultAdaptor(UserCustomerDataAdaptor):
else
:
else
:
last_month_cnav
=
float
(
last_month_cnav_serise
.
values
[
-
1
])
last_month_cnav
=
float
(
last_month_cnav_serise
.
values
[
-
1
])
temp_profit
=
float
(
cal_month_cnav_result
[
cur_fund_id
+
"_earn"
]
.
sum
())
temp_profit
=
float
(
cal_month_cnav_result
[
cur_fund_id
+
"_earn"
]
.
sum
())
fund_hoding_info
[
"profit"
]
=
round
(
float
(
row
[
"confirm_share"
])
*
(
fund_basic_info
[
"cur_cnav"
]
-
last_month_cnav
)
/
10000
,
2
)
fund_hoding_info
[
"profit"
]
=
round
(
temp_profit
/
10000
,
2
)
temp_profit_ratio
=
(
fund_basic_info
[
"cur_cnav"
]
-
last_month_cnav
)
/
last_month_cnav
temp_profit_ratio
=
(
fund_basic_info
[
"cur_cnav"
]
-
last_month_cnav
)
/
last_month_cnav
# 当月收益率
# 当月收益率
fund_hoding_info
[
"month_return_ratio"
]
=
"
%.2
f"
%
round
(
temp_profit
/
temp_
market_values
*
100
,
2
)
fund_hoding_info
[
"month_return_ratio"
]
=
"
%.2
f"
%
round
(
temp_profit
/
temp_
cost
*
100
,
2
)
# fund_hoding_info["month_return_ratio"] = "%.2f" % round(temp_profit_ratio * 100, 2)
# fund_hoding_info["month_return_ratio"] = "%.2f" % round(temp_profit_ratio * 100, 2)
# 累积收益
# 累积收益
cum_profit
=
float
(
p_result_cnav_data
[
cur_fund_id
+
"_earn"
]
.
sum
())
cum_profit
=
float
(
p_result_cnav_data
[
cur_fund_id
+
"_earn"
]
.
sum
())
...
...
app/templates/v2/monthReportV2.1.html
View file @
37f8c2ae
...
@@ -141,6 +141,13 @@
...
@@ -141,6 +141,13 @@
font-weight
:
bold
;
font-weight
:
bold
;
}
}
.box0
.cover_title
.cover_title_text
.cover_date
.cover_time
.cover_time_span
{
font-size
:
22px
;
line-height
:
48px
;
color
:
#ffffff
;
font-weight
:
bold
;
}
.box_line
{
.box_line
{
height
:
15px
;
height
:
15px
;
background
:
#F1F1F1
;
background
:
#F1F1F1
;
...
@@ -976,7 +983,7 @@
...
@@ -976,7 +983,7 @@
{{cover_title2}}
{{cover_title2}}
<div
class=
"cover_date"
>
<div
class=
"cover_date"
>
<div
class=
"cover_time"
>
<div
class=
"cover_time"
>
{{
year_month}}
{{
end_date}}
<div
class=
"cover_time_span"
>
最新净值日期: {{latest_worth_day}}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
...
...
app/utils/jinjia2html_v2.py
View file @
37f8c2ae
...
@@ -23,8 +23,9 @@ from app.utils.radar_chart import gen_radar_chart
...
@@ -23,8 +23,9 @@ from app.utils.radar_chart import gen_radar_chart
class
DataIntegrate
:
class
DataIntegrate
:
def
__init__
(
self
,
ifa_id
=
'USER_INFO15917850824287'
,
customer_id
=
'6716613802534121472'
,
pdf_name
=
str
(
uuid
.
uuid4
())
+
'.pdf'
,
type
=
1
):
def
__init__
(
self
,
ifa_id
=
'USER_INFO15917850824287'
,
customer_id
=
'6716613802534121472'
,
self
.
user_customer
=
UserCustomerResultAdaptor
(
ifa_id
,
customer_id
)
pdf_name
=
str
(
uuid
.
uuid4
())
+
'.pdf'
,
type
=
1
,
end_date
=
str
(
datetime
.
now
()
.
date
())):
self
.
user_customer
=
UserCustomerResultAdaptor
(
ifa_id
,
customer_id
,
end_date
=
end_date
)
self
.
customer_name
=
self
.
user_customer
.
customer_real_name
self
.
customer_name
=
self
.
user_customer
.
customer_real_name
self
.
ifa_name
=
self
.
user_customer
.
ifa_real_name
self
.
ifa_name
=
self
.
user_customer
.
ifa_real_name
# self.pdf_name = self.ifa_name + "_" + self.customer_name + "_" + '.pdf'
# self.pdf_name = self.ifa_name + "_" + self.customer_name + "_" + '.pdf'
...
@@ -50,7 +51,9 @@ class DataIntegrate:
...
@@ -50,7 +51,9 @@ class DataIntegrate:
# 分组和计算个基点评以及新增基金等结果
# 分组和计算个基点评以及新增基金等结果
def
get_group_result
(
self
):
def
get_group_result
(
self
):
for
group_name
,
group_result
in
self
.
d
.
items
():
for
group_name
,
group_result
in
self
.
d
.
items
():
portfolio_diagnose
=
self
.
get_portfolio_diagnose
(
group_result
[
"fund_id_list"
],
invest_amount
=
group_result
[
"total_cost"
])
portfolio_diagnose
=
self
.
get_portfolio_diagnose
(
group_result
[
"fund_id_list"
],
invest_amount
=
group_result
[
"total_cost"
],
weight_dict
=
group_result
[
"weight_result"
])
cur_group_portfolio_result
=
{
cur_group_portfolio_result
=
{
'new_correlation'
:
[],
'new_correlation'
:
[],
'propose_fund_data_list'
:
[],
'propose_fund_data_list'
:
[],
...
@@ -84,17 +87,23 @@ class DataIntegrate:
...
@@ -84,17 +87,23 @@ class DataIntegrate:
self
.
all_folio_result
[
group_name
]
=
cur_group_portfolio_result
self
.
all_folio_result
[
group_name
]
=
cur_group_portfolio_result
def
get_portfolio_diagnose
(
self
,
portfolio
,
client_type
=
1
,
invest_amount
=
10000000
):
def
get_portfolio_diagnose
(
self
,
portfolio
,
client_type
=
1
,
invest_amount
=
10000000
,
weight_dict
=
{}
):
if
invest_amount
<
10000000
:
if
invest_amount
<
10000000
:
invest_amount
=
10000000
invest_amount
=
10000000
folio_fund_dict
=
{}
folio_fund_dict
=
{}
folio_fund_list
=
[]
folio_fund_weight_list
=
[]
for
fd
in
portfolio
:
for
fd
in
portfolio
:
folio_fund_list
.
append
(
fd
)
folio_fund_weight_list
.
append
(
weight_dict
[
fd
])
folio_fund_dict
[
fd
]
=
self
.
user_customer
.
all_fund_type_dict
[
fd
]
folio_fund_dict
[
fd
]
=
self
.
user_customer
.
all_fund_type_dict
[
fd
]
portfolio_diagnose
=
PortfolioDiagnose
(
client_type
=
client_type
,
portfolio
=
folio_fund_dict
,
portfolio_diagnose
=
PortfolioDiagnose
(
client_type
=
client_type
,
portfolio
=
folio_fund_dict
,
invest_amount
=
float
(
invest_amount
),
invest_amount
=
float
(
invest_amount
),
start_date
=
self
.
user_customer
.
start_date
)
start_date
=
self
.
user_customer
.
start_date
)
if
self
.
type
==
2
:
if
self
.
type
==
2
:
portfolio_diagnose
.
optimize
()
portfolio_diagnose
.
proposal_customize
(
folio_fund_list
,
folio_fund_weight_list
,
folio_fund_dict
)
# portfolio_diagnose.optimize()
return
portfolio_diagnose
return
portfolio_diagnose
# 全部数据综述结果
# 全部数据综述结果
...
@@ -166,8 +175,8 @@ class DataIntegrate:
...
@@ -166,8 +175,8 @@ class DataIntegrate:
"""新收益比较,调仓建议"""
"""新收益比较,调仓建议"""
cur_group_portfolio_result
[
"suggestions_result"
],
cur_group_portfolio_result
[
"suggestions_result_asset"
],
\
cur_group_portfolio_result
[
"suggestions_result"
],
cur_group_portfolio_result
[
"suggestions_result_asset"
],
\
cur_group_portfolio_result
[
"return_compare_data"
],
\
cur_group_portfolio_result
[
"return_compare_data"
],
\
cur_group_portfolio_result
[
"indicator_compare"
],
cur_group_portfolio_result
[
"new_group_evaluation"
]
=
portfolio_diagnose
.
new_evaluation
(
folio
,
self
.
d
,
cur_group_portfolio_result
[
"indicator_compare"
],
cur_group_portfolio_result
[
"new_group_evaluation"
]
=
\
self
.
user_customer
)
portfolio_diagnose
.
new_evaluation
(
folio
,
self
.
d
,
self
.
user_customer
,
self
.
user_customer
.
all_fund_type_dict
)
cur_group_portfolio_result
[
"return_compare_pic"
]
=
draw_combination_chart
(
cur_group_portfolio_result
[
"return_compare_data"
][
"xlabels"
],
cur_group_portfolio_result
[
"return_compare_pic"
]
=
draw_combination_chart
(
cur_group_portfolio_result
[
"return_compare_data"
][
"xlabels"
],
cur_group_portfolio_result
[
"return_compare_data"
][
"new_combination"
],
cur_group_portfolio_result
[
"return_compare_data"
][
"new_combination"
],
...
@@ -237,6 +246,7 @@ class DataIntegrate:
...
@@ -237,6 +246,7 @@ class DataIntegrate:
# 全局数据
# 全局数据
'customer_name'
:
self
.
customer_name
,
'customer_name'
:
self
.
customer_name
,
'year_month'
:
datetime
.
now
()
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'year_month'
:
datetime
.
now
()
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'end_date'
:
self
.
user_customer
.
end_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'valueSex'
:
self
.
user_customer
.
valueSex
,
'valueSex'
:
self
.
user_customer
.
valueSex
,
'month'
:
self
.
user_customer
.
month_start_date
.
strftime
(
"
%
m"
),
'month'
:
self
.
user_customer
.
month_start_date
.
strftime
(
"
%
m"
),
'start_date'
:
self
.
user_customer
.
start_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'start_date'
:
self
.
user_customer
.
start_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
...
@@ -271,7 +281,8 @@ class DataIntegrate:
...
@@ -271,7 +281,8 @@ class DataIntegrate:
data
=
{
data
=
{
# 全局数据
# 全局数据
'customer_name'
:
self
.
customer_name
,
'customer_name'
:
self
.
customer_name
,
'year_month'
:
self
.
user_customer
.
end_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'year_month'
:
datetime
.
now
()
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'end_date'
:
self
.
user_customer
.
end_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'valueSex'
:
self
.
user_customer
.
valueSex
,
'valueSex'
:
self
.
user_customer
.
valueSex
,
'month'
:
self
.
user_customer
.
month_start_date
.
strftime
(
"
%
m"
),
'month'
:
self
.
user_customer
.
month_start_date
.
strftime
(
"
%
m"
),
'start_date'
:
self
.
user_customer
.
start_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
'start_date'
:
self
.
user_customer
.
start_date
.
strftime
(
"
%
Y-
%
m-
%
d"
),
...
@@ -312,9 +323,9 @@ class DataIntegrate:
...
@@ -312,9 +323,9 @@ class DataIntegrate:
template
=
env
.
get_template
(
'/v2/monthReportV2.1.html'
)
# 获取一个模板文件
template
=
env
.
get_template
(
'/v2/monthReportV2.1.html'
)
# 获取一个模板文件
monthReport_html
=
template
.
render
(
self
.
data
)
.
replace
(
'None'
,
'none'
)
# 渲染
monthReport_html
=
template
.
render
(
self
.
data
)
.
replace
(
'None'
,
'none'
)
# 渲染
# 保存 monthReport_html
# 保存 monthReport_html
#
save_file = "app/pdf/monthReport.html"
save_file
=
"app/pdf/monthReport.html"
#
with open(save_file, 'w', encoding="utf-8") as f:
with
open
(
save_file
,
'w'
,
encoding
=
"utf-8"
)
as
f
:
#
f.write(monthReport_html)
f
.
write
(
monthReport_html
)
# save_file = "app/html/v2/monthReportV2.html"
# save_file = "app/html/v2/monthReportV2.html"
# with open(save_file, 'w', encoding="utf-8") as f:
# with open(save_file, 'w', encoding="utf-8") as f:
...
...
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