Commit d82a0934 authored by pengxiong@wealthgrow.cn's avatar pengxiong@wealthgrow.cn

Merge remote-tracking branch 'origin/dev' into dev

parents 7801abf3 f9396627
...@@ -14,8 +14,7 @@ import os ...@@ -14,8 +14,7 @@ import os
import sys import sys
import yaml import yaml
from sqlalchemy import create_engine from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker, scoped_session
env = sys.argv[-1] env = sys.argv[-1]
work_dir = os.getcwd() work_dir = os.getcwd()
...@@ -58,9 +57,9 @@ tamp_user_engine = create_engine( ...@@ -58,9 +57,9 @@ tamp_user_engine = create_engine(
), ),
echo=True echo=True
) )
tamp_product_session = sessionmaker(bind=tamp_product_engine, autocommit=True)() tamp_product_session = scoped_session(sessionmaker(bind=tamp_product_engine))()
tamp_order_session = sessionmaker(bind=tamp_order_engine, autocommit=True)() tamp_order_session = scoped_session(sessionmaker(bind=tamp_order_engine))()
tamp_user_session = sessionmaker(bind=tamp_user_engine, autocommit=True)() tamp_user_session = scoped_session(sessionmaker(bind=tamp_user_engine))()
# redis = redis.StrictRedis( # redis = redis.StrictRedis(
# host=config[env]['redis']['host'], # host=config[env]['redis']['host'],
......
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -22,7 +22,7 @@ class UserCustomerDataAdaptor: ...@@ -22,7 +22,7 @@ class UserCustomerDataAdaptor:
month_date = "" month_date = ""
end_date = "" end_date = ""
group_data = {} group_data = {}
trade_cal = None trade_cal_date = None
all_fund_distribution = {} all_fund_distribution = {}
all_fund_performance = {} all_fund_performance = {}
...@@ -32,13 +32,15 @@ class UserCustomerDataAdaptor: ...@@ -32,13 +32,15 @@ class UserCustomerDataAdaptor:
self.compare_index_id = index_id self.compare_index_id = index_id
p_end_date = pd.to_datetime(end_date).date() p_end_date = pd.to_datetime(end_date).date()
p_end_date = datetime.date(year=p_end_date.year, month=p_end_date.month, day=1) - datetime.timedelta(days=1) p_end_date = datetime.date(year=p_end_date.year, month=p_end_date.month, day=1) - datetime.timedelta(days=1)
# self.end_date = pd.to_datetime(str(p_end_date)) self.end_date = pd.to_datetime(str(p_end_date))
self.end_date = pd.to_datetime("2020-11-23") # self.end_date = pd.to_datetime("2020-11-23")
p_start_date = datetime.date(year=p_end_date.year, month=p_end_date.month, day=1) p_start_date = datetime.date(year=p_end_date.year, month=p_end_date.month, day=1)
self.month_start_date = pd.to_datetime("2020-11-16") self.month_start_date = p_start_date
# self.month_start_date = pd.to_datetime("2020-11-16")
self.user_customer_order_df = self.get_user_customer_order_data() self.user_customer_order_df = self.get_user_customer_order_data()
self.fund_nav_total, self.fund_cnav_total = self.get_customer_fund_nav_data() self.fund_nav_total, self.fund_cnav_total = self.get_customer_fund_nav_data()
self.get_customer_index_nav_data() self.index_df = self.get_customer_index_nav_data()
self.total_customer_order_cnav_df = self.total_combine_data()
self.group_operate() self.group_operate()
@staticmethod @staticmethod
...@@ -82,7 +84,7 @@ class UserCustomerDataAdaptor: ...@@ -82,7 +84,7 @@ class UserCustomerDataAdaptor:
def get_customer_fund_nav_data(self): def get_customer_fund_nav_data(self):
now_date = datetime.datetime.now().strftime("%Y%m%d") now_date = datetime.datetime.now().strftime("%Y%m%d")
trade_date_df = self.get_trade_cal("20000101", now_date) trade_date_df = self.get_trade_cal("20000101", now_date)
self.trade_cal = trade_date_df self.trade_cal_date = trade_date_df
all_fund_nav = pd.DataFrame(index=trade_date_df["datetime"]) all_fund_nav = pd.DataFrame(index=trade_date_df["datetime"])
all_fund_cnav = pd.DataFrame(index=trade_date_df["datetime"]) all_fund_cnav = pd.DataFrame(index=trade_date_df["datetime"])
...@@ -94,21 +96,21 @@ class UserCustomerDataAdaptor: ...@@ -94,21 +96,21 @@ class UserCustomerDataAdaptor:
cur_fund_nav_df = pd.DataFrame(list(data), columns=['price_date', 'nav', 'cnav']) cur_fund_nav_df = pd.DataFrame(list(data), columns=['price_date', 'nav', 'cnav'])
# # 对应基金分红 # # 对应基金分红
# sql = """select distinct `distribute_date`, `distribution` from `fund_distribution` where `fund_id`='{}' and `distribute_type`='1' order by `distribute_date` ASC""".format( sql = """select distinct `distribute_date`, `distribution` from `fund_distribution` where `fund_id`='{}' and `distribute_type`='1' order by `distribute_date` ASC""".format(
# cur_fund_id) cur_fund_id)
# cur = tamp_product_session.execute(sql) cur = tamp_product_session.execute(sql)
# data = cur.fetchall() data = cur.fetchall()
# cur_fund_distribution_df = pd.DataFrame(list(data), columns=['price_date', 'distribution']) cur_fund_distribution_df = pd.DataFrame(list(data), columns=['price_date', 'distribution'])
# self.all_fund_distribution[cur_fund_id] = cur_fund_distribution_df self.all_fund_distribution[cur_fund_id] = cur_fund_distribution_df
#
# # 对应基金performance数据 # 对应基金performance数据
# sql = """select distinct `price_date`, `ret_cum_1w`, `ret__cum_1m`, `ret_cum_6m`, `ret_cum_1y`, `ret_cum_ytd`, `ret_cum_incep` from `fund_performance` where `fund_id`='{}' order by `price_date` ASC""".format( sql = """select distinct `price_date`, `ret_1w`, `ret_cum_1m`, `ret_cum_6m`, `ret_cum_1y`, `ret_cum_ytd`, `ret_cum_incep` from `fund_performance` where `fund_id`='{}' order by `price_date` ASC""".format(
# cur_fund_id) cur_fund_id)
# cur = tamp_product_session.execute(sql) cur = tamp_product_session.execute(sql)
# data = cur.fetchall() data = cur.fetchall()
# cur_fund_performance_df = pd.DataFrame(list(data), cur_fund_performance_df = pd.DataFrame(list(data),
# columns=['price_date', 'ret_cum_1w', 'ret__cum_1m', 'ret_cum_6m', 'ret_cum_1y', 'ret_cum_ytd', 'ret_cum_incep']) columns=['price_date', 'ret_1w', 'ret_cum_1m', 'ret_cum_6m', 'ret_cum_1y', 'ret_cum_ytd', 'ret_cum_incep'])
# self.all_fund_performance[cur_fund_id] = cur_fund_performance_df self.all_fund_performance[cur_fund_id] = cur_fund_performance_df
cur_fund_nav_df["price_date"] = pd.to_datetime(cur_fund_nav_df["price_date"]) cur_fund_nav_df["price_date"] = pd.to_datetime(cur_fund_nav_df["price_date"])
cur_fund_nav_df.set_index("price_date", inplace=True) cur_fund_nav_df.set_index("price_date", inplace=True)
...@@ -128,12 +130,12 @@ class UserCustomerDataAdaptor: ...@@ -128,12 +130,12 @@ class UserCustomerDataAdaptor:
index_df["price_date"] = pd.to_datetime(index_df["price_date"]) index_df["price_date"] = pd.to_datetime(index_df["price_date"])
index_df.set_index("price_date", inplace=True) index_df.set_index("price_date", inplace=True)
self.fund_cnav_total["index"] = index_df["index"] self.fund_cnav_total["index"] = index_df["index"]
self.index_df = index_df
return index_df return index_df
# 分组合计算 # 分组合计算
def group_operate(self): def group_operate(self):
for folio in self.user_customer_order_df["folio_name"].unique(): for folio in self.user_customer_order_df["folio_name"].unique():
cur_folio_order_df = self.user_customer_order_df[self.user_customer_order_df["folio_name"] == folio] cur_folio_order_df = self.user_customer_order_df[self.user_customer_order_df["folio_name"] == folio]
fund_id_list = list(self.user_customer_order_df["fund_id"].unique()) fund_id_list = list(self.user_customer_order_df["fund_id"].unique())
...@@ -216,5 +218,64 @@ class UserCustomerDataAdaptor: ...@@ -216,5 +218,64 @@ class UserCustomerDataAdaptor:
self.group_data[p_folio] = {"result_cnav_data": cnav_df, "order_df": p_order_df} self.group_data[p_folio] = {"result_cnav_data": cnav_df, "order_df": p_order_df}
return cnav_df return cnav_df
# 所有的数据操作
def total_combine_data(self): def total_combine_data(self):
pass
p_order_df = self.user_customer_order_df.copy()
p_nav_df = self.fund_nav_total.copy()
p_cnav_df = self.fund_cnav_total.copy()
start_date = pd.to_datetime(p_order_df["confirm_share_date"].min())
cnav_df = p_cnav_df[p_cnav_df.index >= start_date].copy()
p_fund_id_list = list(p_order_df["fund_id"].unique())
for p_fund_id in p_fund_id_list:
order_min_date = p_order_df[p_order_df["fund_id"] == p_fund_id]["confirm_share_date"].min()
if pd.to_datetime(order_min_date) > start_date:
cnav_df.loc[:order_min_date - datetime.timedelta(days=1), p_fund_id] = np.nan
for index, row in p_order_df.iterrows():
cur_fund_id = str(row["fund_id"])
confirm_share_date = pd.to_datetime(row["confirm_share_date"])
# 根据确认净值日查看是否含有累积净值的数据,如果没有按照前后差值推算当天累积净值
if pd.isnull(cnav_df.loc[confirm_share_date, cur_fund_id]):
last_nav_data = p_nav_df[p_nav_df.index < confirm_share_date][cur_fund_id].dropna().tail(1)
last_cnav_data = p_cnav_df[p_cnav_df.index < confirm_share_date][cur_fund_id].dropna().tail(1)
# 判断上个净值日和当前确认日之中是否存在分红日
"""need add judge"""
if len(last_nav_data) < 1:
cnav_df.loc[confirm_share_date, cur_fund_id] = row["nav"]
else:
diff_nav = row["nav"] - last_nav_data.values[0]
cur_cnav = last_cnav_data.values[0] + diff_nav
cnav_df.loc[confirm_share_date, cur_fund_id] = cur_cnav
cnav_df = cnav_df.dropna(axis=0, how="all").fillna(method='ffill')
for index, row in p_order_df.iterrows():
cur_fund_id = str(row["fund_id"])
confirm_share_date = pd.to_datetime(row["confirm_share_date"])
if cur_fund_id + "_amount" not in cnav_df:
profit = cnav_df[cur_fund_id].dropna() - cnav_df[cur_fund_id].dropna().shift(1)
cnav_df[cur_fund_id + "_profit"] = profit
cnav_df[cur_fund_id + "_profit_ratio"] = profit / cnav_df[cur_fund_id].dropna().shift(1)
cnav_df[cur_fund_id + "_amount"] = 0
cnav_df[cur_fund_id + "_earn"] = 0
# cnav_df[cur_fund_id + "_cum_earn"] = 0
cnav_df[cur_fund_id + "_share"] = 0
# buy
if row['order_type'] == 1:
cnav_df.loc[confirm_share_date:, cur_fund_id + "_amount"] += row["confirm_amount"]
cnav_df.loc[confirm_share_date:, cur_fund_id + "_share"] += row["confirm_share"]
# sell
elif row['order_type'] == 2:
cnav_df.loc[confirm_share_date:, cur_fund_id + "_amount"] -= row["confirm_amount"]
cnav_df.loc[confirm_share_date:, cur_fund_id + "_share"] -= row["confirm_share"]
cnav_df[cur_fund_id + "_earn"] = cnav_df[cur_fund_id + "_profit"] * cnav_df[cur_fund_id + "_share"]
cnav_df[cur_fund_id + "_earn"] = cnav_df[cur_fund_id + "_earn"].apply(lambda x: float(x))
cnav_df[cur_fund_id + "_cum_earn"] = cnav_df[cur_fund_id + "_earn"].cumsum()
return cnav_df
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -14,7 +14,7 @@ from matplotlib.ticker import FuncFormatter ...@@ -14,7 +14,7 @@ from matplotlib.ticker import FuncFormatter
from matplotlib.font_manager import FontProperties from matplotlib.font_manager import FontProperties
# 中文字体初始化 # 中文字体初始化
plt.rcParams['font.sans-serif']=['Heiti TC'] plt.rcParams['font.sans-serif']=['SimSun']
def to_percent(temp, position): def to_percent(temp, position):
...@@ -31,7 +31,7 @@ def draw_month_return_chart(xlabels, product_list, cumulative): ...@@ -31,7 +31,7 @@ def draw_month_return_chart(xlabels, product_list, cumulative):
fontsize = 20 fontsize = 20
# 初始化 # 初始化
fig = plt.figure(figsize=figsize) fig = plt.figure(figsize=figsize)
ax1 = fig.add_subplot() ax1 = fig.add_subplot(111)
ax2 = ax1.twinx() ax2 = ax1.twinx()
max_x_count = max([x['data'].size for x in product_list]) max_x_count = max([x['data'].size for x in product_list])
loc = np.arange(max_x_count) # the x locations for the groups loc = np.arange(max_x_count) # the x locations for the groups
......
...@@ -11,6 +11,13 @@ import calendar ...@@ -11,6 +11,13 @@ import calendar
import math import math
dict_substrategy = {1010: '主观多头', 1020: '股票多空', 1030: '量化多头', 2010: '宏观策略', 3010: '主观趋势', 3020: '主观套利',
3030: '量化趋势', 3040: '量化套利', 3050: 'CTA策略', 4010: '并购重组', 4020: '定向增发', 4030: '大宗交易',
4040: '事件驱动复合', 5010: '市场中性', 5020: '套利策略', 5030: '相对价值复合', 6010: '纯债策略', 6020: '强债策略',
6030: '债券策略', 7010: 'MOM', 7020: 'FOF', 8010: '主观多策略', 8020: '量化多策略', -1: '其他策略'}
BANK_RATE = 0.015
def simple_return(net_worth): def simple_return(net_worth):
""" """
简单收益率 简单收益率
...@@ -272,4 +279,43 @@ def freq_days(fav_freq): ...@@ -272,4 +279,43 @@ def freq_days(fav_freq):
N = 3 # 季度更新 N = 3 # 季度更新
else: else:
N = 250 # 没有设置freq默认是天更 N = 250 # 没有设置freq默认是天更
return N return N
\ No newline at end of file
def resample(df, trading_cal, freq):
"""对基金净值表进行粒度不同的重采样,并剔除不在交易日中的结果
Args:
df ([DataFrame]): [原始基金净值表]
trading_cal ([type]): [上交所交易日表]
freq ([type]): [重采样频率: 1:工作日,2:周, 3:月, 4:半月, 5:季度]
Returns:
[DataFrame]: [重采样后剔除不在交易日历中的净值表和交易日历以净值日期为索引的合表]
"""
freq_dict = {1: 'B', 2: 'W-FRI', 3: 'M', 4: 'SM', 5: 'Q'}
resample_freq = freq_dict[freq]
# 按采样频率进行重采样并进行净值的前向填充
df = df.resample(rule=resample_freq).ffill()
# 根据采样频率确定最大日期偏移量(保证偏移后的日期与重采样的日期在同一周,同一月,同一季度等)
timeoffset_dict = {1: 1, 2: 5, 3: 30, 4: 15, 5: 120}
timeoffetmax = timeoffset_dict[freq]
# Dataframe不允许直接修改index,新建一份index的复制并转为list
new_index = list(df.index)
# 遍历重采样后的日期
for idx, date in enumerate(df.index):
# 如果重采样后的日期不在交易日历中
if date not in trading_cal.index:
# 对重采样后的日期进行偏移
for time_offset in range(1, timeoffetmax):
# 如果偏移后的日期在交易日历中,保留偏移后的日期
if date - datetime.timedelta(days=time_offset) in trading_cal.index:
new_index[idx] = date - datetime.timedelta(days=time_offset)
# 任意一天满足立即退出循环
break
# 更改净值表的日期索引为重采样后且在交易日内的日期
df.index = pd.Series(new_index)
return df
# -*- 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.result_service import UserCustomerResultAdaptor
# 准备数据
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['contribution_decomposition']-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
# 组合数据
group_result = d["default"]
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['contribution_decomposition']-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)
# 全部数据
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,
}
# 开始渲染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