根据历史数据构建回归调整的连续期货合约

1 投票
1 回答
3885 浏览
提问于 2025-04-18 14:55

我正在学习Python,所以需要一些指导来解决这个问题。

我正在使用Quandl这个库来下载历史期货数据,比如(ESH2000, ESM2000, ESU2000, ESZ2000, ESH2001, ...., ESU2014)。现在我想建立一个连续的、经过调整的合约,以便进行绘图和回测。

希望能得到一些建议,告诉我应该使用哪些库来完成这个任务(比如pandas、numpy、纯Python,或者其他库):

Quandl文件的数据结构如下:

Date, Open, High, Low, Last, Change, Settle, Volume, Prev. Day Open Interest

ESH2000 data:
3/1/2000    1372.25 1388.75 1371            1384.5  60887   29558
3/2/2000    1384.25 1390.5  1372.5          1385    62489   30059
3/3/2000    1384.75 1414.5  1383.5          1410.5  65432   29923
3/6/2000    1411    1412.75 1386.25         1395    59860   29549
3/7/2000    1394.5  1404.5  1351            1351.75 85263   31256
3/8/2000    1352.75 1376    1348.5          1366    73911   30916
3/9/2000    1367    1405    1357.5          1404    7153    28164
3/10/2000   1403.25 1415.5  1394.25         1399    3192    27549
3/13/2000   1398    1415.75 1364.75         1383.75 2025    26719
3/14/2000   1380.25 1395.75 1359.5          1359.5  1207    25134


ESM2000 data:
3/1/2000    1396    1404    1389.75         1402.75 52  105
3/2/2000    1400.75 1407.75 1391.25         1402.75 91  147
3/3/2000    1400.75 1433    1400.75         1429.75 183 189
3/6/2000    1424.75 1428.75 1405.25         1415    366 379
3/7/2000    1412.5  1423    1370.25         1370.25 1160    1023
3/8/2000    1372.75 1393.75 1366.25         1384    981 1194
3/9/2000    1384.25 1423.5  1376.75         1423    49536   5974
3/10/2000   1423.25 1434.25 1412            1417.75 65615   9561
3/13/2000   1416.75 1418.25 1381.25         1401.75 69428   11559
3/14/2000   1401.25 1414.25 1376.75         1380.5  77793   12057

我想要根据成交量来“滚动”到新的合约。

补充说明:
因为在2000年3月9日,ESH2000合约的成交量下降,交易者转向ESM2000合约,所以我需要在那时“滚动”到新合约的数据,并且对之前的值进行调整。在这个例子中,2000年3月9日新合约的结算值是1423,而旧合约的结算值是1404,所以我想要把它们匹配起来。因此,我需要通过给旧合约的所有值加上19来进行调整。
补充结束:

我想要的输出结果是:Date, AdjOpen, AdjHigh, AdjLow, AdjClose (Settle), Vol, OI:

3/1/2000    1391.25 1407.75 1390    1403.5  60887   29558       ADJ ESH2000 Data
3/2/2000    1403.25 1409.5  1391.5  1404    62489   30059       ADJ ESH2000 Data
3/3/2000    1403.75 1433.5  1402.5  1429.5  65432   29923       ADJ ESH2000 Data
3/6/2000    1430    1431.75 1405.25 1414    59860   29549       ADJ ESH2000 Data
3/7/2000    1413.5  1423.5  1370    1370.75 85263   31256       ADJ ESH2000 Data
3/8/2000    1371.75 1395    1367.5  1385    73911   30916       ADJ ESH2000 Data
3/9/2000    1384.25 1423.5  1376.75 1423    49536   5974        ESU2000 Data
3/10/2000   1423.25 1434.25 1412    1417.75 65615   9561        ESU2000 Data
3/13/2000   1416.75 1418.25 1381.25 1401.75 69428   11559       ESU2000 Data
3/14/2000   1401.25 1414.25 1376.75 1380.5  77793   12057       ESU2000 Data

我现在正在阅读pandas的文档,但不太确定如何“比较”这两个文件/数据框,以及如何输出文件的子集,然后进行调整,并且对历史中的每个额外合约都这样做。

我并不是在让任何人帮我完成这个,只是希望能得到一些方向,以便集中我的学习精力。

1 个回答

7

这里有一些粗略的想法,可以帮助你入门——要让这个方法更通用,还需要更多的思考,可能还会有改进的空间。

首先,我将只处理每个合同在2000年3月的数据,假设每个合同的数据都在自己的数据框中。

esm = Quandl.get("CME/ESM2000")['2000-3']
esh = Quandl.get("CME/ESH2000")['2000-3']

我们可以使用 merge 来合并这些数据,这个方法可以根据索引或列来连接数据框。因为日期在两个数据框中都是索引,所以需要指定 left_indexright_index

combined = esh.merge(esm, left_index=True, right_index=True)

如果有相同的列名,合并后会在左边的列名后加上 _x,在右边的列名后加上 _y。要判断 M 合同的交易量是否最高,只需比较这两个数据框的对应列。要找出交易量首次变化的日期,可以用这个比较结果的索引来获取第一个索引值。

m_highest = combined['Volume_y'] > combined['Volume_x']
roll_date = m_highest[m_highest].index[0]

接下来,通过选择每个数据框在该日期的结算数据来计算差距。

roll_gap = esm.loc[roll_date, 'Settle'] - esh.loc[roll_date, 'Settle']

构建合并后的数据框时,从每个数据框中选择正确的日期并进行拼接。

df = pd.concat([esh[esh.index < roll_date], esm[esm.index >= roll_date]])

最后,选择较早的日期,并根据差距进行调整。

df.loc[df.index < roll_date, ['Open','High','Low','Settle']] = (
         df.loc[df.index < roll_date, ['Open','High','Low','Settle']] + roll_gap)

撰写回答