​用 Python 动态可视化,看看比特币这几年

数据派THU

共 7959字,需浏览 16分钟

 ·

2021-04-06 13:15


来源:早起Python

本文约3600字,建议阅读8分钟

比特币一年翻6倍?


最近几年,一直站在风口浪尖的比特币被追捧为最佳的投资产品,拥护者们认为这种加密货币是一种类似于黄金的储值工具,可以对冲通胀和美元疲软。其他人则认为,比特币的暴涨只是一个经济刺激措施催生的巨大泡沫,并且必将破裂。

本文就将对比特币2013年到2021年价格进行动态可视化,先看效果:


获取数据

比特币数据很多网站都有,并且也有很多成熟的API,所以取数据非常简单,直接调用API接口即可,下面是获取与写入数据的全部代码:


import requestsimport jsonimport csvimport timetime_stamp = int(time.time())url = f"https://web-api.coinmarketcap.com/v1/cryptocurrency/ohlcv/historical?convert=USD&slug=bitcoin&time_end={time_stamp}&time_start=1367107200"rd = requests.get(url = url)# 返回的数据是 JSON 格式,使用 json 模块解析co = json.loads(rd.content)list1 = co['data']['quotes']
with open('BTC.csv','w' ,encoding='utf8',newline='') as f: csvi = csv.writer(f) csv_head = ["date","price","volume"] csvi.writerow(csv_head)
for i in list1: quote_date = i["time_open"][:10] quote_price = "{:.2f}".format(i["quote"]["USD"]["close"]) quote_volume = "{:.2f}".format(i["quote"]["USD"]["volume"]) csvi.writerow([quote_date, quote_price, quote_volume])

执行后,当前目录就会生成BTC.csv数据文件



动态可视化BTC价格变化

首先导入需要的包及相关设定:


import pandas as pdimport matplotlib as mplfrom matplotlib import cmimport numpy as npimport matplotlib.pyplot as pltimport matplotlib.ticker as ticker import matplotlib.animation as animationfrom IPython.display import HTMLfrom datetime import datetimeplt.rcParams['font.sans-serif'] = ['SimHei']  plt.rcParams['axes.unicode_minus'] = False  plt.rc('axes',axisbelow=True) mpl.rcParams['animation.embed_limit'] = 2**128

其中两句plt.rcParams[]是用来设置显示中文的plt.rc('axes',axisbelow=True)的作用是设置外观要求,即坐标轴置底。mpl.rcParams['animation.embed_limit'] = 2**128这句是为了生成动画而用的,由于动画默认的最大体积为20971520.字节。如果需要调整生成的动画最大体积,需要更改这个参数。

接下来数据并利用查看前5行与后5行:


从表格初窥可以得知,13年初的价格在100美元左右,而到如今21年价格已经飞涨到5万左右了。具体在哪段时间飞涨如此之快呢,我们通过动态面积可视化来探索。

可视化之前,需要对数据进行处理,由于我们原本的数据是这样的:



是csv格式,且Date字段是字符串类型,而在Python中运用matplotlib画时间序列图都需要datetime时间戳格式才美观,所以我们运用了如下代码进行转换:


df = pd.read_csv('BTC.csv')df['date']=[datetime.strptime(d, '%Y/%m/%d').date() for d in df['date']]

下面制作静态面积图,使用单色填充的话,可用如下代码:


Span=180N_Span=0df_temp=df.loc[N_Span*Span:(N_Span+1)*Span,:]df_temp.head(5)fig =plt.figure(figsize=(6,4), dpi=100)plt.subplots_adjust(top=1,bottom=0,left=0,right=0.9,hspace=0,wspace=0)plt.fill_between(df_temp.date.values, y1=df_temp.price.values, y2=0,alpha=0.75, facecolor='r', linewidth=1,edgecolor ='none',zorder=1)plt.plot(df_temp.date, df_temp.price, color='k',zorder=2)plt.scatter(df_temp.date.values[-1], df_temp.price.values[-1], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')plt.ylim(0, df_temp.price.max()*1.68)plt.xticks(ticks=df_temp.date.values[0:Span+1:30],labels=df_temp.date.values[0:Span+1:30],rotation=0)plt.margins(x=0.01)ax = plt.gca()#获取边框ax.spines['top'].set_color('none')    # 设置上‘脊梁’为无色ax.spines['right'].set_color('none')  # 设置上‘脊梁’为无色ax.spines['left'].set_color('none')   # 设置上‘脊梁’为无色plt.grid(axis="y",c=(217/256,217/256,217/256),linewidth=1)         #设置网格线   plt.show()

其中Span设定的是多少天的价格,这里我们使用200天。N_Span代表权重;

df_temp=df.loc[N_Span*Span:(N_Span+1)*Span,:] 代表的是选择到179行为止的数据,即180天。

plt.fill_between()使用单色--红色填充,得到如下效果:


但是一个颜色填充总感觉不够好看,所以下面使用渐变色填充,使用plt.bar()函数实现Spectral_r颜色映射。代码如下:


Span_Date =180  Num_Date =360  #终止日期df_temp=df.loc[Num_Date-Span_Date: Num_Date,:]  #选择从Num_Date-Span_Date开始到Num_Date的180天的数据colors = cm.Spectral_r(df_temp.price / float(max(df_temp.price)))fig =plt.figure(figsize=(6,4), dpi=100)plt.subplots_adjust(top=1,bottom=0,left=0,right=0.9,hspace=0,wspace=0)plt.bar(df_temp.date.values,df_temp.price.values,color=colors,width=1,align="center",zorder=1)plt.plot(df_temp.date, df_temp.price, color='k',zorder=2)plt.scatter(df_temp.date.values[-1], df_temp.price.values[-1], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')plt.ylim(0, df_temp.price.max()*1.68)plt.xticks(ticks=df_temp.date.values[0: Span_Date +1:30],labels=df_temp.date.values[0: Span_Date +1:30],rotation=0)plt.margins(x=0.01)ax = plt.gca()#获取边框ax.spines['top'].set_color('none')   # 设置上‘脊梁’为无色ax.spines['right'].set_color('none')  # 设置上‘脊梁’为无色ax.spines['left'].set_color('none')   # 设置上‘脊梁’为无色plt.grid(axis="y",c=(217/256,217/256,217/256),linewidth=1)   #设置网格线   plt.show()

这里的数据筛选有稍许不同,其中Span_Date设置初始时间,这里设置为180即从起始日开始算的180天。

Num_Date设置的是终止时间。

df_temp=df.loc[Num_Date-Span_Date: Num_Date,:] 则是用loc函数筛选从180天到终止日期的数据。

效果如下:


动态可视化


最后,我们来将这幅图动起来,先将刚刚的绘图部分封装:


def draw_areachart(Num_Date):    Span_Date=180    ax.clear()    if Num_Date<Span_Date:        df_temp=df.loc[0:Num_Date,:]        df_span=df.loc[0:Span_Date,:]        colors = cm.Spectral_r(df_span.price.values / float(max(df_span.price.values)))        plt.bar(df_temp.date.values,df_temp.price.values,color=colors,width=1.5,align="center",zorder=1)        plt.plot(df_temp.date, df_temp.price, color='k',zorder=2)        plt.scatter(df_temp.date.values[-1], df_temp.price.values[-1], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)        plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')        plt.ylim(0, df_span.price.max()*1.68)        plt.xlim(df_span.date.values[0], df_span.date.values[-1])        plt.xticks(ticks=df_span.date.values[0:Span_Date+1:30],labels=df_span.date.values[0:Span_Date+1:30],rotation=0,fontsize=9)    else:        df_temp=df.loc[Num_Date-Span_Date:Num_Date,:]        colors = cm.Spectral_r(df_temp.price / float(max(df_temp.price)))        plt.bar(df_temp.date.values[:-2],df_temp.price.values[:-2],color=colors[:-2],width=1.5,align="center",zorder=1)        plt.plot(df_temp.date[:-2], df_temp.price[:-2], color='k',zorder=2)        plt.scatter(df_temp.date.values[-4], df_temp.price.values[-4], color='white',s=150,edgecolor ='k',linewidth=2,zorder=3)        plt.text(df_temp.date.values[-1], df_temp.price.values[-1]*1.18,s=np.round(df_temp.price.values[-1],1),size=10,ha='center', va='top')        plt.ylim(0, df_temp.price.max()*1.68)        plt.xlim(df_temp.date.values[0], df_temp.date.values[-1])        plt.xticks(ticks=df_temp.date.values[0:Span_Date+1:30],labels=df_temp.date.values[0:Span_Date+1:30],rotation=0,fontsize=9)    
plt.margins(x=0.2) ax.spines['top'].set_color('none') # 设置上‘脊梁’为红色 ax.spines['right'].set_color('none') # 设置上‘脊梁’为无色 ax.spines['left'].set_color('none') # 设置上‘脊梁’为无色 plt.grid(axis="y",c=(217/256,217/256,217/256),linewidth=1) #设置网格线 plt.text(0.01, 0.95,"BTC平均价格($)",transform=ax.transAxes, size=10, weight='light', ha='left') ax.text(-0.07, 1.03, '2013年到2021年的比特币BTC价格变化情况',transform=ax.transAxes, size=17, weight='light', ha='left')
fig, ax = plt.subplots(figsize=(6,4), dpi=100)plt.subplots_adjust(top=1,bottom=0.1,left=0.1,right=0.9,hspace=0,wspace=0) draw_areachart(150)

之后使用matplotlib包的animation.FuncAnimation()函数,之后调用上述编写的draw_areachart(Num_Date)函数。

其中输入的参数Num_Date是如静态可视化中提及的日期作用一样,赋值为np.arange(0,df.shape[0],1)。

最后使用Ipython包的HTML()函数将动画转换成动画页面的形式演示。代码如下:


import matplotlib.animation as animationfrom IPython.display import HTMLfig, ax = plt.subplots(figsize=(6,4), dpi=100)plt.subplots_adjust(left=0.12, right=0.98, top=0.85, bottom=0.1,hspace=0,wspace=0)  animator = animation.FuncAnimation(fig, draw_areachart, frames=np.arange(0,df.shape[0],1),interval=100)HTML(animator.to_jshtml())

函数FuncAnimation(fig,func,frames,init_func,interval,blit)是绘制动图函数。其参数如下:


  • fig 表示绘制动图的画布名称(figure);

  • func为自定义绘图函数,如draw_barchart()函数;

  • frames为动画长度,一次循环包含的帧数,在函数运行时,其值会传递给函数draw_barchart (year)的形参“year”;

  • init_func为自定义开始帧可省略;

  • interval表示更新频率,计量单位为ms;

  • blit表示选择更新所有点,还是仅更新产生变化的点,应选择为True,但mac电脑用户应选择False,否则无法显示。


最后效果就是这样👇


可以看到在过去的一年中,由于机构的兴趣日益增加,比特币上涨超过了6倍,最高突破58000美元/枚,当然可以看到跌起来也是非常恐怖的,关于比特币你怎么看呢,欢迎评论区讨论~

编辑:黄继彦

校对:林亦霖

浏览 27
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报