用 Python 动态可视化,看看比特币这几年
作者 | 刘早起
来源 | 早起Python
头图 | 下载于视觉中国
最近几年,一直站在风口浪尖的比特币被追捧为最佳的投资产品,拥护者们认为这种加密货币是一种类似于黄金的储值工具,可以对冲通胀和美元疲软。其他人则认为,比特币的暴涨只是一个经济刺激措施催生的巨大泡沫,并且必将破裂。
本文就将对比特币2013年到2021年价格进行动态可视化,先看效果:
获取数据
比特币数据很多网站都有,并且也有很多成熟的API,所以取数据非常简单,直接调用API接口即可,下面是获取与写入数据的全部代码
import requests
import json
import csv
import time
time_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 pd
import matplotlib as mpl
from matplotlib import cm
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.animation as animation
from IPython.display import HTML
from datetime import datetime
plt.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=180
N_Span=0
df_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=180ax.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 animation
from IPython.display import HTML
fig, 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美元/枚,当然可以看到跌起来也是非常恐怖的,关于比特币你怎么看呢,欢迎评论区讨论~
点击这里 ???? 关注我们~~~
更多精彩推荐
☞关于深度学习编译器,这些知识你需要知道☞小小几张图,把深度学习讲透彻☞Python 搭建车道智能检测系统☞网易伏羲论文入选 CVPR:AI 感知表情能力或实现巨大突破!
点分享点收藏点点赞点在看
相关文章:

违规用户处理办法
2019独角兽企业重金招聘Python工程师标准>>> 1.简单设置用户信赖状态 给用户设置信任字段,0不可信任,1默认许可(默认值),2可信赖用户 当用户违规后,对其进行惩罚并设置其为 不可信赖状态&#…

linux同步软件
linux同步软件:scp,rsync,inotify,sersync一、scpscp就是secure copy,是用来进行远程文件拷贝的。数据传输使用 ssh,并且和ssh 使用相同的认证方式,提供相同的安全保证 。 与rcp 不同的是,scp 在需要进行验证时会要求你…

C语言内联函数
内联函数也称内嵌函数,它主要解决程序的运行效率。 #####################问题######################################### 函数调用需要建立栈内存环境,进行参数传递,并产生程序执行转移,这些转移都需要时间开销。 有些函数在程序…

Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum. For example, given the array [−2,1,−3,4,−1,2,1,−5,4],the contiguous subarray [4,−1,2,1] has the largest sum 6. Code: class Solution { public:int …

从Python到AI,这条路好走吗?
大家都在学Python的时候,怎么才能让自己更有竞争力?Python 的应用方向有很多,基本每个方向都是大热门,但至今为止,人工智能行业仍处于人才稀缺的情况。正因这样,近几年来,AI 成为了广大 Python …

微信小程序server-1-搭建HTTPS server
一.使用 Node 和 Express 搭建一个 HTTP 服务器 1.在app.js修改小程序通信域名 App({config: {host: // 这个地方填写你的域名},onLaunch () {console.log(App.onLaunch());} }); 2.安装 NodeJS 和 NPM yum install nodejs npm -y node -v 3.编写HTTP服务源码 touch package.j…

被“钱”困住的开源开发者们!
「Given enough eyeballs,all bugs are shallow.」(只要有足够多的眼睛,就可以让所有 Bug 浮现)1997 年,随着《大教堂与集市》的到来,开源新时代的号角正式吹响,也将 Linus 法则深深地烙印在开源…

PHP连接MySQL的2种方法以及防止乱码
PHP的MySQL配置 报错信息:Class mysqli not found in Answer: 1.在conf/php.ini中,在vim用"/php_mysql"搜索到extensionphp_mysql.dll,去掉前面的";", 同时在下面增加extensionphp_mysqli.dll; 注意后面那个dll多了个i 2."/extension_dir&…

nodejs npm install -g 全局安装和非全局安装的区别
1. npm install xxx -g 时, 模块将被下载安装到【全局目录】中。 【全局目录】通过 npm config set prefix "目录路径" 来设置。 比如说,当我们使用了npm install -g express安装了express框架后, 我们就可以在电脑里的某一个文件夹…

Windows平台上实现P2P服务(三)
2019独角兽企业重金招聘Python工程师标准>>> 我们已经建立好一个UDP的服务程序了,下面我们要给这个服务程序添加服务内容了。 其服务内容将根据通讯的客户端请求来进行定义和处理。首先我们再回顾一下通讯内容的定义: /// <summary>信息…

ASP.NET 2.0数据处理之高级分页/排序
GridView控件中的"选择"操作纯粹是一个UI概念,它的SelectedIndex属性与表格的可视数据行中的当前被选中的行的索引相对应。如果你启用了表格的分页和排序功能,在执行分页或排序操作之后,SelectedIndex的值仍然不会变化,…

rpcgen的简单讲解及例子程序
rpcgen 简介 rpcgen可以自动生成RPC服务器程序的大多数代码,它的输入为一个规格说明文件,它的输出为一个C语言的源程序。规格文件(*.x)包含常量、全局数据类型以及远程过程的声明。Rpcgen产生的代码包含了实现客户机和服务器程序所…

Python 捕获警告
来源 | 写代码的明哥责编 | 寇雪芹头图 | 下载于视觉中国警告不是异常你是不是经常在使用一些系统库或者第三方模块的时候,发现一些既不是异常也不是错误的警告信息?这些经常出现的警告信息,容易让新手造成一些误判,以为是程序出错…

python装饰器+迭代器+生成器
1.函数嵌套:在调用一个函数的过程中,调用了其他函数 def f1():x1def f2():print(from f2)f2() f1() 2.名称空间与作用域 a. 名称空间:存放名字与变量值绑定关系的地方 (1)内置名称空间:在python解释器启动…

ASP.NET中绑定枚举类型
在项目开发中好多地方用了枚举,要把枚举显示到下拉列表框中我们平常的方法就是在下拉列表控件中一个一个添加进去!这样做也行但如果我的枚举类型中的枚举值一旦改变,那么你就得满世界的去找然后再修改很麻烦。这里我有反射动态的绑定枚举值就…

Java 领域offer收割:程序员黄金 5 年进阶心得!
怎样才能拿到大厂的offer?没有掌握绝对的技术,那么就要不断的学习。如何拿下阿里等大厂的offer的呢,今天分享一个秘密武器,资深架构师整理的Java核心知识点,面试时面试官必问的知识点,篇章包括了很多知识点…

视频专辑:Photoshop基础视频教程
为什么80%的码农都做不了架构师?>>> 专辑:Photoshop基础视频教程 简介:Photoshop基础视频教程 1 1. 软件界面介绍 [photoshop基础教程] 2013-10-31 11:56 | 播放(6) | 评论(0) | 时长:42:44 2 2. 工行LOGO分析及制作1 [photoshop基础教程…

linux运维如何月薪过万?(收藏自用)
作者:汤哥在北京链接:https://www.zhihu.com/question/27505552来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。IT行业,是近些年相当火的一个专业,从事于IT行业的工作人员也…

当深度学习遇上图: 图神经网络的兴起 | 赠书
什么是图也许我们从来没有意识到,我们正生活在一个充满图的世界。例如,我们最熟悉的社交网络(如下图所示),就是一个最典型的图。在计算机领域,我们通常用图指代一种广义的抽象结构,用来表示一堆…

Asp.net 2.0 中将网站首页生成静态页的一个比较好的方法
做网站时,有时为了提高性能会将网站首页生成静态页(当然, Asp.net中页面缓存也是一个不错的选择了 将页面生成静态的方法有多中,据不完全统计有N种(N>1) 呵呵 以下的方法来自 "孟子E " 解释的方法 代码如下 protected override void Render(HtmlTextWriter wri…

[转]解决Eclipse中编辑xml文件的智能提示问题
转自:http://hi.baidu.com/cghroom/item/48fd2d0dc1fc23c675cd3c3e 摘要: Eclipse for Android xml 文件代码自动提示功能,介绍Eclipse 编辑器中实现xml 文件代码自动智能提示功能,解决eclipse 代码提示失效、eclipse 不能自动提…

温水里的程序员,技术将淘汰一切。
七月,炎炎的夏日,疯狂的暴雨不分昼夜,侵袭着这座城。早上七点,我骑着摩拜单车出发去往地铁站,誓死如归一般的,挤进地铁。像往常一样,骑车、挤地铁、打卡上班。相 信大家都跟我一样,未…

ASP.net 2.0下应用程序离线信息
ASP.net 2.0 有一个新特性,就是支持应用程序离线信息。 什么是离线信息呢?以前我们在更新应用程序,导至asp.net应用程序重启,应用程序的用户通常会显示不友好的错误信息,或者IE一直显示加载状态。 ASP.net 2.0支持您…

Lync server 2013 之office web apps server 搭建步骤
office web apps server 搭建步骤:一、.NET Framework 4.5 节点下的HTTP 激活.NET Framework 3.5Windows Identity Foundation 3.5Add-WindowsFeature Web-Server,Web-Mgmt-Tools,Web-Mgmt-Console,Web-WebServer,Web-Common-Http,Web-Default-Doc,Web-Static-Conte…

360数科发布2020全年财报:全年收入上涨47.1%,科技为运营效率提供第一动力
3月16日,360数科发布2020年第4季度及全年未经审计的财务报告。2020财年,360数科实现收入135.64亿元,较2019年92.2亿元增长47.1%;非美国会计准则(Non-GAAP)下净利润为37.97亿元,较2019年27.52亿元…

内存分配器memblock【转】
转自:http://blog.csdn.net/kickxxx/article/details/54710243 版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[-] 背景 Data structurememblock initializationmemblock API memory和reserved regionmemblock_reservedmemblo…

with admin option /with grant option
1. with admin option是用在系统权限上的,with grant option是用在对象权限上的。 SQL> grant create synonym to scott with grant option;grant create synonym to scott with grant option *第 1 行出现错误:ORA-01939: 只…

第四层到第七层的高层交换技术及其应用
1 前言Internet的特点就是不断变化发展,目前网络上的信息量和业务量都呈现爆炸性的增长趋势。不断增长的负荷和新需求的出现,使得用单台服务器处理应用服务的结构已成为过去,取而代之的是以单一虚拟IP地址(VIP)来代表整个服务器集群&#x…

赠书 | 315之后,无人旁观时我们是谁
315的曝光,让人脸信息被随意采集、简历被低价出卖等话题受到公众热议。然而,不知道有多少人,直到这一场晚会才知道,原来自己始终是被悄悄“出卖”的人。智联招聘声称拥有1.8亿用户,视用户信息安全与隐私保护为自己“生…

bugzilla部署
Centos6.8部署bugzilla apache mysql1.apache可以使用系统自带的apache服务2.安装mysql:yum –y installmysql mysql-server //使用yum安装vi /etc/my.cnf //编辑mysql配置文件default-character-set utf8 //在mysql_safe段添加字符集支持service mysq…