Python 相当于 Excel 的 PERCENTILE.EXC

Python equivalent of Excel's PERCENTILE.EXC

我正在使用 Pandas 计算一些财务风险分析,包括风险价值。简而言之,要计算风险价值 (VaR),您需要一系列时间序列的模拟投资组合价值变化,然后计算特定的尾部百分位数损失。例如,95% VaR 是该时间序列中的第 5 个百分位数。

我的时间序列在 Pandas 数据框中,目前正在使用 pd.quantile() 函数来计算百分位数。 I ] PERECENTILE.EXC() 有效。 Pandas quantile() 的工作方式类似于 Excel 的 PERCENTILE.INC() 的工作方式 - 它包括指定的百分位数。我已经搜索了几个 python 数学包以及这个论坛的 python 解决方案,它使用与 Excel 中的 PERCENTILE.EXC() 相同的方法,但没有成功。我希望这里有人可以提出建议?

这是示例代码。

import pandas as pd
import numpy as np

test_pd = pd.Series([15,14,18,-2,6,-78,31,21,98,-54,-2,-36,5,2,46,-72,3,-2,7,9,34])
test_np = np.array([15,14,18,-2,6,-78,31,21,98,-54,-2,-36,5,2,46,-72,3,-2,7,9,34])

print 'pandas: ' + str(test_pd.quantile(.05))
print 'numpy: '+ str(np.percentile(test_np,5))

我要找的答案是-77.4

谢谢,

瑞安

编辑:我刚刚看到您的编辑。我认为你犯了一个错误。值 -77.4 实际上是数据的 99.5% 百分位数。尝试 test_pd.quantile(.005)。我相信您在指定百分位数时一定 Excel 有误。

编辑 2:我刚刚在 Excel 中自己测试了它。对于第 50 个百分位数,我在 Excel 和 Numpy/Pandas 中都得到了正确的值。然而,对于第 5 个百分位数,我在 Pandas/Numpy 中得到 -72,在 Excel 中得到 -74.6。但是 Excel 在这里是错误的:很明显 -74.6 是第 0.5 个百分位,而不是第 5 个...

最终编辑:经过一些测试,Excel 似乎在使用 PERCENTILE.EXC() 函数时围绕非常小的 k 值表现不稳定。事实上,使用任何 k < 0.05 returns 的函数都是错误的,因此 0.05 必须是一个阈值,低于该阈值函数将无法正常工作。我不知道为什么 Excel 在被要求排除第 5 个百分位时选择 return 第 0.5 个百分位(逻辑行为是 return 第 4.9 个百分位,或第 4.99 个。 ..).但是,对于 Numpy,Pandas 和 Excel return 其他 k 值的值相同。例如,PERCENTILE.EXC(0.5) = 6,还有 test_pd.quantile(0.5) = 6。我想教训是我们需要警惕 Excel 的行为 ;).

我对你的问题的理解是:你想知道对应于数据的第 k 个百分位数的值,这个第 k 个百分位数被排除在外。但是,pd.quantile() returns 对应于您的第 k 个百分位的值,包括第 k 个百分位。

我认为 pd.quantile() return 包含第 k 个百分位数不是问题。事实上,假设您希望所有股票的风险价值都严格高于第 5 个百分位数,您会这样做:

mask = data["VaR"] < pd.quantile(data["VaR"], 0.05)
data_filt = data[mask]

因为您使用了 "smaller than" ( < ) 运算符,将排除与您的第 5 个百分位数完全对应的值,类似于 Excel 的 PERCENTILE.EXC()函数。

请告诉我这是否是您要找的。

它不会像 Pandas' 自己的百分位数那样有效,但它应该有效:

def quantile_exc(ser, q):
    ser_sorted = ser.sort_values()
    rank = q * (len(ser) + 1) - 1
    assert rank > 0, 'quantile is too small'
    rank_l = int(rank)
    return ser_sorted.iat[rank_l] + (ser_sorted.iat[rank_l + 1] - 
                                     ser_sorted.iat[rank_l]) * (rank - rank_l)

ser = pd.Series([15,14,18,-2,6,-78,31,21,98,-54,-2,-36,5,2,46,-72,3,-2,7,9,34])

quantile_exc(ser, 0.05)
Out: -77.400000000000006

quantile_exc(ser, 0.1)
Out: -68.399999999999991

quantile_exc(ser, 0.3)
Out: -2.0

请注意 Excel 对于较小的百分位数失败;这不是错误。这是因为低于最小值的等级不适合插值。因此,您可能需要检查 quantile_exc 函数中的等级是否 > 0(请参阅断言部分)。