【问题标题】:Commodity Futures Hierarchical Data Structure商品期货分层数据结构
【发布时间】:2013-06-15 05:19:09
【问题描述】:

我这辈子似乎都无法获得我想要的结构并让它正常运行,所以我一怒之下来找你们。

设置: 我有一个名为 Futures_Contracts 的目录,里面有大约 30 个文件夹,所有文件夹都以标的资产命名,最后是 6 个最近的 csv 格式到期合约。每个 csv 格式相同,包含 Date,O,H,L,C,V,OI,Expiration Month。

注意:O H L C V OI 是开盘价、最高价、最低价、收盘价、成交量、未平仓合约(对于那些不熟悉的人)也假设收盘价是以下结算的同义词

任务:从这里开始,目标是将期货数据加载到多索引 pandas 数据框中,其中顶级索引是基础商品符号,中级索引是到期月份 - 年,最后是 OHLC 数据。最终目标是拥有一些我可以在 zipline 模块上开始破解的东西,让它在期货上运行。 所以在视觉上:

我的微弱尝试:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from pandas import DataFrame, Series
import datetime
plt.figsize(16,8)

deliveries = {}
commoidities = {}
columns = 'open', 'high', 'low', 'settle', 'volume', 'interest', 'delivery' #Contract fields
path = os.getcwdu()+'/Futures_Contracts/' #Futures Path
for sym in os.listdir(path):
    if sym[0] != '.': #Weed out hidden files
        deliveries[sym] = []
        i = 0
        for contract in os.listdir(path + sym):
            temp = pd.io.parsers.read_csv(path + sym + '/' + contract, index_col=0, parse_dates = True, names = columns)#pull in the csv
            deliveries[sym].append(str(contract[:-4][-1] + contract[:-4][:-1][-2:])) #add contract to dict in form of MonthCode-YY
            commodities[sym] = deliveries[sym]
            commodities[sym][i] = temp
            i += 1

这有点工作,但是这实际上是一个嵌套的字典,最后包含一个数据框。因此切片非常笨重:

commodities['SB2'][0]['settle'].plot()
commodities['SB2'][3]['settle'].plot()
commodities['SB2'][4]['settle'].plot()
commodities['SB2'][3]['settle'].plot()
commodities['SB2'][4]['settle'].plot()
commodities['SB2'][5]['settle'].plot()

并产生

最佳情况下,我将能够对每个索引进行切片,以便我可以比较资产、到期、日期和价值的数据。此外,标记我正在查看的内容,正如您在 matplotlib 图表中看到的那样,所有内容都简单地命名为“解决”

肯定有办法做到这一点,但我不够聪明,无法弄清楚。

【问题讨论】:

    标签: python pandas hierarchical-data trading algorithmic-trading


    【解决方案1】:

    我认为将其放入一个 DataFrame 会更好,因此请考虑使用 MultiIndex。这是一个玩具示例,我认为它可以很好地转化为您的代码:

    In [11]: dfN13 = pd.DataFrame([[1, 2]], columns=[['N13', 'N13'], ['a', 'b']])
    
    In [12]: dfM13 = pd.DataFrame([[3, 4]], columns=[['M13', 'M13'], ['a', 'b']])
    

    这些是您示例中的 DataFrame,但列的第一级只是资产名称。

    In [13]: df = pd.concat([dfN13, dfM13], axis=1)
    
    In [14]: df
    Out[14]:
       N13     M13
         a  b    a  b
    0    1  2    3  4
    

    为方便起见,我们可以标记列级别和索引。

    In [15]: df.columns.names = ['asset', 'chart']
    
    In [16]: df.index.names = ['date']  # well, not in this toy example
    
    In [17]: df
    Out[17]:
    asset  N13     M13
    chart    a  b    a  b
    date
    0        1  2    3  4
    

    注意:这看起来很像您的电子表格。

    我们可以使用xs 获取特定图表(例如 ohlc):

    In [18]: df.xs('a', level='chart', axis=1)
    Out[18]:
    asset  N13  M13
    date
    0        1    3
    
    In [19]: df.xs('a', level='chart', axis=1).plot()  # win
    

    【讨论】:

    • 请允许我再多思考一下。不幸的是,并非所有的标的资产都具有相同的合约到期时间。我该如何处理?由于这个原因,我认为创建数据框是不可行的。最理想的是,它们是将 csv 连接在一起的技巧,有什么想法吗?
    • 是不同的日期,但我担心与明确到期相对应的列。
    • 例如 N13 对应于 2013 年 7 月到期的合同。在您的示例中,您使用了合同 N13 和 M13。为了说明,我将添加一个额外的合约 Z13 和另一个基础资产 c。在您的代码中,它假定每个资产在每个到期 N13、M13 和 Z13 都有一个合约。实际上,每种资产都将有一个独特的到期范围。所以 a 和 b 可能在 N13 上到期。 B 和 c 有 Z13,最后 a 和 c 共享 M13。所以我认为使用上面的代码将无法对齐数据。对吗?
    • @BrandonOgl​​e 不,它应该对齐它(并将 NaN 放在不存在数据的地方)。
    • @BrandonOgl​​e 或者您是在暗示存在某种多对多关系?
    【解决方案2】:

    好的,这似乎有效。

    commodities = {}
    columns = 'open', 'high', 'low', 'settle', 'volume', 'interest', 'delivery' #Contract fields
    path = os.getcwdu()+'/Futures_Contracts/' #Futures Path
    for sym in os.listdir(path):
        if sym[0] != '.': #Weed out hidden files
            i = 0
            c_expirations = {}
            for contract in os.listdir(path + sym):
                expiry = (contract[:-4][-1].encode('ascii', 'ignore') + contract[:-4][:-1][-2:].encode('ascii', 'ignore'))
                c_expirations[expiry] = pd.io.parsers.read_csv(path + sym + '/' + contract, index_col=0, parse_dates = True, names = columns)
            commodities[sym] = pd.concat(c_expirations, axis =1)
    df_data = pd.concat(commodities, axis=1)
    df_data.columns.names = 'asset', 'expiry', 'data'
    

    看看打印出来的内容

    print df_data
    
    
    <class 'pandas.core.frame.DataFrame'>
    DatetimeIndex: 1568 entries, 2007-04-16 00:00:00 to 2013-06-17 00:00:00
    Columns: 1197 entries, (CC2, H14, open) to (ZW, Z13, delivery)
    dtypes: float64(1197)
    

    真的只是修改了安迪的建议,并大规模应用它

    【讨论】:

    • 谢谢您,非常感谢您的帮助!现在我需要仔细考虑如何进行:(
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-08
    • 2015-03-12
    相关资源
    最近更新 更多