# -*- encoding: utf-8 -*- # ----------------------------------------------------------------------------- # @File Name : draw.py # @Time : 2020/11/19 上午10:51 # @Author : X. Peng # @Email : acepengxiong@163.com # @Software : PyCharm # ----------------------------------------------------------------------------- import base64 import uuid from urllib import parse from io import BytesIO import numpy as np import matplotlib import matplotlib.pyplot as plt from matplotlib import ticker from matplotlib.ticker import FuncFormatter from matplotlib.font_manager import FontProperties from app.api.engine import template_folder, work_dir, temp_img_save_folder matplotlib.use('Agg') # 中文字体初始化 plt.rcParams['font.sans-serif']=['Heiti TC'] def to_percent(temp, position): return '%.2f' % temp + '%' def draw_month_return_chart(xlabels, product_list, cumulative): """月度回报表现图""" # plt.title('Scores by group and gender') # plt.ylabel('Scores') figsize = (24, 12) # 标签文字大小 fontsize = 15 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot(111) ax2 = ax1.twinx() max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups width = 0.35 # the width of the bars: can also be len(x) sequence color_list = ['#B0B0B0', '#6C71AA', '#E1BC95', '#F9DBB8'] # 坐标轴 ax1.tick_params(labelsize=fontsize) ax2.tick_params(labelsize=fontsize) # 坐标轴颜色 ax2.tick_params(axis='y', colors='#D40000') ax1.set_xticks(loc) ax1.set_xticklabels(xlabels) # ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) ax2.yaxis.set_major_formatter(FuncFormatter(to_percent)) # temp_rate = np.zeros(max_x_count) # for i in range(len(product_list)): # temp_rate += product_list[i]['data'] # max_rate = np.max(np.hstack((temp_rate, cumulative['data']))) # ax2.set_ylim(0, max_rate + 15) # 柱状图 prod_legend = [] for i in range(len(product_list)): ax = None bottom = np.zeros(max_x_count) if i == 0: ax = ax1.bar(loc, product_list[i]['data'], width, color=color_list[i], alpha=0.8) else: for j in range(i): bottom = bottom + product_list[j]['data'] if i < len(color_list): ax = ax1.bar(loc, product_list[i]['data'], width, bottom=bottom, color=color_list[i], alpha=0.8) else: ax = ax1.bar(loc, product_list[i]['data'], width, bottom=bottom, alpha=0.8) for a, b in zip(range(len(xlabels)), product_list[0]['data']): if b > 0: ax1.text(a, b*1.08, '%.2f万' % b, ha='center', va='bottom', fontsize=fontsize) elif b < 0: ax1.text(a, b*0.92, '%.2f万' % b, ha='center', va='top', fontsize=fontsize) prod_legend.append(ax[0]) ax1.legend(prod_legend, [prod['name'] for prod in product_list], loc='upper left', fontsize=fontsize) # 画折线图 ax2.plot(loc, cumulative['data'], color='#D40000', marker='.', linewidth=3, label=cumulative['name']) # 添加数字标签 for a, b in zip(range(len(xlabels)), cumulative['data']): ax2.text(a*1.05, b, '%.2f' % b + '%', ha='center', va='bottom', fontsize=fontsize, color='#D40000') ax2.legend(loc='upper center', fontsize=fontsize) # plt.show() # imgdata = BytesIO() # fig.savefig(imgdata, format='png', bbox_inches='tight') # imgdata.seek(0) # rewind the data # month_return_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') filename = str(uuid.uuid4()) + '.png' fig.savefig(temp_img_save_folder + filename, format='png', bbox_inches='tight') return_path = template_folder + filename return return_path def draw_contribution_chart(xlabels, product_list, cumulative): """贡献分解图""" # plt.title('Scores by group and gender') # plt.ylabel('Scores') figsize = (25, 12) # 标签文字大小 fontsize = 22 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot(111) ax2 = ax1.twiny() max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups width = 0.35 # the width of the bars: can also be len(x) sequence color_list = ['#AFAFAF', '#D56666', '#DE7A7A', '#ED9494', '#F4A9A9', '#FFC8C8', '#DEA27A', '#EFAF85', '#FBBF98', '#FFD2B5', '#E1C277', '#EBCD85', '#FEDF96'] # 坐标轴 ax1.tick_params(labelsize=fontsize) ax1.set_xticks(loc) ax1.set_xticklabels(xlabels) ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) ax1.grid(axis='y') # temp_rate = np.zeros(max_x_count) # for i in range(len(product_list)): # temp_rate += product_list[i]['data'] # max_rate = np.max(np.hstack((temp_rate, cumulative['data']))) ax2.set_xticks([]) # ax2.set_ylim(0, max_rate + 10) # 堆叠柱状图 prod_legend = [] for i in range(len(product_list)): ax = None bottom = np.zeros(max_x_count) if i == 0: ax = ax1.bar(loc, product_list[i]['data'], width, color=color_list[i], alpha=0.8) else: for j in range(i): bottom = bottom + product_list[j]['data'] if i < len(color_list): ax = ax1.bar(loc, product_list[i]['data'], width, bottom=bottom, color=color_list[i], alpha=0.8) else: ax = ax1.bar(loc, product_list[i]['data'], width, bottom=bottom, alpha=0.8) prod_legend.append(ax[0]) ax1.legend(prod_legend, [prod['name'] for prod in product_list], bbox_to_anchor=(0.9, -0.1), ncol=4, fontsize=fontsize) # 画折线图 ax2.plot(loc, cumulative['data'], color='#B40A15', marker='', linewidth=3, label=cumulative['name']) # 添加数字标签 for a, b in zip(range(len(xlabels)), cumulative['data']): ax2.text(a*1.1, b *1.05, '%.2f' % b + '%', ha='center', va='bottom', fontsize=fontsize, color='#B40A15') ax2.legend(loc='upper left', fontsize=fontsize) # imgdata = BytesIO() # fig.savefig(imgdata, format='png', bbox_inches='tight') # imgdata.seek(0) # rewind the data # month_return_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') # return month_return_img filename = str(uuid.uuid4()) + '.png' fig.savefig(temp_img_save_folder + filename, format='png', bbox_inches='tight') return_path = template_folder + filename return return_path # def draw_contribution_chart(xlabels, product_list, cumulative): # """贡献分解图""" # # # plt.title('Scores by group and gender') # # plt.ylabel('Scores') # figsize = (25, 12) # # 标签文字大小 # fontsize = 22 # # 初始化 # fig = plt.figure(figsize=figsize) # ax1 = fig.add_subplot() # ax2 = ax1.twiny() # max_x_count = max([x['data'].size for x in product_list]) # loc = np.arange(max_x_count) # the x locations for the groups # width = 0.35 # the width of the bars: can also be len(x) sequence # color_list = ['#222A77', '#6C71AA', '#E1BC95', '#F9DBB8'] # # # 坐标轴 # ax1.tick_params(labelsize=fontsize) # ax1.set_xticks(loc) # ax1.set_xticklabels(xlabels) # ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) # # temp_rate = np.zeros(max_x_count) # # for i in range(len(product_list)): # # temp_rate += product_list[i]['data'] # # max_rate = np.max(np.hstack((temp_rate, cumulative['data']))) # ax2.set_xticks([]) # # ax2.set_ylim(0, max_rate + 10) # # # 堆叠柱状图 # prod_legend = [] # for i in range(len(product_list)): # ax = None # for j in range(len(product_list[i]['data'])): # product_list[i]['bottom'] = product_list[i].get('bottom', 0) # product_list[i]['bottom_neg'] = product_list[i].get('bottom_neg', 0) # if j > 0: # product_list[i]['bottom'] += product_list[i].get('bottom', 0) # product_list[i]['bottom_neg'] += product_list[i].get('bottom_neg', 0) # if i < len(color_list): # for x in loc: # if product_list[i]['data'][x] >= 0: # ax = ax1.bar(x, product_list[i]['data'][x], width, bottom=product_list[i]['bottom'], color=color_list[i], alpha=0.8) # else: # ax = ax1.bar(x, product_list[i]['data'][x], width, bottom=product_list[i]['bottom_neg'], # color=color_list[i], alpha=0.8) # else: # for x in loc: # if product_list[i]['data'][x] >= 0: # ax = ax1.bar(x, product_list[i]['data'][x], width, bottom=product_list[i]['bottom'], alpha=0.8) # else: # ax = ax1.bar(x, product_list[i]['data'][x], width, bottom=product_list[i]['bottom_neg'], alpha=0.8) # prod_legend.append(ax[0]) # # ax1.legend(prod_legend, [prod['name'] for prod in product_list], bbox_to_anchor=(0.9, -0.1), ncol=4, fontsize=fontsize) # # # 画折线图 # ax2.plot(loc, cumulative['data'], color='#C6A774', marker='', linewidth=3, label=cumulative['name']) # ax2.legend(loc='upper left', fontsize=fontsize) # # plt.show() # # imgdata = BytesIO() # # fig.savefig(imgdata, format='png', bbox_inches='tight') # # imgdata.seek(0) # rewind the data # # month_return_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') # # return month_return_img def draw_comment_chart(xlabels, source_prod, target_prod): """个基点评图""" figsize = (20, 12) # 标签文字大小 fontsize = 22 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot() ax2 = ax1.twiny() # ax = plt.gca() # gca:get current axis得到当前轴 # ax.spines['bottom'].set_position(('data', 0)) # data表示通过值来设置x轴的位置,将x轴绑定在y=0的位置 product_list = [source_prod, target_prod] max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups # 坐标轴 ax1.tick_params(labelsize=fontsize) ax2.tick_params(labelsize=fontsize) ax1.set_xticks(loc) ax1.set_xticklabels(xlabels) ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) max_rate = np.max(np.hstack((source_prod['data'], target_prod['data']))) ax2.set_xticks([]) # 个基折线图 ax1.plot(loc, source_prod['data'], color='#C6A774', marker='', linewidth=3, label=source_prod['name']) ax1.legend(loc='upper left', fontsize=fontsize) # 指数折线图 ax2.plot(loc, target_prod['data'], color='black', marker='', linewidth=3, label=target_prod['name']) ax2.legend(loc='upper center', fontsize=fontsize) plt.show() def draw_old_combination_chart(xlabels, origin_combination, index): """旧组合对比图""" figsize = (20, 12) # 标签文字大小 fontsize = 22 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot(111) ax3 = ax1.twiny() # ax = plt.gca() # gca:get current axis得到当前轴 # ax.spines['bottom'].set_position(('data', 0)) # data表示通过值来设置x轴的位置,将x轴绑定在y=0的位置 product_list = [origin_combination, index] max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups # 坐标轴 ax1.tick_params(labelsize=fontsize) ax3.tick_params(labelsize=fontsize) ax1.set_xticks(loc) ax1.set_xticklabels(xlabels) ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) ax3.set_xticks([]) # 新组合折线图 ax1.plot(loc, origin_combination['data'], color='#C6A774', marker='', linewidth=3, label=origin_combination['name']) ax1.legend(loc='upper left', fontsize=fontsize) # 指数折线图 ax3.plot(loc, index['data'], color='black', marker='', linewidth=3, label=index['name']) ax3.legend(loc='upper right', fontsize=fontsize) # plt.show() # imgdata = BytesIO() # fig.savefig(imgdata, format='png', bbox_inches='tight') # imgdata.seek(0) # rewind the data # return_compare_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') # return return_compare_img filename = str(uuid.uuid4()) + '.png' fig.savefig(temp_img_save_folder + filename, format='png', bbox_inches='tight') return_path = template_folder + filename return return_path def draw_combination_chart(xlabels, new_combination, origin_combination, index): """新组合对比图""" figsize = (20, 12) # 标签文字大小 fontsize = 22 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot(111) ax2 = ax1.twiny() ax3 = ax1.twiny() # ax = plt.gca() # gca:get current axis得到当前轴 # ax.spines['bottom'].set_position(('data', 0)) # data表示通过值来设置x轴的位置,将x轴绑定在y=0的位置 product_list = [origin_combination, new_combination, index] max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups # 坐标轴 ax1.tick_params(labelsize=fontsize) ax2.tick_params(labelsize=fontsize) ax3.tick_params(labelsize=fontsize) ax1.set_xticks(loc) ax1.set_xticklabels(xlabels) ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) ax2.set_xticks([]) ax3.set_xticks([]) # 新组合折线图 ax1.plot(loc, new_combination['data'], color='#C6A774', marker='', linewidth=3, label=new_combination['name']) ax1.legend(loc='upper left', fontsize=fontsize) # 原组合折线图 ax2.plot(loc, origin_combination['data'], color='#222A77', marker='', linewidth=3, label=origin_combination['name']) ax2.legend(loc='upper center', fontsize=fontsize) # 指数折线图 ax3.plot(loc, index['data'], color='black', marker='', linewidth=3, label=index['name']) ax3.legend(loc='upper right', fontsize=fontsize) # plt.show() # imgdata = BytesIO() # fig.savefig(imgdata, format='png', bbox_inches='tight') # imgdata.seek(0) # rewind the data # return_compare_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') # return return_compare_img filename = str(uuid.uuid4()) + '.png' fig.savefig(temp_img_save_folder + filename, format='png', bbox_inches='tight') return_path = template_folder + filename return return_path def draw_index_combination_chart(compare_data): """基金和指数对比图""" xlabels, origin_combination, index = compare_data["xlabels"], compare_data["fund"], compare_data["index"] figsize = (20, 12) # 标签文字大小 fontsize = 22 # 初始化 fig = plt.figure(figsize=figsize) ax1 = fig.add_subplot(111) ax3 = ax1.twiny() ax1.spines['top'].set_visible(False) ax1.spines['right'].set_visible(False) ax1.spines['bottom'].set_visible(False) ax1.spines['left'].set_visible(False) ax3.spines['top'].set_visible(False) ax3.spines['right'].set_visible(False) ax3.spines['bottom'].set_visible(False) ax3.spines['left'].set_visible(False) # ax = plt.gca() # gca:get current axis得到当前轴 # ax.spines['bottom'].set_position(('data', 0)) # data表示通过值来设置x轴的位置,将x轴绑定在y=0的位置 product_list = [origin_combination, index] max_x_count = max([x['data'].size for x in product_list]) loc = np.arange(max_x_count) # the x locations for the groups # 坐标轴 # ax1.tick_params(labelsize=fontsize) # ax3.tick_params(labelsize=fontsize) # ax1.set_xticks(loc) # ax1.set_xticklabels(xlabels) # ax1.yaxis.set_major_formatter(FuncFormatter(to_percent)) # ax1.set_yticks([]) # ax3.set_yticks([]) # ax3.set_xticks([]) ax1.axis('off') ax3.axis('off') # 基金折线图 ax1.plot(loc, origin_combination['data'], color='#D40000', marker='', linewidth=3) # ax1.legend() # 指数折线图 ax3.plot(loc, index['data'], color='grey', marker='', linewidth=3) # ax3.legend() # plt.show() # imgdata = BytesIO() # fig.savefig(imgdata, format='png', bbox_inches='tight') # imgdata.seek(0) # rewind the data # return_compare_img = 'data:image/png;base64,' + base64.b64encode(imgdata.getvalue()).decode('utf-8') # return return_compare_img filename = str(uuid.uuid4()) + '.png' fig.savefig(temp_img_save_folder + filename, format='png', bbox_inches='tight') plt.clf() return_path = template_folder + filename return return_path if __name__ == '__main__': # xlabels = ('2020-1', '2020-2', '2020-3', '2020-4', '2020-5', '2020-6', '2020-7', '2020-8', '2020-9', '2020-10', '2020-11', '2020-12') # product = {'name': '月度回报率', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} # contrast = {'name': '同比上涨', 'data': np.array([10, 50, 120, 100, 36, 0, 50, 120, 100, 36, 23, 98])} # draw_month_return_chart(xlabels, [product], contrast) xlabels = ('2020-1', '2020-2', '2020-3', '2020-4', '2020-5', '2020-6', '2020-7', '2020-8', '2020-9', '2020-10', '2020-11', '2020-12') product1 = {'name': '塞亚成长1号', 'data': np.array([-10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product2 = {'name': '塞亚成长2号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product3 = {'name': '塞亚成长3号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product4 = {'name': '塞亚成长4号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product5 = {'name': '塞亚成长5号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product6 = {'name': '塞亚成长6号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product7 = {'name': '塞亚成长7号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product8 = {'name': '塞亚成长8号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} product_list = [product1, product2, product3, product4, product5, product6, product7, product8] cumulative = {'name': '总收益', 'data': np.array([10, 50, 120, 100, 36, 0, 50, 120, 100, 36, 23, 98])} draw_contribution_chart(xlabels, product_list, cumulative) # xlabels = ('2020-1', '2020-2', '2020-3', '2020-4', '2020-5', '2020-6', '2020-7', '2020-8', '2020-9', '2020-10', '2020-11', '2020-12') # source_prod = {'name': '远澜银杏1号', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} # target_prod = {'name': '上证指数', 'data': np.array([-10, 10, 5, 55, 24, 10, 20, 8, 10, 31, 40, 32])} # draw_comment_chart(xlabels, source_prod, target_prod) # xlabels = ('2020-1', '2020-2', '2020-3', '2020-4', '2020-5', '2020-6', '2020-7', '2020-8', '2020-9', '2020-10', '2020-11', '2020-12') # new_combination = {'name': '新组合', 'data': np.array([20, 30, 40, 50, 60, 20, 30, 40, 50, 60, 50, 60])} # origin_combination = {'name': '原组合', 'data': np.array([10, 20, 30, 40, 50, 10, 20, 30, 40, 50, 40, 50])} # index = {'name': '上证指数', 'data': np.array([-10, 10, 5, 55, 24, 10, 20, 8, 10, 31, 40, 32])} # draw_combination_chart(xlabels, new_combination, origin_combination, index)