项目结构调整,模版填充

parent 39a9a9d0
......@@ -42,8 +42,7 @@ tamp_order_engine = create_engine(
port=config[env]['MySQL']['port'],
user=config[env]['MySQL']['user'],
password=config[env]['MySQL']['password'],
charset="utf8"),
echo=True
charset="utf8")
)
tamp_user_engine = create_engine(
......@@ -54,8 +53,7 @@ tamp_user_engine = create_engine(
user=config[env]['MySQL']['user'],
password=config[env]['MySQL']['password'],
charset="utf8"
),
echo=True
)
)
tamp_fund_engine = create_engine(
......@@ -66,8 +64,7 @@ tamp_fund_engine = create_engine(
user=config[env]['MySQL']['user'],
password=config[env]['MySQL']['password'],
charset="utf8"
),
echo=True
)
)
# tamp_product_session = scoped_session(sessionmaker(bind=tamp_product_engine))()
# tamp_order_session = scoped_session(sessionmaker(bind=tamp_order_engine))()
......
......@@ -821,10 +821,10 @@ portfolio = ['HF00002JJ2', 'HF00005DBQ', 'HF0000681Q', 'HF00006693', 'HF00006AZF
portfolio_diagnose = PortfolioDiagnose(client_type=1, portfolio=portfolio, invest_amount=10000000)
portfolio_diagnose.optimize()
if __name__ == '__main__':
print(portfolio_diagnose.single_fund_radar())
print(portfolio_diagnose.propose_fund_radar())
print(portfolio_diagnose.old_portfolio_evaluation())
print('旧组合相关性:', portfolio_diagnose.old_correlation)
print('新组合相关性:', portfolio_diagnose.new_correlation)
# print(portfolio_diagnose.single_fund_radar())
# print(portfolio_diagnose.propose_fund_radar())
# print(portfolio_diagnose.old_portfolio_evaluation())
# print('旧组合相关性:', portfolio_diagnose.old_correlation)
# print('新组合相关性:', portfolio_diagnose.new_correlation)
print('旧组合个基评价:', portfolio_diagnose.old_portfolio_evaluation())
print('新组合个基评价:', portfolio_diagnose.propose_fund_evaluation())
......@@ -2500,12 +2500,14 @@
</div>
</div>
<div class="self_description">
{% for one in single_fund.evaluation%}
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
{{single_fund.evaluation}}
{{one}}
</div>
</div>
{% endfor %}
</div>
</div>
</td>
......@@ -2518,539 +2520,17 @@
</table>
</li>
{% endfor %}
<li class="self_item">
<table>
<tr>
<td style="padding: 0;text-align: left;vertical-align: middle;">
<div class="self_item_left">
<div class="self_header">
<div class="self_title">
远澜银杏 1 号
<div class="self_title_tri"></div>
</div>
<div class="self_type green">
保留
</div>
</div>
<div class="self_description">
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
1、该基金整体表现
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
收益能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
回撤控制能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
风险收益比例
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>;
</div>
</div>
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
2、在收益方面,该基金年化收益能力
<span class="self_description_red">高于</span>/
<span class="self_description_green">持平</span>/
<span class="self_description_green">低于</span>
同类基金平均水平,有x%区间跑赢大盘/指数,绝对收益能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
</div>
</div>
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
3、在风险方面,该基金抵御风险能力优秀,在同类基金中处于中等水平,最大回撤为x%,低于同类基金平均水平;
</div>
</div>
</div>
</div>
</td>
<td style="padding: 0;text-align: left;vertical-align: middle;">
<div class="self_item_right">
<img src="./img/logo-blue.png" alt="" class="self_img">
</div>
</td>
</tr>
</table>
</li>
</ul>
</div>
</div>
<!-- 优化组合建议1 -->
<div class="mr_block5 have_sub_tb">
<!--标题-->
<div class="head_wrap head_yellow1 clearfix">
<div class="head_title fl">
10月综述 -- 优化组合建议1
</div>
<div class="head_logo_wrap fr">
<img src="./img/logo-blue.png" alt="">
<span class="com_brand_line"></span>
<span class="com_brand_name">
飞度工作室
</span>
</div>
</div>
<div class="optimization_content">
<div class="transfer_table">
<div class="transfer_head clearfix">
<div class="transfer_title fl">
【调仓建议】
</div>
<div class="transfer_time fr">
截止日:最新净值日(2020-11-05)
</div>
</div>
<table border="1">
<tr>
<th>投资策略</th>
<th>基金简称</th>
<th>优化前(万元)</th>
<th>优化后(万元)</th>
</tr>
<tr>
<td rowspan="3">宏观策略</td>
<td>半夏宏观对冲</td>
<td class="font_red">200</td>
<td class="font_green">1000</td>
</tr>
<tr>
<td>半夏宏观对冲</td>
<td class="font_red">200</td>
<td class="font_green">1000</td>
</tr>
<tr>
<td>半夏宏观对冲</td>
<td class="font_red">200</td>
<td class="font_green">1000</td>
</tr>
<tr>
<td colspan="2" class="back_gray font_bold">总市值(万元)</td>
<td class="font_bold">1200</td>
<td class="font_bold">1000</td>
</tr>
</table>
</div>
<div class="profit_chart clearfix">
<div class="profit_chart_item fl">
<div class="profit_chart_title">
【收益比较】
</div>
<div class="profit_chart_graphic">
<img src="./img/logo-blue.png" alt="" class="profit_chart_img">
</div>
</div>
<div class="profit_chart_item fr">
<div class="profit_chart_title">
【相关性分析】
</div>
<div class="profit_chart_graphic relative_chart">
<div class="rc_chart clearfix">
<div class="rcc_left fl">
<table border="1" style="border-color: transparent;margin-right: 20px;">
<tr>
<td>
<span class="rcc_index">1</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">2</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">3</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">4</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">5</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">6</span>
</td>
</tr>
<tr>
<td>
<span class="rcc_index">7</span>
</td>
</tr>
</table>
</div>
<div class="rcc_right fr">
<table border="1">
<tr>
<td>
<span class="rcc_index">1</span>
</td>
<td class="level_color1">0.56</td>
<td class="level_color2">0.56</td>
<td class="level_color3">0.56</td>
<td class="level_color4">0.56</td>
<td class="level_color5">0.56</td>
<td class="level_color6">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>
<span class="rcc_index">2</span>
</td>
<td class="level_color1">0.56</td>
<td class="level_color2">0.56</td>
<td class="level_color3">0.56</td>
<td class="level_color4">0.56</td>
<td class="level_color5">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>0.56</td>
<td>
<span class="rcc_index">3</span>
</td>
<td class="level_color1">0.56</td>
<td class="level_color2">0.56</td>
<td class="level_color3">0.56</td>
<td class="level_color4">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>
<span class="rcc_index">4</span>
</td>
<td class="level_color1">0.56</td>
<td class="level_color2">0.56</td>
<td class="level_color3">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>
<span class="rcc_index">5</span>
</td>
<td class="level_color1">0.56</td>
<td class="level_color2">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>
<span class="rcc_index">6</span>
</td>
<td class="level_color1">0.56</td>
</tr>
<tr>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>0.56</td>
<td>
<span class="rcc_index">7</span>
</td>
</tr>
</table>
</div>
</div>
<div class="rc_tooltip">
<div class="rct_color clearfix">
<div class="rct_color_item fl level_color1"></div>
<div class="rct_color_item fl level_color2"></div>
<div class="rct_color_item fl level_color3"></div>
<div class="rct_color_item fl level_color4"></div>
<div class="rct_color_item fl level_color5"></div>
<div class="rct_color_item fl level_color6"></div>
</div>
<div class="rct_number clearfix">
<div class="rtc_number_item fl">1.00</div>
<div class="rtc_number_item fl">0.50</div>
<div class="rtc_number_item fl">0.25</div>
<div class="rtc_number_item fl">0.00</div>
<div class="rtc_number_item fl">-0.25</div>
<div class="rtc_number_item fl">-0.50</div>
<div class="rtc_number_item fl">-1.00</div>
</div>
</div>
<div class="rc_label clearfix">
<div class="rcl_item fl">
<div class="rcl_item_number">
1
</div>
<div class="rcl_item_name">
基金名称1
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
2
</div>
<div class="rcl_item_name">
基金名称2
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
3
</div>
<div class="rcl_item_name">
基金名称3
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
4
</div>
<div class="rcl_item_name">
基金名称4
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
5
</div>
<div class="rcl_item_name">
基金名称5
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
6
</div>
<div class="rcl_item_name">
基金名称6
</div>
</div>
<div class="rcl_item fl">
<div class="rcl_item_number">
7
</div>
<div class="rcl_item_name">
基金名称7
</div>
</div>
</div>
</div>
</div>
</div>
<div class="aim_table">
<div class="aim_head clearfix">
<div class="aim_title fl">
【指标对比】
</div>
<div class="aim_time fr">
截止日:最新净值日(2020-11-05)
</div>
</div>
<table border="1">
<tr>
<th>类型</th>
<th>区间收益(%)</th>
<th>年化收益(%)</th>
<th>波动率(%)</th>
<th>最大回撤(%)</th>
<th>夏普比率</th>
</tr>
<tr class="back_yellow1">
<td>建议优化组合</td>
<td>5.75</td>
<td>0.40</td>
<td>2.29</td>
<td>2.15</td>
<td>3.05</td>
</tr>
<tr class="back_yellow2">
<td>建议优化组合</td>
<td>5.75</td>
<td>0.40</td>
<td>2.29</td>
<td>2.15</td>
<td>3.05</td>
</tr>
<tr>
<td>现有持仓组合</td>
<td>5.75</td>
<td>0.40</td>
<td>2.29</td>
<td>2.15</td>
<td>3.05</td>
</tr>
</table>
<div class="aim_foot">
注:以上指标自持仓首日开始计算,结果仅供参考,如果持仓时间过短会造成指标失真的情况。
</div>
</div>
<div class="target_all">
<div class="all_title">
总体点评
<div class="all_tri"></div>
</div>
<div class="all_content">
<div class="all_item">
<div class="all_dot"></div>
<div class="all_text">
在保留综合性基金(富国创新,鹏华匠心,汇添富中盘)并增配申毅套利基金后,整体组合的波动率大幅降低,最大回撤从26%降到不足4%,年化收益提升1个点。
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 优化组合建议1--新增基金 -->
<div class="mr_block6 have_sub_tb">
<!--标题-->
<div class="head_wrap head_yellow1 clearfix">
<div class="head_title fl">
优化组合建议1 -- 新增基金
</div>
<div class="head_logo_wrap fr">
<img src="./img/logo-blue.png" alt="">
<span class="com_brand_line"></span>
<span class="com_brand_name">
飞度工作室
</span>
</div>
</div>
<div class="self_content">
<div class="self_item">
<table>
<tr>
<td style="padding: 0;text-align: left;vertical-align: middle;">
<div class="self_item_left">
<div class="self_header">
<div class="self_title">
远澜银杏 1 号
<div class="self_title_tri"></div>
</div>
</div>
<div class="self_description">
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
1、该基金整体表现
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
收益能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
回撤控制能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
风险收益比例
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>;
</div>
</div>
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
2、在收益方面,该基金年化收益能力
<span class="self_description_red">高于</span>/
<span class="self_description_green">持平</span>/
<span class="self_description_green">低于</span>
同类基金平均水平,有x%区间跑赢大盘/指数,绝对收益能力
<span class="self_description_red">优秀</span>/
<span class="self_description_red">良好</span>/
<span class="self_description_green">一般</span>/
<span class="self_description_green">合格</span>/
<span class="self_description_green">较差</span>
</div>
</div>
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
3、在风险方面,该基金抵御风险能力优秀,在同类基金中处于中等水平,最大回撤为x%,低于同类基金平均水平;
</div>
</div>
</div>
</div>
</td>
<td style="padding: 0;text-align: left;vertical-align: middle;">
<div class="self_item_right">
<img src="./img/logo-blue.png" alt="" class="self_img">
</div>
</td>
</tr>
</table>
</div>
</div>
</div>
<!-- 优化组合建议2 -->
<div class="mr_block5 have_sub_tb">
<!--标题-->
<div class="head_wrap head_yellow2 clearfix">
<div class="head_title fl">
10月综述 -- 优化组合建议2
10月综述 -- 优化组合建议1
</div>
<div class="head_logo_wrap fr">
<img src="./img/logo-blue.png" alt="">
......@@ -3277,7 +2757,7 @@
<!--标题-->
<div class="head_wrap head_yellow2 clearfix">
<div class="head_title fl">
优化组合建议2 -- 新增基金
优化组合建议1 -- 新增基金
</div>
<div class="head_logo_wrap fr">
<img src="./img/logo-blue.png" alt="">
......@@ -3302,12 +2782,14 @@
</div>
</div>
<div class="self_description">
{{for one in single_fund.evaluation}}
<div class="self_description_item">
<div class="self_description_dot"></div>
<div class="self_description_text">
{{single_fund.evaluation}}
{{one}}
</div>
</div>
{% endfor %}
</div>
</div>
</td>
......
import time
from jinja2 import PackageLoader, Environment
from app.service.portfolio_diagnose import portfolio_diagnose
from app.service.result_service import UserCustomerResultAdaptor
import numpy as np
# 准备数据
from app.utils.draw import draw_month_return_chart, draw_contribution_chart
from app.utils.radar_chart import gen_radar_chart
class DataIntegrate:
def __init__(self, ifa_id='USER_INFO15914346866762', customer_id='202009281545001'):
self.user_customer = UserCustomerResultAdaptor(ifa_id, customer_id)
self.df = self.user_customer.calculate_total_data()
self.d = self.user_customer.calculate_group_result_data()
# 组合数据
self.group_result = self.d["default"]
# 几月综述部分
self.get_summarize()
# 月度回报
self.get_month_return()
# 旧持仓组合点评
self.comments_on_position_portfolio()
# 贡献分解
self.contribution_deco()
# 个基点评
self.single_fund_comment()
# 旧相关性
self.get_old_correlation()
# 新增基金
self.propose_fund()
# 目标与业绩
self.objectives_performance(self.group_result)
# 渲染模版
self.render_data()
def get_summarize(self):
"""几月综述部分."""
self.total_cost = self.df["total_cost"]/10000
self.now_yield = round((self.df['cumulative_return']-1)*100,2)
self.index_yield = round((self.df["index_result"]["return_ratio"]-1)*100, 2)
self.now_withdrawal = round(self.df["max_drawdown"][0]*100,2)
self.index_withdrawal = round(self.df["index_result"]["max_drawdown"][0]*100, 2)
def get_month_return(self):
"""月度回报."""
xlabels, product_list, cumulative = self.user_customer.get_month_return_chart()
self.monthly_return_performance_pic = draw_month_return_chart(xlabels, product_list, cumulative)
def comments_on_position_portfolio(self):
"""旧持仓组合点评."""
self.old_evaluation = portfolio_diagnose.old_evaluation('default', self.d, self.user_customer)
def contribution_deco(self):
"""贡献分解."""
g_data = self.group_result["contribution_decomposition"]
self.contribution_decomposition = draw_contribution_chart(g_data['xlabels'], g_data['product_list'], g_data['cumulative'])
def single_fund_comment(self):
"""个基点评."""
self.single_fund_data_list = []
portfolio_evaluation = portfolio_diagnose.old_portfolio_evaluation()
radar_chart_data = portfolio_diagnose.single_fund_radar()
for i in range(len(portfolio_evaluation)):
self.single_fund_data_list.append({
'fund_name': portfolio_evaluation[i]['name'],
'status': '保留',
'evaluation': portfolio_evaluation[i]['data'],
'radar_chart_path': gen_radar_chart(radar_chart_data[i])
})
# 调仓建议
# 收益比较
def get_old_correlation(self):
"""旧相关性分析."""
old_correlation = portfolio_diagnose.old_correlation
old_correlation_columns = old_correlation.columns.tolist()
old_correlation_values = old_correlation.values.tolist()
self.old_correlation = list(zip(range(1, len(old_correlation_columns)+1), old_correlation_columns, old_correlation_values))
def propose_fund(self):
"""新增基金"""
# 优化组合建议1 -- 新增基金
self.propose_fund_data_list = []
propose_fund_evaluation = portfolio_diagnose.propose_fund_evaluation()
propose_radar_chart_data = portfolio_diagnose.propose_fund_radar()
for i in range(len(propose_fund_evaluation)):
self.propose_fund_data_list.append({
'fund_name': propose_fund_evaluation[i]['name'],
'status': '保留',
'evaluation': propose_fund_evaluation[i]['data'],
'radar_chart_path': gen_radar_chart(propose_radar_chart_data[i])
})
def objectives_performance(self, group_result):
"""目标与业绩"""
self.now_month_income = int(group_result["cur_month_profit"]) # 本月收益
self.now_year_income = int(group_result["cur_year_profit"]) # 今年累计收益
self.totoal_rate_of_return = round((group_result['cumulative_return']-1)*100, 2) # 累计收益率
self.month_rise = round(group_result["cur_month_profit_ratio"]*100, 2) # 本月涨幅
self.year_totoal_rate_of_return = round(group_result["cur_year_profit_ratio"]*100, 2) # 今年累计收益率
self.annualised_return = round(group_result["return_ratio_year"]*100, 2) # 年化收益率
self.volatility = round(group_result["volatility"]*100, 2)
self.max_withdrawal = round(group_result["max_drawdown"][0]*100, 2)
self.sharpe_ratio = round(group_result["sharpe"], 2)
self.cost_of_investment = int(group_result["total_cost"]) # 投资成本
self.final_balance = int(group_result["total_cost"] + group_result["cumulative_profit"]) # 期末资产
self.total_profit = int(group_result["cumulative_profit"]) # 累计盈利
self.index_section_return = round((group_result["index_result"]["return_ratio"]-1)*100, 2)
self.index_annualised_return = round(group_result["index_result"]["return_ratio_year"]*100, 2) # 年化收益率
self.index_volatility = round(group_result["index_result"]["volatility"]*100, 2)
self.index_max_withdrawal = round(group_result["index_result"]["max_drawdown"][0]*100, 2)
self.index_sharpe_ratio = round(group_result["index_result"]["sharpe"], 2)
self.group_nav_info = group_result["group_nav_info"]
self.group_hoding_info = group_result["group_hoding_info"]
def render_data(self):
# 全部数据
data = {'customer_name': '成龙', 'customer_gender': '女',
'year_month': '2020年10月', 'ifa_company': '飞度工作室',
'title': '10月综述', 'brand_name': '飞度工作室',
'customer_old': 42, 'customer_level': '平衡型',
'position_years': '5年', 'planned_allocation_amount': 2000.00,
'now_allocation_amount': self.total_cost, 'now_yield': self.now_yield, 'index_yield': self.index_yield,
'expected_yield': 20,
'now_withdrawal': self.now_withdrawal, 'index_withdrawal': self.index_withdrawal, 'expected_withdrawal': 20,
'now_year_income': self.now_year_income, 'now_month_income': self.now_month_income,
'totoal_rate_of_return': self.totoal_rate_of_return,
'month_rise': self.month_rise, 'year_totoal_rate_of_return': self.year_totoal_rate_of_return,
'annualised_return': self.annualised_return, 'cost_of_investment': self.cost_of_investment,
'final_balance': self.final_balance, 'total_profit': self.total_profit,
'latest_worth_day': '2020-11-05',
'index_comparison': {'section_return': self.totoal_rate_of_return, 'annualized_returns': self.annualised_return,
'volatility': self.volatility, 'max_withdrawal': self.max_withdrawal,
'sharpe_ratio': self.sharpe_ratio},
'index_comparison_500': {'section_return': self.index_section_return,
'annualized_returns': self.index_annualised_return,
'volatility': self.index_volatility, 'max_withdrawal': self.index_max_withdrawal,
'sharpe_ratio': self.index_sharpe_ratio},
'monthly_return_performance_pic': self.monthly_return_performance_pic,
'group_nav_info': self.group_nav_info,
'group_hoding_info': self.group_hoding_info,
'old_evaluation': self.old_evaluation,
'contribution_decomposition': self.contribution_decomposition,
'single_fund_data_list': self.single_fund_data_list,
'old_correlation': self.old_correlation,
'propose_fund_data_list': self.propose_fund_data_list
}
# 开始渲染html模板
env = Environment(loader=PackageLoader('app', 'templates')) # 创建一个包加载器对象
template = env.get_template('monthReport.html') # 获取一个模板文件
monthReport_html = template.render(data) # 渲染
# 保存 monthReport_html
save_file = "app/html/monthReport.html"
with open(save_file, 'w', encoding="utf-8") as f:
f.write(monthReport_html)
if __name__ == '__main__':
start = time.time()
DataIntegrate()
print('耗时{}秒'.format(round(time.time()-start, 2)))
# -*- encoding: utf-8 -*-
# -----------------------------------------------------------------------------
# @File Name : html_to_pdf.py
# @Time : 2020/11/19 上午11:07
# @Author : X. Peng
# @Email : acepengxiong@163.com
# @Software : PyCharm
# -----------------------------------------------------------------------------
import pdfkit
from PyPDF2 import PdfFileMerger, PdfFileReader, PdfFileWriter
def html_to_pdf():
options = {
'--enable-local-file-access': '--enable-local-file-access',
# 'encoding': "utf-8",
# 'page-size': 'A5',
# 'page-width': '300mm',
# 'page-height': '200mm',
# 'margin-top': '0mm',
# 'margin-right': '0mm',
# 'margin-bottom': '0mm',
# 'margin-left': '0mm'
}
url1 = 'https://www.jianshu.com'
# url = 'http://baidu.com'
url2 = 'https://manage.meerkat.top'
# pdfkit.from_url(url1, '../pdf/out5.pdf', options=options)
# pdfkit.from_file('../templates/monthReport.html', '../pdf/out5.pdf', options=options)
pdfkit.from_file('app/html/monthReport.html', 'app/pdf/out5.pdf', options=options)
def merge_pdf(pdfFiles, target_file='/Users/pengxiong/Desktop/combine.pdf'):
""""""
merger = PdfFileMerger()
pdfWriter = PdfFileWriter() # 生成一个空白的pdf文件
for fileName in pdfFiles:
pdfReader = PdfFileReader(open(fileName, 'rb')) # 以只读方式依次打开pdf文件
for pageNum in range(pdfReader.numPages):
print(pdfReader.getPage(pageNum))
pdfWriter.addPage(pdfReader.getPage(pageNum)) # 将打开的pdf文件内容一页一页的复制到新建的空白pdf里
pdfOutput = open(target_file, 'wb') # 生成combine.pdf文件
pdfWriter.write(pdfOutput) # 将复制的内容全部写入combine.pdf
if __name__ == '__main__':
html_to_pdf()
# merge_pdf(['/Users/pengxiong/Desktop/out1.pdf', '/Users/pengxiong/Desktop/out.pdf'])
from jinja2 import PackageLoader, Environment
from app.service.portfolio_diagnose import portfolio_diagnose
from app.service.result_service import UserCustomerResultAdaptor
import numpy as np
# 准备数据
from app.utils.draw import draw_month_return_chart, draw_contribution_chart
from app.utils.radar_chart import gen_radar_chart
ifa_id = 'USER_INFO15914346866762'
customer_id = '202009281545001'
user_customer = UserCustomerResultAdaptor(ifa_id, customer_id)
df = user_customer.calculate_total_data()
d = user_customer.calculate_group_result_data()
# print(d)
# 几月综述部分
total_cost = df["total_cost"]/10000
now_yield = round((df['cumulative_return']-1)*100,2)
index_yield = round((df["index_result"]["return_ratio"]-1)*100, 2)
now_withdrawal = round(df["max_drawdown"][0]*100,2)
index_withdrawal = round(df["index_result"]["max_drawdown"][0]*100, 2)
# monthly_return_performance_pic = '_'.join((ifa_id, customer_id, '20201109', 'monthly_return_performance.png'))
# image_dir = './img/'
# monthly_return_performance_pic = image_dir + monthly_return_performance_pic
# 月度回报
xlabels, product_list, cumulative = user_customer.get_month_return_chart()
monthly_return_performance_pic = draw_month_return_chart(xlabels, product_list, cumulative)
# 组合数据
group_result = d["default"]
# 持仓组合点评
old_evaluation = portfolio_diagnose.old_evaluation('default', d, user_customer)
# 贡献分解
g_data = group_result["contribution_decomposition"]
contribution_decomposition = draw_contribution_chart(g_data['xlabels'], g_data['product_list'], g_data['cumulative'])
# 个基点评
single_fund_data_list = []
portfolio_evaluation = portfolio_diagnose.old_portfolio_evaluation()
radar_chart_data = portfolio_diagnose.single_fund_radar()
for i in range(len(portfolio_evaluation)):
single_fund_data_list.append({
'fund_name': portfolio_evaluation[i]['name'],
'status': '保留',
'evaluation': portfolio_evaluation[i]['data'],
'radar_chart_path': gen_radar_chart(radar_chart_data[i])
})
# 调仓建议
# 收益比较
# 旧相关性分析
old_correlation = portfolio_diagnose.old_correlation
old_correlation_columns = old_correlation.columns.tolist()
old_correlation_values = old_correlation.values.tolist()
old_correlation = list(zip(range(1, len(old_correlation_columns)+1), old_correlation_columns, old_correlation_values))
print(old_correlation)
# 优化组合建议1 -- 新增基金
propose_fund_data_list = []
propose_fund_evaluation = portfolio_diagnose.propose_fund_evaluation()
propose_radar_chart_data = portfolio_diagnose.propose_fund_radar()
for i in range(len(propose_fund_evaluation)):
propose_fund_data_list.append({
'fund_name': propose_fund_evaluation[i]['name'],
'status': '保留',
'evaluation': propose_fund_evaluation[i]['data'],
'radar_chart_path': gen_radar_chart(propose_radar_chart_data[i])
})
now_month_income = int(group_result["cur_month_profit"]) # 本月收益
now_year_income = int(group_result["cur_year_profit"]) # 今年累计收益
totoal_rate_of_return = round((group_result['cumulative_return']-1)*100, 2) # 累计收益率
month_rise = round(group_result["cur_month_profit_ratio"]*100, 2) # 本月涨幅
year_totoal_rate_of_return = round(group_result["cur_year_profit_ratio"]*100, 2) # 今年累计收益率
annualised_return = round(group_result["return_ratio_year"]*100, 2) # 年化收益率
volatility = round(group_result["volatility"]*100, 2)
max_withdrawal = round(group_result["max_drawdown"][0]*100, 2)
sharpe_ratio = round(group_result["sharpe"], 2)
cost_of_investment = int(group_result["total_cost"]) # 投资成本
final_balance = int(group_result["total_cost"] + group_result["cumulative_profit"]) # 期末资产
total_profit = int(group_result["cumulative_profit"]) # 累计盈利
index_section_return = round((group_result["index_result"]["return_ratio"]-1)*100, 2)
index_annualised_return = round(group_result["index_result"]["return_ratio_year"]*100, 2) # 年化收益率
index_volatility = round(group_result["index_result"]["volatility"]*100, 2)
index_max_withdrawal = round(group_result["index_result"]["max_drawdown"][0]*100, 2)
index_sharpe_ratio = round(group_result["index_result"]["sharpe"], 2)
group_nav_info = group_result["group_nav_info"]
group_hoding_info = group_result["group_hoding_info"]
# 全部数据
data = {'customer_name':'成龙', 'customer_gender':'女',
'year_month':'2020年10月', 'ifa_company':'飞度工作室',
'title':'10月综述', 'brand_name':'飞度工作室',
'customer_old':42, 'customer_level':'平衡型',
'position_years':'5年', 'planned_allocation_amount':2000.00,
'now_allocation_amount':total_cost, 'now_yield':now_yield, 'index_yield':index_yield, 'expected_yield':20,
'now_withdrawal':now_withdrawal, 'index_withdrawal': index_withdrawal, 'expected_withdrawal': 20,
'now_year_income':now_year_income,'now_month_income':now_month_income,'totoal_rate_of_return':totoal_rate_of_return,
'month_rise':month_rise, 'year_totoal_rate_of_return':year_totoal_rate_of_return,
'annualised_return': annualised_return, 'cost_of_investment': cost_of_investment,
'final_balance':final_balance, 'total_profit':total_profit,
'latest_worth_day':'2020-11-05',
'index_comparison':{'section_return': totoal_rate_of_return, 'annualized_returns': annualised_return,
'volatility':volatility, 'max_withdrawal':max_withdrawal, 'sharpe_ratio': sharpe_ratio},
'index_comparison_500':{'section_return':index_section_return, 'annualized_returns': index_annualised_return,
'volatility':index_volatility, 'max_withdrawal':index_max_withdrawal, 'sharpe_ratio':index_sharpe_ratio},
'monthly_return_performance_pic':monthly_return_performance_pic,
'group_nav_info': group_nav_info,
'group_hoding_info': group_hoding_info,
'old_evaluation': old_evaluation,
'contribution_decomposition': contribution_decomposition,
'single_fund_data_list': single_fund_data_list,
'old_correlation': old_correlation,
'propose_fund_data_list': propose_fund_data_list
}
# 开始渲染html模板
env = Environment(loader=PackageLoader('app','templates')) # 创建一个包加载器对象
template = env.get_template('monthReport.html') # 获取一个模板文件
monthReport_html = template.render(data) # 渲染
# 保存 monthReport_html
save_file = "app/html/monthReport.html"
with open(save_file, 'w', encoding="utf-8") as f:
f.write(monthReport_html)
\ No newline at end of file
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