我在具有以下结构的单独csv文件中拥有所有纽约证券交易所股票的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
....
我想计算一下纽约证券交易所tick (上涨交易的股票数量减去下跌交易的股票数量)并将其写入新的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中最有效地做到这一点?
答案 0 :(得分: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文件读入一个名为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
这假设记录时间与所有股票匹配:如果没有,则有强大的重采样工具可用于对齐它们。
答案 1 :(得分: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.tee
和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
将是一个包含每个文件的csv数据的当前行和前一行的2元组的元组。我们需要从其中一条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