数据入口:【每周挑战】比特币10年价格数据可视化和量化分析 - Heywhale.com

本数据集包含 2014 - 2024 的比特币美元价格数据,具体包含比特币每日的开盘价、最高价、最低价、收盘价以及成交量等关键信息。数据说明如下:

字段说明
Date日期,比特币的交易日期
Open (Open price per unit)开盘价,每天比特币交易开始时的价格
High (Highest price per unit)最高价,每天交易期间比特币的最高成交价格
Low最低价,每天交易期间比特币的最低成交价格
Close (Adj Close)收盘价,指当天交易结束时的价格,调整后的收盘价考虑了股息等因素
Volume成交量,每天比特币的交易量,通常以比特币的单位表示

本文将从以下方面进行:价格波动与趋势分析、成交量与市场波动关系分析、价格异常波动检测和成交量异常值检测。

一:数据预处理

import pandas as pd
file_path = 'BTC-USD (2014-2024).csv'
df = pd.read_csv(file_path)
df1 = df[['Date', 'Adj Close', 'Volume']]
df1

这里常用收盘价作为当日比特币价格,所以可以去除其他与数据分析无关的列,数据样貌如下:

df1.info()

数据概览如下:

有与观察到数据存在空值,可能会影响后续分析,可以先去除空值:

df1 = df1.dropna(subset=['Adj Close', 'Volume'])

二:价格波动与趋势分析

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

df1['Date'] = pd.to_datetime(df1['Date'])

start_index_2014 = df1[df1['Date'].dt.year == 2014].index[0]

plt.figure(figsize=(14, 7))
plt.plot(df1['Date'], df1['Adj Close'], label='Adjusted Close Price')
plt.title('Adjusted Close Price Trend from 2014')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.gca().xaxis.set_major_locator(mdates.YearLocator())  
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y')) 
plt.gca().set_xlim(df1['Date'][start_index_2014], df1['Date'].iloc[-1])  
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

rolling_window = 30
df1['Rolling Mean'] = df1['Adj Close'].rolling(window=rolling_window).mean()
df_reduced['Rolling Std'] = df1['Adj Close'].rolling(window=rolling_window).std()

plt.figure(figsize=(14, 7))
plt.plot(df1['Date'], df1['Rolling Mean'], label='30-day Rolling Mean')
plt.plot(df1['Date'], df1['Rolling Std'], label='30-day Rolling Std Dev')
plt.title('30-day Rolling Mean and Standard Deviation from 2014')
plt.xlabel('Date')
plt.ylabel('Price')
plt.legend()
plt.gca().xaxis.set_major_locator(mdates.YearLocator())  
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y')) 
plt.gca().set_xlim(df1['Date'][start_index_2014], df1['Date'].iloc[-1]) 
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()

绘制的两个图分别为比特币的调整收盘价趋势图以及30天滚动平均值和标准差的图表

这段代码主要分为两部分:第一部分是绘制股票的调整收盘价趋势图,第二部分是绘制该比特币的30天滚动平均值和标准差:

第一部分:绘制调整收盘价趋势图

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

这里导入了matplotlib.pyplot用于绘图,matplotlib.dates用于日期处理。

转换日期格式

df1['Date'] = pd.to_datetime(df1['Date'])

将数据框df1中的’Date’列转换为pandas的datetime对象,这样可以在绘图时正确处理日期。

找到2014年的起始索引

start_index_2014 = df1[df1['Date'].dt.year == 2014].index[0]

通过筛选出年份为2014的日期,并获取第一个索引,这样就可以在图表中从2014年开始展示数据。

设置绘图窗口

plt.figure(figsize=(14, 7))

创建一个绘图窗口,设置大小为14x7英寸。

绘制调整收盘价趋势

plt.plot(df1['Date'], df1['Adj Close'], label='Adjusted Close Price')

使用matplotlib的plot函数绘制调整收盘价随日期变化的折线图,并设置图例标签为’Adjusted Close Price’。

设置图表标题和轴标签

plt.title('Adjusted Close Price Trend from 2014')
plt.xlabel('Date')
plt.ylabel('Price')

设置图表的标题和x轴、y轴的标签。

添加图例

plt.legend()

在图表上添加图例。

设置x轴的主定位器和格式化器

plt.gca().xaxis.set_major_locator(mdates.YearLocator())
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y'))

设置x轴的主定位器为每年,并设置格式化器为年份格式。

设置x轴的显示范围

plt.gca().set_xlim(df1['Date'][start_index_2014], df1['Date'].iloc[-1])

设置x轴的显示范围从2014年的起始索引到数据框的最后一个日期。

设置x轴标签的旋转角度

plt.xticks(rotation=45)

将x轴上的日期标签旋转45度,以便更清晰地显示。

调整布局

plt.tight_layout()

自动调整子图参数,使之填充整个图表区域,并防止标签重叠。

显示图表

plt.show()

显示之前设置和绘制的图表。

第二部分:绘制30天滚动平均值和标准差

设置滚动窗口大小

rolling_window = 30

设置滚动窗口的大小为30天。

计算30天滚动平均值

df1['Rolling Mean'] = df1['Adj Close'].rolling(window=rolling_window).mean()

计算调整收盘价的30天滚动平均值,并将结果存储在新的列’Rolling Mean’中。

计算30天滚动标准差

df1['Rolling Std'] = df1['Adj Close'].rolling(window=rolling_window).std()

计算调整收盘价的30天滚动标准差,并将结果存储在新的列’Rolling Std’中。

绘制滚动平均值和标准差趋势图 

这部分代码与第一部分绘制调整收盘价趋势图的步骤非常相似,这里绘制了两条线:一条是30天滚动平均值,另一条是30天滚动标准差。

整体而言,这段代码是用于分析比特币数据的,通过绘制趋势图来可视化比特币价格的走势以及波动性。

三:成交量与市场波动关系分析

import seaborn as sns
import numpy as np

df1['Daily Returns'] = df1['Adj Close'].pct_change()

df1['Volume Change'] = df1['Volume'].pct_change()

df1 = df1.dropna()

correlation = df1[['Daily Returns', 'Volume Change']].corr()

plt.figure(figsize=(14, 7))
sns.scatterplot(x='Daily Returns', y='Volume Change', data=df1)
plt.title('Scatter Plot of Daily Returns vs Volume Change')
plt.xlabel('Daily Returns of Adjusted Close')
plt.ylabel('Daily Change in Volume')
plt.grid(True)
plt.show()

correlation, np.corrcoef(df1['Daily Returns'], df1['Volume Change'])

绘制的关于日常收益与交易量变化的散点图如下:

这段代码是用来分析比特币市场数据中的日常收益和交易量变化之间的关系。以下是代码的详细解释:

import seaborn as sns
import numpy as np
  • seaborn(简称sns)是一个基于matplotlib的数据可视化库,它提供了更美观和高级的绘图样式。
  • numpy(简称np)是Python中用于科学计算的核心库之一,提供了强大的数学函数和矩阵处理功能。
df1['Daily Returns'] = df1['Adj Close'].pct_change()
  • 这行代码为df1数据框添加了一个新列'Daily Returns'
  • 'Adj Close'是调整后的收盘价,pct_change()方法计算了该列相邻元素之间的百分比变化,即日常收益。
df1['Volume Change'] = df1['Volume'].pct_change()
  • 这行代码为df1数据框添加了一个新列'Volume Change'
  • 'Volume'是交易量,pct_change()同样用于计算相邻交易日交易量的百分比变化。
df1 = df1.dropna()
  • 使用dropna()方法删除含有缺失值的行,因为pct_change()方法会在数据框的开始处产生一个NaN值。
correlation = df1[['Daily Returns', 'Volume Change']].corr()
  • 这行代码计算了'Daily Returns''Volume Change'之间的相关系数。
  • .corr()方法返回一个相关系数矩阵。
plt.figure(figsize=(14, 7))
sns.scatterplot(x='Daily Returns', y='Volume Change', data=df1)
plt.title('Scatter Plot of Daily Returns vs Volume Change')
plt.xlabel('Daily Returns of Adjusted Close')
plt.ylabel('Volume Change')
plt.grid(True)
plt.show()
  • plt.figure(figsize=(14, 7))设置了图形的大小为14x7英寸。
  • sns.scatterplot()绘制了一个散点图,其中x轴是日常收益,y轴是交易量变化。
  • plt.title()plt.xlabel()plt.ylabel()分别设置了图表的标题和坐标轴标签。
  • plt.grid(True)添加了网格线。
  • plt.show()显示了图表。
correlation
  • 第一部分correlation是之前计算得到的相关系数矩阵。
  • np.corrcoef()使用numpy库计算两个序列的相关系数,并返回一个相关系数矩阵。

这段代码的最终输相关系数矩阵:

通过对“Adj Close”(调整后的收盘价)和“Volume”(交易量)的日变动率进行相关性分析,我们可以看到它们之间的相关系数约为0.047。这表明存在一定程度的正相关关系,但这种关系相对较弱。这意味着当“Adj Close”价格变动时,“Volume”的变动在统计上并不是非常显著。

从散点图中可以看出,虽然有一定的趋势表明价格变动和交易量变动可能同向,但这种关系并不明显。散点图中的点相对分散,说明没有强烈的线性关系。

总的来说,虽然存在一些关系,但“Adj Close”和“Volume”的波动之间的关联性并不强。这意味着其他因素可能对交易量的波动有更大的影响,或者两者之间的关联可能不是线性的,而是更加复杂。

四:价格异常波动检测和成交量异常值检测

from scipy import stats

adj_close_z_threshold = stats.norm.ppf(0.99)
volume_z_threshold = stats.norm.ppf(0.99)

df1['Adj Close Z-Score'] = stats.zscore(df1['Adj Close'])

df1['Volume Z-Score'] = stats.zscore(df1['Volume'])

adj_close_outliers = df1[df1['Adj Close Z-Score'].abs() > adj_close_z_threshold]
volume_outliers = df1[df1['Volume Z-Score'].abs() > volume_z_threshold]

(adj_close_outliers, volume_outliers)

根据结果知:调整收盘价的异常值有122条,成交量的异常值有96条。

这段代码是用来识别数据集中的异常值,具体来说,它处理的是比特币市场的调整收盘价(Adj Close)和成交量(Volume)的异常值。

from scipy import stats

这行代码从scipy库中导入stats模块,该模块提供了大量的统计函数,包括概率分布、统计测试和其他相关的统计计算。

adj_close_z_threshold = stats.norm.ppf(0.99)

这行代码使用stats.norm.ppf函数计算正态分布的分位数。ppf代表的是“百分位点函数”(Percent Point Function),也就是累积分布函数(CDF)的逆函数。这里传入的参数是0.99,意味着计算的是正态分布的第99百分位点,也就是上阈值,用于确定Z分数高于这个值的观测值被认为是异常值。

volume_z_threshold = stats.norm.ppf(0.99)

与上一行类似,这行代码计算了成交量(Volume)的正态分布的第99百分位点,用于识别成交量的异常值。

df1['Adj Close Z-Score'] = stats.zscore(df1['Adj Close'])

这行代码计算了调整收盘价(Adj Close)的Z分数。stats.zscore函数计算了数据的标准化得分,即每个数据点与均值的差值除以标准差。Z分数表示了每个观测值距离均值的标准化距离,可以用来识别异常值。

df1['Volume Z-Score'] = stats.zscore(df1['Volume'])

与上一行类似,这行代码计算了成交量(Volume)的Z分数。

adj_close_outliers = df1[df1['Adj Close Z-Score'].abs() > adj_close_z_threshold]

这行代码使用之前计算出的阈值来识别调整收盘价的异常值。它通过比较每个观测值的Z分数的绝对值与阈值,找出那些绝对值大于阈值的观测值,并将它们作为异常值保存到adj_close_outliers变量中。

volume_outliers = df1[df1['Volume Z-Score'].abs() > volume_z_threshold]

这行代码与上一行类似,但它用于识别成交量的异常值。

(adj_close_outliers, volume_outliers)

最后,这行代码将调整收盘价和成交量的异常值作为元组返回。这个元组包含两个DataFrame对象,adj_close_outliersvolume_outliers,分别包含了调整收盘价和成交量的异常值记录。

总结来说,这段代码的目的是识别和返回比特币市场数据集中调整收盘价和成交量的异常值。通过计算Z分数并与预先设定的阈值比较,它能够找出那些在统计上显著不同于其他观测值的记录。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐