立即开始增强您的 PostgreSQL。
作者 Junaid Ahmed
了解时间序列动态对于各行各业的数据驱动型决策越来越重要。随着时间的推移思考数据使公司变得敏捷和具有竞争力,因为他们可以从特定时间点获得洞察力,以深入了解发生的事情,更重要的是,为什么会发生。借助 时间序列分析 和预测,公司可以提高运营绩效并获得显着的竞争优势。
从开发人员的角度来看,您可以使用各种工具和编程语言来有效地执行时间序列分析和 预测。每种方法都有其优点和特点,但 Python 和 TimescaleDB 在我的时间序列分析和预测工具集中发挥着主导作用。
Python 因其简单性和多功能性而被广泛使用。该框架附带了用于数据操作和建模的广泛库,例如 pandas、NumPy 和 scikit-learn。它还提供了适用于时间序列预测的预测库(如 Statsmodels 和 Prophet),使高级统计建模和预测方法变得更容易。
另一方面,我们有 TimescaleDB,这是一个为有效处理此类数据而开发的数据库。其创新的架构简化了时间序列数据的收集、管理和分析过程。
Python 和 TimescaleDB 共同使组织能够发掘时间序列数据中的隐藏价值并进行预测。在本教程中,我们将探索时间序列分析的不同阶段,从数据预处理到模型评估。我们还将使用最先进的 超级函数(它们擅长从时间戳数据中挖掘意义)来做出准确的预测。
在本教程中,您将学习如何使用五年多的历史股票数据来分析和预测股票市场趋势。主要目标是建立一个模型,该模型可以同时实现两个目标:它应该是预测性的,并且使用过去的数据作为参考。我们将探索趋势以了解股票市场的下一步走势,这将通过以下方式完成
预测短期走势:一些交易者使用这些信息来判断股票价格在短期内是涨还是跌,并据此做出决策。
了解波动性:可视化数据并识别波动性可以帮助说明风险管理功能。
识别长期趋势:使用预测算法,我们可以预测 10 年趋势,以构建适应性强的投资策略,从而在长期内提供更好的增长机会。
为了实现这些目标,我们将采用各种数据分析技术和机器学习算法,包括
数据摄取:我们将使用 TimescaleDB 进行数据存储和检索,因为它专为处理时间序列数据而设计。
探索性数据分析:我们将使用 Python 库(如 Matplotlib、Seaborn 和 Plotly)来识别数据中的趋势。
机器学习模型:我们将探索各种模型,例如 ARIMA、LSTM NN 和回归分析,以确定最精确的模型。
特征工程:使用机器学习模型和 TimescaleDB 中的超级函数,我们将提取可以帮助预测股票价格的最重要特征。
模型评估:将使用评估指标来衡量预测模型的性能。这些指标包括 RMSE(均方根误差)、MAE(平均绝对误差)和 R 方。
该数据集经过精心策划,有助于进行此分析,其中包含每个交易日的以下属性
日期:交易日,格式为 yy-mm-dd,为每个数据点提供时间锚点。
开盘价:股票在开盘时的价格,可以洞察当天的起始估值。
最高价:交易日达到的最高价格,表明市场估值达到峰值。
最低价:交易日达到的最低价格,突出了当天市场估值的低谷。
收盘价:股票的收盘价,这对于了解当天的最终市场估值至关重要。
成交量:当天交易的股票总数,反映了市场活动和流动性。
名称:股票代码,用作每家公司的唯一标识符。
如果您觉得需要后退一步,请查看我们的 Python 时间序列分析指南。
在摄取数据之前,请确保您的 TimescaleDB 实例已启动并运行。您可以在各种操作系统和云平台上安装 TimescaleDB。有关安装说明,请参阅这些官方 TimescaleDB 文档。
安装 TimescaleDB 后,创建您的第一个实例 并连接到您的 PostgreSQL 数据库。创建一个数据库,然后创建一个与 CSV 文件架构匹配的表。对于时间序列数据,您应该使用 TimescaleDB 函数 create_hypertable () 将此表转换为超表。我已经创建了超表。您可以使用以下代码为您拥有的股票数据创建一个超表
CREATE TABLE stock_data (
date DATE,
open FLOAT,
high FLOAT,
low FLOAT,
close FLOAT,
volume BIGINT,
name TEXT
);
SELECT create_hypertable('stock_data', 'date');
创建超表后,我们可以使用 复制命令 将数据从 CVS 文件加载到超表中。
如果尚未安装这些库,请使用以下代码块安装它们
pip install psycopg2
pip install pandas
pip install matplotlib
pip install plotly
安装所需的库后,我们可以在数据库和笔记本之间建立连接并导入数据。现在,您可以使用以下代码建立连接
con = psycopg2.connect(
host='your_host',
port='your_port',
database='your_database',
user='your_username',
password='your_password'
)
替换数据库凭据、用户名和密码进行连接。下一步是创建一个游标对象,它将帮助您与数据库交互并执行查询。
# Create a cursor
cur = conn.cursor()
定义 SQL 查询,调整“stock_data”表和所需的列
query = sql.SQL(SELECT * FROM stock_data LIMIT 10)
# Execute the query
cursor.execute(query)
之后,您可以使用以下命令获取所有行
# Fetch the results
records = cur.fetchall()
最佳做法是在完成后关闭游标和连接
# Close the cursor and connection
cur.close()
conn.close()
如果您想直接在 Python 脚本中查看输出,请打印记录
for record in records:
print(record)
获取最新股票数据的另一种方法是使用雅虎财经软件包。为了提取数据并以合适的格式显示,我们使用了以下代码
import yfinance as yf
import pandas as pd
from datetime import datetime, timedelta
# Define the list of stock tickers and the time period
tickers = [
'AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'FB', 'NVDA', 'NFLX', 'INTC', 'AMD',
'IBM', 'ORCL', 'CSCO', 'ADBE', 'PYPL', 'QCOM', 'TXN', 'AVGO', 'CRM', 'SAP'
]
start_date = '2019-05-17'
end_date = '2024-05-17' # Use today's date
代码块定义了用于数据检索的雅虎财经模块和用于数据操作的 pandas。然后,我们定义了一个股票代码列表,其中包括全球各种表现最佳的股票,如苹果和特斯拉。由于我们要查找过去五年的数据,因此我们定义了开始日期和结束日期。
# Function to download and format data for a single stock
def download_and_format_stock_data(ticker, start_date, end_date, retries=3):
for i in range(retries):
try:
stock_data = yf.download(ticker, start=start_date, end=end_date)
if not stock_data.empty:
stock_data.reset_index(inplace=True)
stock_data['Name'] = ticker
stock_data = stock_data[['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Name']]
stock_data.columns = ['date', 'open', 'high', 'low', 'close', 'volume', 'name']
return stock_data
except Exception as e:
print(f"Attempt {i+1} failed for {ticker}: {e}")
return pd.DataFrame()
# Download and format data for all tickers
all_stocks_data = pd.concat([download_and_format_stock_data(ticker, start_date, end_date) for ticker in tickers])
# Display the first few rows of the combined data
print(all_stocks_data.head())
# Save to CSV
file_path = 'formatted_stock_data2.csv'
all_stocks_data.to_csv(file_path, index=False)
print(f"Data saved to {file_path}")
它下载并重新格式化数据,然后将其格式化为包含日期、开盘价、最高价、最低价、收盘价、成交量和股票名称列的 DataFrame。然后,该方法尝试下载数据最多三次,然后再继续。
接下来,它向下遍历股票代码列表的 for 循环,下载并将它们转换为每个代码的 DataFrame,将它们连接成一个,打印前几行,并将它们保存为 CSV。
代码输出如下所示
现在,让我们分析数据以揭示隐藏的模式。
通过 EDA,我们将深入研究历史股票价格走势的深处,以了解波动性、趋势、季节性和可能无法一目了然的异常情况。下图展示了基于数据集的股票市场的两个不同方面
最高平均交易量:这是第一个图表,显示了数据集中交易量最高的公司的交易量随时间的变化。该图表显示了一些非常繁忙的日子,这表明投资者活动增加,或者可能是股票受到市场特别影响的情况。
最高平均波动率:第二个图表显示了平均波动率最高的公司的波动率(使用收盘价的 30 天滚动标准差作为代理)。这家公司经历了更明显的价格波动,这意味着投资者面临更高的风险和潜在的更高回报。
让我们使用 Plotly 创建一个交互式图表,以显示特定时区的交易情况,并提供放大和缩小选项。
导入绘图所需的库。
import plotly.graph_objects as go
import pandas as pd
过滤 DataFrame 以获取 2024 年的数据以及平均交易量最高的公司
max_volume_df_2024 = max_volume_df[(max_volume_df['date'] >= pd.Timestamp('2024-01-01')) & (max_volume_df['date'] <= pd.Timestamp('2024-5-16'))]
使用 Plotly 创建交互式图表
fig = go.Figure()
添加交易量的条形图
fig.add_trace(go.Bar(x=max_volume_df_2024['date'], y=max_volume_df_2024['volume'], marker_color='purple'))
更新布局以获得更好的视觉外观
fig.update_layout(
title=f'Trading Volume for {max_volume_company["name"]} in 2024',
xaxis_title='Date',
yaxis_title='Volume',
template='plotly_white',
xaxis_rangeslider_visible=True # Enable the range slider for zooming
)
现在使用图形函数显示图形
fig.show()
该图的输出显示了 TSLA 公司在 2024 年各个时区的交易量
交互式图表显示了全年交易量的显着波动。这些波动可能表明投资者对市场事件、收益公告或其他直接影响公司的新闻的反应。交易量峰值突出了市场兴趣增加或对外部因素做出反应的时期。
让我们深入研究使用 Python 和 TimescaleDB 强大功能进行的一些基本统计分析。我们的目标是conduct对我们的数据集进行统计计算。这可能涉及 计算标准差、均值或任何其他与我们分析相关的 统计函数。
让我们从对数据集进行一些描述性分析开始。首先,让我们在 Python 中找到数据集的摘要。
# Print summary statistics
print(data.describe())
输出如下所示
股票数据摘要显示 23,921 个数据点,平均开盘价为 190.49 美元,平均交易量为 3110 万股。价格和交易量的标准差很高,反映出显着的可变性。价格从最低 12.07 美元到最高 1426.00 美元不等。
开盘价中位数为 138.68 美元,第 75 个百分位数为 229.34 美元。记录的最高交易量为 9.14 亿股。本摘要提供了对指定时期内股票整体价格范围和交易活动的见解。
# Get the row count
row_count = len(data)
# Print formatted output
print("approximate_row_count")
print("----------------------")
print(row_count)
Timescale 的超函数可帮助您使用更少的代码行有效地分析时间序列数据。例如,通过利用 TimescaleDB 的 approximate_row_count() 函数,我们可以计算数据集的总行数。获取行数的代码是
ANALYZE stock_data;
SELECT * FROM approximate_row_count('stock_data');
预期输出为
现在让我们探索对数据集的全面统计分析。
这是我们用来计算开盘价列的统计数据的代码
import pandas as pd
import numpy as np
# Assuming stock_data is already defined and contains the dataset
# Convert 'date' column to datetime if it's not already in datetime format
data['date'] = pd.to_datetime(data['date'])
# Set 'date' as the index
data.set_index('date', inplace=True)
# Group data by daily intervals and calculate statistics for the 'open' price
daily_summary = data['open'].resample('D').agg(
stats1D=lambda x: (np.mean(x), np.std(x), x.skew()) if not x.empty else np.nan
)
# Remove rows with NaN values (if any)
daily_summary = daily_summary.dropna()
# Print the result
print(daily_summary)
使用 TimescaleDB 的 stats_agg() 超函数,我们可以有效地生成统计指标,例如单个变量在定义的时期内的均值、标准差等,从而可以对时间序列模式进行有意义的研究。以下是您可以使用的示例代码
WITH t AS (
SELECT
time_bucket('1 day'::interval, "date") AS dt,
stats_agg(open) AS stats1D
FROM stock_data
WHERE Name = 'AAL'
GROUP BY time_bucket('1 day'::interval, "date")
)
SELECT
average(stats1D) AS avg_open,
stddev(stats1D) AS stddev_open,
skewness(stats1D) AS skewness_open
FROM t;
输出
Python 和 TimescaleDB 上述计算的输出预计为:
这些值可以用作预测模型的输入。例如,一种交易策略可能涉及在均值相对于历史数据较低且波动性下降时买入。
现在,让我们找出过去几年中表现最佳的两只股票之间的相关性。
执行代码后,我们发现表现最佳的两只股票 ADBE 和 AVGO 之间存在相关性。Adobe (ADBE) 和 Broadcom (AVGO) 从 2023 年 2 月到 2024 年 5 月的相关性结果显示出极高的正相关性,始终高于 0.999。这表明这两只股票的价格走势高度同步。
如此强的相关性表明,两只股票对市场状况的反应相似,这有助于预测其未来价格并管理投资组合中的风险。同比比较显示,相关性略有增加,表明随着时间的推移同步性越来越高。这种持续的高相关性有助于投资者根据这些股票之间可预测的关系做出明智的决策。
现在我们已经通过可视化和统计分析发现了趋势,让我们构建并对股票价格进行预测。
预测股票价格涉及根据历史数据、市场趋势和其他影响因素预测未来价值。适合股票价格的预测模型通常包括时间序列分析和机器学习算法。以下是一些流行的模型
ARIMA(自回归综合移动平均线):一种经典的时间序列预测模型,它通过其组件捕获数据的不同方面,如趋势和季节性。
LSTM(长短期记忆网络):一种能够学习序列预测问题中的顺序依赖性的递归神经网络 (RNN),适用于股票价格的波动性。
Prophet:由 Facebook 开发,Prophet 专为预测每日观察结果而设计,这些观察结果在不同的时间尺度上显示出模式。它对缺失数据和趋势变化具有鲁棒性,并且通常可以很好地处理异常值。查看有关 使用 Prophet 进行时间序列预测 的教程以了解更多信息。
XGBoost:虽然不是传统的预测模型,但 XGBoost 可用于时间序列预测,方法是创建滞后特征并使用其强大的梯度提升框架来预测未来的股票价格。
在这里,我们将重点介绍构建一个简单的 ARIMA 模型来进行股票价格预测。该过程涉及数据准备、模型拟合和参数调整。根据相关性结果和波动性分析,我们选择了 AVGO 股票来构建该模型,因为它显示了过去一年中表现最佳和波动最大的股票。
以下代码展示了时间序列分析的典型工作流程,包括数据预处理、平稳性检验和 ARIMA 模型拟合
# Convert the date column to datetime and set it as the index
data['date'] = pd.to_datetime(data['date'])
data.set_index('date', inplace=True)
# Filter for a specific stock,
avgo_df = data[data['name'] == 'AVGO']['close'].asfreq('B')
# Check for stationarity
result = adfuller(avgo_df.dropna())
print('ADF Statistic:', result[0])
print('p-value:', result[1])
# If the series is not stationary, differencing might be necessary
# Fit the ARIMA model
model = ARIMA(avgo_df, order=(5,1,0)) # Example order, needs optimization
model_fit = model.fit()
# Summary of the model
print(model_fit.summary())
代码片段的输出如下
鉴于 ADF 测试结果和 p 值,时间序列数据似乎是非平稳的,需要在拟合 ARIMA 模型之前进行额外的预处理过程,例如差分。此外,诊断测试揭示了 ARIMA 模型拟合的质量,以及自相关和异方差等可能的问题。
让我们对 ARIMA 模型进行一些差分
# Perform differencing
differenced_series = avgo_df.diff().dropna() # Compute the difference and remove NaN values
# Check for stationarity after differencing
result_diff = adfuller(differenced_series)
print('ADF Statistic after differencing:', result_diff[0])
print('p-value after differencing:', result_diff[1])
代码片段的输出显示
差分后的 ADF 检验统计量显着为负,p 值为零,表明强烈反对非平稳性原假设的证据。这表明差分序列是平稳的,适合使用 ARIMA 模型进行建模。现在,我们可以继续进行模型拟合和预测。
拟合新结果后模型的总结如下
系数和诊断测试表明拟合的模型充分捕捉了时间序列的动态。
标准化残差:标准化残差表示预测股票价格与实际股票价格之间的差异,通过其估计标准差进行标准化。这些残差有助于评估模型的拟合优度,较小的残差表示拟合更好。
直方图和估计密度:直方图提供了误差分布的直观表示。相比之下,估计密度图(核密度估计 - KDE)对直方图进行了平滑处理,以估计潜在的概率密度函数。符号 N(0,1) 表示标准正态分布,其中均值为零,方差为一。以零为中心的钟形曲线表明误差呈正态分布。
正态 Q-Q 图:正态 Q-Q 图将标准化残差与标准正态分布的理论分位数进行比较。如果图上的点落在一条直线上,则表明残差呈正态分布。偏离直线表示偏离正态性,例如偏度或重尾分布。
自相关图:自相关图也称为自相关函数图,显示了残差在不同滞后阶数下的自相关系数。某些滞后阶数下的显着自相关表明残差中存在模型未捕获的模式或结构。这有助于识别数据中模型应考虑的任何剩余时间依赖性。
评估预测模型的性能对于了解其准确性和可靠性至关重要。让我们使用两个指标来评估模型的性能:平均绝对误差和均方根误差。平均绝对误差:衡量一组预测中误差的平均幅度,而不考虑其方向。此指标的代码为
from sklearn.metrics import mean_absolute_error
# Calculate MAE
mae_diff = mean_absolute_error(differenced_series[1:], train_predictions_diff)
print("MAE:", mae_diff)
均方根误差:衡量误差平方平均值的平方根。它对较大的误差赋予更高的权重。该指标的代码为
from sklearn.metrics import mean_squared_error
# Make predictions on the training data
train_predictions_diff = model_fit_diff.predict(start=differenced_series.index[1], end=differenced_series.index[-1])
# Align the indices of the differenced series and predictions
train_predictions_diff = train_predictions_diff[differenced_series.index[1]:]
# Calculate RMSE
rmse_diff = np.sqrt(mean_squared_error(differenced_series[1:], train_predictions_diff))
print("RMSE:", rmse_diff)
这些指标的结果是
指标 | 值 |
RMSE(均方根误差) | 14.122 |
MAE(平均绝对误差) | 9.2202 |
较低的 RMSE 和 MAE 值表示更好的性能,表明 ARIMA 模型的预测值相对接近实际值。
分析股票数据的另一种方法是使用 TimescaleDB 金融数据库来获取有关开盘价、收盘价、最高价和最低价的实时数据。以下是您如何在 Python 中从 TimescaleDB 检索该数据
import psycopg2
import pandas as pd
# Database credentials
db_url = "postgres://tsdbadmin:[email protected]:33159/tsdb?sslmode=require"
# Connect to the database
conn = psycopg2.connect(db_url)
# Create a cursor
cur = conn.cursor()
# Define the query to fetch data for the past 3 months
query = """
SELECT bucket, open, high, low, close
FROM one_min_candle
WHERE symbol = 'BTC/USD'
AND bucket >= NOW() - INTERVAL '1 months'
ORDER BY bucket DESC;
"""
# Execute the query
cur.execute(query)
# Fetch the results
rows = cur.fetchall()
# Convert the results to a pandas DataFrame
stock_data = pd.DataFrame(rows, columns=['bucket', 'open', 'high', 'low', 'close'])
# Print the DataFrame
print(stock_data)
# Optionally, save the DataFrame to a CSV file
stock_data.to_csv('stock_data.csv', index=False)
# Close the cursor and connection
cur.close()
conn.close()
以下是我们通过运行此代码获得的输出
使用这些数据,我们可以使用TimescaleDB 的连续聚合和 Python 时间序列模型来分析数据。
在当今数据驱动的世界中,时间序列分析的重要性不容低估。
TimescaleDB 凭借其专门的时间序列功能和超函数,通过开发快速的数据存储和恢复功能,无需任何预处理即可直接进入数据库,从而简化了数据准备过程。
通过股票价格数据示例,我们探索了 TimescaleDB 统计聚合函数,使用 Python 来探索趋势并使用 ARIMA 进行模型构建。我强烈建议通过探索高级技术来更深入地研究时间序列分析领域。这些技术包括深度学习模型、异常检测算法和多变量分析,以提高数据集的准确性。
此外,借助无数资源,从TimescaleDB 文档到Python 时间序列分析库和交互式平台,您可以在时间序列分析的前沿开展工作。这将带来创新突破并有助于决策过程。