# -*- encoding: utf-8 -*- # ----------------------------------------------------------------------------- # @File Name : draw.py # @Time : 2020/11/19 上午10:51 # @Author : X. Peng # @Email : acepengxiong@163.com # @Software : PyCharm # ----------------------------------------------------------------------------- import base64 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 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*1.05, '%.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') return month_return_img 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 = ['#333333', '#928C8C', '#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 # 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 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 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 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)