返回

高效计算美股相关性:Python优化技巧

python

高效计算美国Top 500股票相关性

计算美国Top 500股票彼此间的相关性,是一种常见的量化分析任务。 简单的循环嵌套方法会导致大量重复计算,不仅效率低下,也会消耗大量资源。如何避免重复计算并提升性能是一个关键问题。

问题分析:重复计算的根源

现有的代码结构使用了嵌套循环,外层循环遍历每个股票,内层循环同样遍历所有股票。这就导致了像 “A股票 vs B股票”和“B股票 vs A股票” 这种对称组合被重复计算。 实际应用中,这种重复运算是没有必要的。 我们只需要每对股票的相关性计算一次就足够了。

解决方案一:使用索引或数据结构过滤

解决这个问题,可以使用一种巧妙的方式:限制内层循环的起始位置,让其只比较当前股票之后的股票。我们可以利用循环变量的索引来实现这一点。 或者使用类似 set 的数据结构存储已计算的股票对,从而避免重复计算。

操作步骤 (使用索引过滤):

  1. 修改内层循环,让 comparetickers 列表中 ticker 当前位置的下一个元素开始。
  2. 删除 if ticker == compare 条件判断,这个判断是多余的。
  3. 代码示例 (Python):
import pandas as pd
import numpy as np

tickers = ["AAPL\n", "MSFT\n", "GOOG\n", "AMZN\n"]  # 使用示例股票列表

index = 0
ticker_col = np.array([])
compare_col = np.array([])
correlation_col = np.array([])

for i, ticker in enumerate(tickers):
    ticker = ticker.strip()
    for j in range(i + 1, len(tickers)):
        compare = tickers[j].strip()
        index += 1

        compare_list = pd.read_csv(f'C:/stockpredictions/stocks_dfs/{compare}.csv')['Adj Close']
        ticker_list = pd.read_csv(f'C:/stockpredictions/stocks_dfs/{ticker}.csv')['Adj Close']
        
        df = pd.DataFrame({'Data1': ticker_list, 'Data2': compare_list})
        correlation = df['Data1'].corr(df['Data2'])

        ticker_col = np.append(ticker_col, ticker)
        compare_col = np.append(compare_col, compare)
        correlation_col = np.append(correlation_col, correlation)

print(f"计算次数: {index}")
print(pd.DataFrame({"ticker":ticker_col, "compare":compare_col, "correlation":correlation_col}))

代码解读:

  • 使用 enumerate 函数同时获得循环的索引 i 和元素 ticker
  • 内循环从 range(i + 1, len(tickers)) 开始,这样就避免了和之前的股票重复比较。

优点:

  • 代码简洁易懂,修改成本较低。
  • 运行速度提升明显,减少了近一半的计算量。

缺点:

  • 只在代码逻辑上做了优化,没有利用额外数据结构。

解决方案二: 使用组合生成器

Python itertools 库提供了组合生成器功能,我们可以利用 itertools.combinations 函数直接生成不重复的股票对。这种方法逻辑清晰、代码简洁。

操作步骤:

  1. 引入 itertools 库。
  2. 使用 itertools.combinations 生成不重复的股票对。
  3. 计算每对股票的相关性。

代码示例 (Python):

import pandas as pd
import numpy as np
import itertools


tickers = ["AAPL\n", "MSFT\n", "GOOG\n", "AMZN\n"]  # 使用示例股票列表
index = 0
ticker_col = np.array([])
compare_col = np.array([])
correlation_col = np.array([])

for ticker, compare in itertools.combinations(map(str.strip, tickers), 2):
    index += 1
    compare_list = pd.read_csv(f'C:/stockpredictions/stocks_dfs/{compare}.csv')['Adj Close']
    ticker_list = pd.read_csv(f'C:/stockpredictions/stocks_dfs/{ticker}.csv')['Adj Close']

    df = pd.DataFrame({'Data1': ticker_list, 'Data2': compare_list})
    correlation = df['Data1'].corr(df['Data2'])
    
    ticker_col = np.append(ticker_col, ticker)
    compare_col = np.append(compare_col, compare)
    correlation_col = np.append(correlation_col, correlation)


print(f"计算次数: {index}")
print(pd.DataFrame({"ticker":ticker_col, "compare":compare_col, "correlation":correlation_col}))

代码解读:

  • 使用 map(str.strip, tickers)tickers 列表中的股票名称去除末尾的换行符, 并传递给itertools.combinations, 2 代表每次生成两个元素的组合。
  • 直接从生成器中获取不重复的股票对。

优点:

  • 代码可读性更强,逻辑更清晰,减少人为错误。
  • 避免使用索引和复杂的条件判断,更加 Pythonic。
  • 减少了开发调试的时间。

缺点:

  • 对于新手而言可能略难理解。
  • 代码量减少的同时对第三方库产生了依赖。

安全建议

  1. 数据验证 : 在读取股票数据后,进行数据类型和数据质量的检查,以避免因数据错误导致计算偏差。
  2. 文件路径 : 确保读取CSV文件的路径准确无误,可以使用相对路径并做合理错误处理。
  3. 异常处理: 在进行相关性计算前,进行 try except 块来捕获 DataFrame.corr() 方法中可能出现的异常,例如空数据帧或所有数据都相同的情况。
  4. 版本控制: 使用 git 或其他版本控制系统,管理和跟踪代码的变更。

合理使用上述方法和建议可以使你的股票相关性分析更快速、准确和安全。选择哪种方法取决于个人习惯,项目需求和团队的熟练程度。 使用工具提升开发效率是必须的技能。