2

我在具有以下结构的单独 csv 文件中拥有所有 NYSE 股票的 1 分钟数据:

(数据、开盘价、最高价、最低价、收盘价、成交量)

2013-09-16 09:30:00,461.01,461.49,461,461,183507
2013-09-16 09:31:00,460.82,461.6099,460.39,461.07,212774
...
2013-09-16 15:59:00,449.72,450.0774,449.59,449.95,146399
2013-09-16 16:00:00,450.12,450.12,449.65,449.65,444594
2013-09-17 09:30:00,448,448,447.5,447.96,173624
2013-09-17 09:31:00,449.2628,449.68,447.5,448,193186
....

我想计算纽约证券交易所的报价 (上涨交易的股票数量减去下跌交易的股票数量)并将其写入具有以下结构的新 csv 文件:

2013-09-16 09:30:00,[tick]
2013-09-16 09:31:00,[tick]
...
2013-09-16 15:59:00,[tick]
2013-09-16 16:00:00,[tick]
2013-09-17 09:30:00,[tick]
2013-09-17 09:31:00,[tick]
....

本质上,我需要:

Loop every csv file
    # For every file compare close[t] to close[t-1]
    If close[t] > close[t-1]:
        increment tick by 1
    Else:
        subtract 1 from tick 

你将如何在 python 中最有效地做到这一点?

4

2 回答 2

3

我可能会为此使用pandas库。它有很多很好的功能可以处理一般的时间序列,特别是 OHLC 数据,但我们不会在这里使用任何功能。

import glob
import numpy as np
import pandas as pd

stocks = glob.glob("stock*.csv")

total_tick = 0
for stock in stocks:
    df = pd.read_csv(stock, 
                     names=["time", "open", "high", "low", "close", "volume"],
                     parse_dates=[0], index_col="time")
    tick = df["close"].diff().apply(np.sign).fillna(0.0)
    total_tick += tick

total_tick.to_csv("tick.csv")

它产生的输出看起来像

2013-09-16 09:30:00,0.0
2013-09-16 09:31:00,3.0
2013-09-16 15:59:00,-5.0
2013-09-16 16:00:00,-3.0
2013-09-17 09:30:00,1.0
2013-09-17 09:31:00,-1.0

我在其中制作了看起来像您的示例数据。


基本思想是您可以将 csv 文件读入一个名为 a 的对象DataFrame

>>> df
                         open      high     low       close  volume
time                                                               
2013-09-16 09:30:00  461.0100  461.4900  461.00  453.484089  183507
2013-09-16 09:31:00  460.8200  461.6099  460.39  474.727508  212774
2013-09-16 15:59:00  449.7200  450.0774  449.59  436.010403  146399
2013-09-16 16:00:00  450.1200  450.1200  449.65  455.296584  444594
2013-09-17 09:30:00  448.0000  448.0000  447.50  447.465545  173624
2013-09-17 09:31:00  449.2628  449.6800  447.50  477.785506  193186

我们可以选择一列:

>>> df["close"]
time
2013-09-16 09:30:00    453.484089
2013-09-16 09:31:00    474.727508
2013-09-16 15:59:00    436.010403
2013-09-16 16:00:00    455.296584
2013-09-17 09:30:00    447.465545
2013-09-17 09:31:00    477.785506
Name: close, dtype: float64

请注意,如果我们从前一个值中减去,那么初始值是未定义的:

>>> df["close"].diff()
time
2013-09-16 09:30:00          NaN
2013-09-16 09:31:00    21.243419
2013-09-16 15:59:00   -38.717105
2013-09-16 16:00:00    19.286181
2013-09-17 09:30:00    -7.831039
2013-09-17 09:31:00    30.319961
Name: close, dtype: float64

将其设为正数或负数,具体取决于其符号:

>>> df["close"].diff().apply(np.sign)
time
2013-09-16 09:30:00   NaN
2013-09-16 09:31:00     1
2013-09-16 15:59:00    -1
2013-09-16 16:00:00     1
2013-09-17 09:30:00    -1
2013-09-17 09:31:00     1
Name: close, dtype: float64

并用 0 填充NaN

>>> df["close"].diff().apply(np.sign).fillna(0)
time
2013-09-16 09:30:00    0
2013-09-16 09:31:00    1
2013-09-16 15:59:00   -1
2013-09-16 16:00:00    1
2013-09-17 09:30:00   -1
2013-09-17 09:31:00    1
dtype: float64

这假设所有股票的记录时间都匹配:如果不匹配,则可以使用强大的重采样工具来对齐它们。

于 2013-10-05T18:57:04.193 回答
1

这个问题的几个部分在 Python 中有优雅(但可能不明显)的解决方案。

第一个棘手的部分是处理一次打开所有文件。通常你想使用with open(filename),但是当有(可能是可变的)大量文件要打开时,这不起作用。相反,您可以使用contextlib.ExitStack上下文管理器来处理文件:

import contextlib
import csv
import itertools

def tick(filenames):
    with contextlib.ExitStack() as stack:
        files = [stack.enter_context(open(name, newline=""))
                 for name in filenames]

下一位是读取读取 csv 文件的句柄。使用该csv模块实际上非常容易:

        CSVs = [csv.reader(file) for file in files]

现在,当我们遍历 CSV 文件时,我们需要将每一行与前一行一起考虑。也就是说,我们需要同时生成当前行和之前的行。有一种优雅的方法可以使用itertools.teeand zip(在 之前或之后粘贴此功能tick):

def current_and_prev(iterable):
    a, b = itertools.tee(iterable, 2)
    next(a) # throw away first value from "current" iterator
    return zip(a, b)

回到tick函数中,我们可以将其包装在每个csv.reader实例周围:

        pair_iterators = [current_and_prev(CSV) for CSV in CSVs]

现在,我们要一起迭代所有迭代器,并行(因为我们需要检查它们来计算tick)。zip是这样做的工具:

        for pairs in zip(*pair_iterators):

pairs将是一个 2 元组的元组,其中包含每个文件中 csv 数据的当前行和上一行。我们需要从其中一行中获取时间戳current,然后遍历它们以找出哪些处于上升趋势,哪些处于下降趋势。

            timestamp = pair[0][0][0] # first file, current line, first column
            tick = 0
            for current, prev in pairs:
                if float(current[-2]) > float(prev[-2]):
                    tick += 1
                elif float(current[-2]) < float(prev[-2]):
                    tick -= 1
            yield timestamp, tick
于 2013-10-05T18:18:53.950 回答