收益率计算方法
本页介绍一些常见的投资收益率计算方法。
# 一些基本概念
投资收益率是一个特定投资组合(portfolio)在特定的统计周期中的投资业绩表现。
投资组合可以只包含一个投资标的(账户),也可以包含多个投资标的。现金可能是投资组合的一部分——现金作为投资标的看起来似乎违反直觉,但组合中的现金占比往往对投资业绩有着重要影响,计算收益率时不应当忽略现金仓位。如果投资组合只包含一个账户,该组合的投资收益率也被叫做该账户的投资收益率。
统计周期是指定的一段时间周期,周期开始的时间点称为期初,周期结束的时间点称为期末。常见的统计周期是整年度或整半年度。当统计周期不是整年度时,有一些计算方法可以把收益率换算为年化收益率。TataruBook 允许以天为单位指定任意一段时间为统计周期,而且不会对收益率进行年化换算。
投资组合的市场价值(或价值)是对组合中所有资产按照某种货币计价计算出来的。用于计价的货币在 TataruBook 中称为标准资产。
外部资金流(external flows)指的是投资组合与外部因为非投资衍生收益而产生的价值流动。从外部流到组合中称为资金流入;从组合中流到外部称为资金流出。比如,如果把整个家庭的所有资产看作一个投资组合,家庭成员的工资收入、日常消费支出就是常见的外部资金流。投资组合内部各个账户之间的价值流动不属于外部资金流,比如家庭成员之间的转账或者使用投资组合中的现金购买股票等等。投资衍生收益,如利息、票息、分红等也不属于外部资金流,它们被视为投资收益的一部分,且在产生后会被保留在投资组合中。外部资金流在计算收益率的时候是需要被补偿的,否则会导致收益率失真。
# 无外部资金流时的计算
假设在期初,投资组合的市场价值为$$ V_s $$;期末,投资组合的市场价值为$$ V_e $$,那么收益率$$ R $$为:
$$ R = \frac{V_e - V_s}{V_s} $$
注意$$ V_e $$包括了投资组合在统计周期内获得的所有利息、票息、分红等收益,而不仅仅是投资品在期末的市场价值。
举例:假设投资组合中只有一只股票,期初持有该股票$$ 100 $$股,每股价格$$ 10 $$元,那么投资组合的期初价值为$$ 10 \times 100 = 1000 $$元。在统计周期内,该股票进行了每股$$ 0.5 $$元的分红,期末时该股票价格为每股$$ 9.8 $$元,则获得的分红总计为$$ 0.5 \times 100 = 50 $$元,期末持有的股票价值为$$ 9.8 \times 100 = 980 $$元。因此,$$ V_e = 980 + 50 = 1030 $$元,收益率$$\displaystyle R = \frac{30}{1000} = 3% $$。
这种算法简单易懂,但是只适用于统计周期内没有外部资金流的情况。在上面这个例子中,如果投资者在统计周期内追加买入了$$ 100 $$股,买入价格仍是$$ 10 $$元,那么期末时投资组合市场价值为$$ 2060 $$元(原例子的两倍),这时沿用原公式算出的收益率为$$\displaystyle R = \frac{2060 - 1000}{1000} = 106% $$,显然这个收益率是不准确的。
有人可能会想:把统计周期内的资金流入价值加到期初价值$$ V_s $$中去是否可行呢?——对于这个例子来说没问题,因为这个例子里只有资金流入没有资金流出。但实际情况可能比这复杂得多,比如一个短线交易者可能每天都有大笔资金流入和流出,如果只累加所有的资金流入价值,收益率计算结果也是不准确的。
显然,我们需要一些方法来补偿外部资金流所造成的影响。下面介绍几种常见的方法。
# 简单 Dietz 方法
简单 Dietz 方法 (opens new window)把统计周期内所有资金流入和流出的价值累加(资金流入的符号为正,资金流出的符号为负),计算出净流入$$ F $$(如果实际为净流出,则值为负数),然后把期初的价值加上净流入的一半,即:
$$ R = \frac{V_e - V_s - F}{V_s + \displaystyle \frac{F}{2}} $$
简单 Dietz 方法基于这样的假设:资金流入和流出在整个统计周期中是大致平均的发生的,因此可以看作在统计周期中点发生了一次净流入。
举例:假设投资组合中只有一只股票,统计周期有$$ 3 $$天,每天的股价和资金流入流出如下:
| 天 | 股价 | 新增股数 | 资金流入 | 持有股数 | 市场价值 |
|---|---|---|---|---|---|
| 0 | 10 | 0 | 0 | 10 | 100 |
| 1 | 12 | 5 | 60 | 15 | 180 |
| 2 | 11 | 0 | 0 | 15 | 165 |
则简单 Dietz 方法计算的收益率为:
$$ R = \frac{V_e - V_s - F}{V_s + \displaystyle \frac{F}{2}} = \frac{165 - 100 - 60}{100 + \displaystyle \frac{60}{2}} = \frac{5}{130} \approx 3.85% $$
简单 Dietz 方法的缺点是:如果资金流入和流出在整个统计周期中并不是平均分布的,那么计算结果会不准确。假设一种极端情况:在一年的统计周期中,初始市场价值为$$ 0 $$;在第$$ 2 $$天,大笔资金流入并买入股票;在第$$ 364 $$天,和之前差不多价值的资金流出。由于整个统计周期中资金净流入的绝对值很小(甚至可能为$$ 0 $$),故公式里分母的值非常小(或者为$$ 0 $$),导致收益率产生很大偏差。
尽管简单 Dietz 方法存在缺点,但个人或家庭的整体资金流入流出往往很接近简单 Dietz 方法的假设(即资金流入和流出在时间上大致分布均匀)。因此 TataruBook 在计算包含所有内部账户的投资组合的收益率时使用简单 Dietz 方法。(见 portfolio_stats 视图)。
# 改良的 Dietz 方法
为了解决简单 Dietz 方法的缺点,改良的 Dietz 方法 (opens new window)不再假设只在统计周期的中点产生一次净流入,而是按实际的资金流入流出情况计算出统计周期内的平均资本(即投资组合的平均市场价值),再用平均资本作为分母:
$$ R = \frac{V_e - V_s - F}{V_s + \displaystyle \sum_{i=1}^{n} W_i \times F_i} $$
其中,$$ F = \displaystyle \sum_{i=1}^{n} F_i $$,是整个统计周期的净流入;$$ n $$是资金流入和流出的次数之和;$$ F_i $$是第$$ i $$次资金流入或流出的价值(流入为正值,流出为负值);$$ W_i $$是第$$ i $$次资金流入或流出的权重,权重是根据流入或流出发生的时间计算出来的,即:
$$ W_i = \frac{T - t_i}{T} $$
其中$$ T $$为统计周期的时间长度;$$ t_i $$为第$$ i $$次资金流入或流出发生的时间距离期初的时间长度。流入或流出发生得越早,其权重越高,对于收益率的影响越大。
举例:假设统计周期有$$ 365 $$天,每天的股价和资金流入流出如下(中间没有变化的天省略掉):
| 天 | 股价 | 新增股数 | 资金流入 | 持有股数 | 市场价值 |
|---|---|---|---|---|---|
| 0 | 10 | 0 | 0 | 0 | 0 |
| 1 | 10 | 1100 | 11000 | 1100 | 11000 |
| 364 | 11 | -1000 | -11000 | 100 | 1100 |
| 365 | 11 | 0 | 0 | 100 | 1100 |
则改良的 Dietz 方法计算收益率的过程为:
$$ W_0 = \frac{365 - 1}{365} \approx 0.997 $$
$$ W_1 = \frac{365 - 364}{365} \approx 0.003 $$
$$ R = \frac{V_e - V_s - F}{V_s + \displaystyle \sum_{i=1}^{n} W_i \times F_i} \approx \frac{1100 - 0 - 0}{0 + 0.997 \times 11000 - 0.003 \times 11000} \approx 10% $$
这个计算结果是符合直觉的,因为股价从$$ 10 $$涨到$$ 11 $$正好上涨了$$ 10% $$。如果用简单 Dietz 方法对这个例子进行计算,会因为分母为$$ 0 $$而无法计算。
一般来说,如果投资的收益是随着时间稳定增长的(如存款利息、货币基金收益),那么改良的 Dietz 方法计算的收益率往往非常准确。但是,如果投资品的价格剧烈变化,那么改良的 Dietz 方法计算的结果可能出现不小的偏差。在上面的例子中,如果资金流入不是在第$$ 1 $$天而是在第$$ 363 $$天,那么计算出的平均资本会很小,导致收益率为一个巨大的数字,和实际不符。
由于改良的 Dietz 方法计算利息收益的准确性,TataruBook 在计算每个账户的利息收益率时使用改良的 Dietz 方法。(见interest_rates视图)。
# 内部收益率(IRR)
内部收益率 (opens new window)是使得所有资金流入和流出的净现值 (opens new window)恰好等于$$ 0 $$的收益率。通俗的讲,假设投资组合的价值一直以固定的速率$$ R $$增长,在此假设下,使用该投资组合的期初价值、资金流入流出计算出的期末价值刚好能和实际匹配上,则满足该假设的$$ R $$就是内部收益率。
内部收益率的计算有一些特别的要求:资金流入或流出必须以固定的时间间隔发生,且计算出的收益率$$ R $$只能是这个时间间隔长度的收益率。假设每间隔时间$$ T $$有一次资金流入或流出$$ F_i $$,那么在统计周期$$ T $$的内部收益率$$ R $$是下面这个方程的解:
$$ \sum_{i=0}^{n} \frac{F_i}{(1 + R)^i} = 0 $$
注意:计算内部收益率时,资金流入的$$ F_i $$为负数,资金流出的$$ F_i $$为正数,这和其它方法中定义的符号相反。$$ F_0 $$为期初的价值的相反数,即$$ F_0 = -V_s $$;$$ F_n $$为期末的价值,即$$ F_n = V_e $$。也就是说,把期初的价值看成一次资金流入,期末的价值看成一次资金流出。
举例:假设统计周期为$$ 3 $$年,投资组合每隔一年有一笔资金流出,如下:
| 年 | 资金流 |
|---|---|
| 0 | -123400 |
| 1 | 36200 |
| 2 | 54800 |
| 3 | 48100 |
那么,内部收益率是下面这个方程的解:
$$ \sum_{i=0}^{n} \frac{F_i}{(1 + R)^i} = -123400 + \frac{36200}{(1 + R)} + \frac{54800}{(1 + R)^2} + \frac{48100}{(1 + R)^3} = 0 $$
从该方程可解出一年的内部收益率$$ R \approx 5.96% $$
内部收益率在现实中有广泛的应用。比如,对于每月需要归还固定金额的贷款,内部收益率代表该贷款的真实利率。但是,内部收益率也存在很多缺点,比如,当资金流入流出不是以固定的时间间隔发生时,计算会遇到麻烦。虽然计算时可以粗糙的以天为时间间隔来处理资金流入流出,并把没有资金流入流出的天看成$$ F_i = 0 $$,但这样计算出来的内部收益率是一天的收益率,而不是原始统计周期的收益率。如果按年化的方法把一天的收益率换算成一年的收益率,又可能出现很大的偏差。
举个例子:某投资组合的统计周期为一年,期初价值为$$ 100 $$,在第一天末流出了$$ 101 $$,之后没有任何流入和流出,期末价值为$$ 0 $$。对该投资组合,计算出来的内部收益率是一天$$ 1% $$。如果把收益率简单换算成年化,那么年化收益率为$$ (1 + 0.01)^{365} \approx 37.78 $$倍。显然这个年化收益率是严重失真的。
内部收益率的另一个缺点是计算时需要解高次方程,计算量大,手工几乎无法计算,只能编程求解。
由于 SQLite 数据库和 Python 标准库都没有提供计算内部收益率的功能,为了不增加软件的依赖,且避免软件响应时间过长,TataruBook 并没有直接提供计算内部收益率功能。但是,TataruBook 提供了periods_cash_flows视图,这个视图展示了所有内部账户集合在每天的资金净流入/流出价值。把该视图中的数据复制到 Excel,并用XIRR函数就可以计算所有内部账户集合作为投资组合的内部收益率。 {: .notice}
# 时间加权收益
时间加权收益 (opens new window)基于这样的思路:在任意两次资金流入流出之间的时间段里是没有资金流入流出的,那么对于每段没有资金流入流出的子周期可以应用无外部资金流时的计算方法来计算收益率。然后,可以把所有子周期的收益率相乘来得到总收益率。
要计算时间加权收益,仅仅知道投资组合的期初价值和期末价值是不够的,还必须知道每次资金流入流出时的投资组合价值。假设有$$ n - 1 $$次资金流入流出,那么$$ V_0 = V_s $$为期初价值;$$ V_n = V_e $$为期末价值;$$ V_i $$为在第$$ i $$次资金流入流出$$ F_i $$后的价值。则时间加权收益率$$ R $$为这个方程的解:
$$ 1 + R = \frac{V_1 - F_1}{V_0} \times \frac{V_2 - F_2}{V_1} \times \frac{V_3 - F_3}{V_2} \times \dots \times \frac{V_{n-1} - F_{n-1}}{V_{n-2}} \times \frac{V_{n} - F_{n}}{V_{n-1}} $$
举例:假设投资组合中只有一只股票,统计周期为$$ 2 $$年,初始和每年末的股价及资金流入流出如下:
| 年 | 股价 | 新增股数 | 资金流入 | 持有股数 | 市场价值 |
|---|---|---|---|---|---|
| 0 | 10 | 0 | 0 | 50 | 500 |
| 1 | 20 | 50 | 1000 | 100 | 2000 |
| 2 | 15 | 0 | 0 | 100 | 1500 |
那么,时间加权收益率为:
$$ \frac{V_1 - F_1}{V_0} \times \frac{V_2 - F_2}{V_1} - 1 = \frac{2000 - 1000}{500} \times \frac{1500 - 0}{2000} - 1 = 2 \times 0.75 - 1 = 50% $$
这个收益率实际上是股价本身的变化率,并没有体现资金流入流出对真实收益的影响。如果观察这项投资的实际利润,会发现期初价值$$ 500 $$,中间增加投入$$ 1000 $$,期末价值$$ 1500 $$,实际收益为$$ 0 $$,与时间加权收益率不符。
但这正是时间加权收益的特点,它把整个组合看成一只基金,资金流入和流出相当于基金份额的申购和赎回,时间加权收益希望剔除申购和赎回造成的影响,只体现基金本身的投资绩效。因此,有时候时间加权收益也被叫做基金净值法。
如果投资组合的资金流入流出是不受投资组合的管理人控制的,那么时间加权收益很好的体现了管理人的投资水平。但是如果管理人本身控制着投资组合的资金流入流出,那么就像上面的例子那样,时间加权收益并没有反映真实的收益情况。
TataruBook 没有提供计算时间加权收益的功能,因为它要求每次资金流入流出时都要能计算出投资组合的价值。然而,个人或家庭的资金流入流出几乎不会遵循这个要求。比如:在非交易日投资组合的价值可能无法计算,但仍然会有资金流入流出。 {: .notice}
# 最小初始资金法
如果投资组合中只有一种投资品,那么所有的外部资金流都是对这种投资品的买入/卖出操作。假设在投资组合中加入一个虚拟的现金账户,且这个现金账户中的资金价值能够满足统计周期内所有的买入卖出操作,即:把每次买入看成是现金账户转移价值到投资品账户;把每次卖出看成是投资品账户转移价值到现金账户。这样,原来的外部资金流就都变成了新投资组合中投资账户和现金账户之间的内部价值流动。对这个新的投资组合来说,不再存在外部资金流,可应用无外部资金流时的计算方法来计算收益率。
为了能最准确地体现实际收益率,虚拟现金账户中的期初资金价值要尽可能小,只要能刚好完成所有买入卖出操作即可。这个最小的虚拟现金账户期初价值称为最小初始资金$$ C_s $$。要计算出最小初始资金$$ C_s $$,可以这样考虑:先假设$$ C_s = 0 $$,这种情况下如果现金账户的价值在统计周期内不会出现负值,那么说明$$ 0 $$就是最小初始资金;如果现金账户的价值在统计周期内会出现负值,那么找到绝对值最大的那个负值,把它的绝对值作为最小初始资金$$ C_s $$,这样就能刚刚好使得现金账户的价值在统计周期内不会出现负值。
$$ C_s = \text{max}(0, F_1, F_1 + F_2, F_1 + F_2 + F_3, \dots, \sum_{i=1}^{n}F_i) $$
上面公式中,$$ F_i $$是第$$ i $$次资金流入或流出的价值(流入为正值,流出为负值)。注意流入流出是从原始投资组合的视角看的,从新投资组合看,资金流入是从现金账户转移价值到投资账户,会使得现金账户价值减少。所以现金账户的价值余额已经是$$ F_i $$累加后的相反数,不需要再次取反。
使用最小初始资金推算,到期末时虚拟现金账户中的价值为$$ C_e $$。
$$ C_e = C_s - \sum_{i=1}^{n}F_i $$
收益率$$ R $$计算方法为:
$$ R = \frac{(V_e + C_e) - (V_s + C_s)}{V_s + C_s} $$
举例 1:假设原始的投资组合中只有一只股票,统计周期有$$ 4 $$天,每天的股价和资金流入流出如下:
| 天 | 股价 | 股数变动 | 资金流入/流出 | 持有股数 | 市场价值 |
|---|---|---|---|---|---|
| 0 | 10 | 0 | 0 | 10 | 100 |
| 1 | 12 | 5 | 60 | 15 | 180 |
| 2 | 15 | -6 | -90 | 9 | 135 |
| 3 | 11 | 0 | 0 | 9 | 99 |
由于在第$$ 1 $$天产生了价值$$ 60 $$的资金流入,因此虚拟现金账户最小初始资金$$ C_s = 60 $$。在第$$ 2 $$天有价值$$ 90 $$的资金流出,所以期末时虚拟现金账户中的价值$$ C_e = 90 $$。计算收益率:
$$ R = \frac{(99 + 90) - (100 + 60)}{100 + 60} = 18.125% $$
需要注意的是,如果这个例子中的两次资金流入流出顺序交换,那么虚拟现金账户最小初始资金就不是这个数值了。
举例 2:在上面例子中,交换第$$ 1 $$天和第$$ 2 $$天的数据,得到每天的股价和资金流入流出如下:
| 天 | 股价 | 股数变动 | 资金流入/流出 | 持有股数 | 市场价值 |
|---|---|---|---|---|---|
| 0 | 10 | 0 | 0 | 10 | 100 |
| 1 | 15 | -6 | -90 | 4 | 60 |
| 2 | 12 | 5 | 60 | 9 | 108 |
| 3 | 11 | 0 | 0 | 9 | 99 |
因为第$$ 1 $$天有价值$$ 90 $$的资金流出,所以虚拟现金账户会多出$$ 90 $$的价值。第$$ 2 $$天虽然有$$ 60 $$的资金流入,但此时虚拟现金账户的价值已经足够覆盖这些流入,且在流入后还剩下$$ 30 $$的价值。因此,虚拟现金账户在期初并不需要有价值,最小初始资金为$$ 0 $$。收益率:
$$ R = \frac{(99 + 30) - (100 + 0)}{100 + 0} = 29% $$
对于价格浮动的单只投资品来说,最小初始资金法计算的收益率在各种不同的资金流入流出情况下都能得到看起来比较合理的结果。因此,TataruBook 对于单个非标准资产账户采用最小初始资金法来计算收益率,见return_on_shares视图。 {: .notice}
# 如何确定外部资金流的价值
资金流的价值都是以标准资产计价的。当投资组合中的资产以标准资产(即本位币)的形式进行流入流出时,其价值很容易确定。然而,有时候流入流出并不是以标准资产进行的。
以一笔交易来举例:
| 流出账户 | 流出数额 | 流入账户 | 流入数额 |
|---|---|---|---|
| A | -500 | B | 10 |
如果投资组合只包含A账户,那么这笔交易是流出;如果投资组合只包含B账户,那么这笔交易是流入。假设A账户和B账户中包含的都是非标准资产,那么对于这笔交易就需要确定以标准资产计价的流入流出价值。
现实中与这种交易对应的一个场景是使用非本位币进行投资:比如当本位币是人民币时,使用美元购买美国股票。在这样的交易中,要确定流入流出以人民币计价的价值,准确的方法应当是记录交易发生时刻的美元兑人民币即时汇率,并进行换算。
但是,TataruBook 的prices表中只有每天结束时的资产价格信息,并不包含交易时刻的即时价格。所以对于这种交易的流入流出价值,TataruBook 的计算结果并不完全准确。然而,考虑到大多数时候资产在日内的价格波动并不大,这种近似的结果往往已经够用了。
一般情况下 TataruBook 采用的算法是:在计算A账户的流出价值时,使用B账户的流入数额按照当日B账户包含的资产的价格进行换算;反之,在计算B账户的流入价值时,使用A账户的流出数额按照当日A账户包含的资产的价格进行换算。
但是有一种特殊的交易不适用于这种算法:当交易中有一方账户的变动数额为$$ 0 $$时:
| 流出账户 | 流出数额 | 流入账户 | 流入数额 |
|---|---|---|---|
| A | 0 | B | 200 |
这种交易通常出现在股票、基金的分红,或债券的票息发放时。比如若A账户是某只美国股票,B账户是接收分红的美元账户,此时若还用上面的算法,就会出现B账户此次交易的流入价值为$$ 0 $$,这是不合理的。
为了解决这个问题,TataruBook 做了特殊处理:如果某笔交易中两个账户都包含非标准资产,且一方的变动数额为$$ 0 $$,那么两个账户的流入流出价值都根据变动数额不为$$ 0 $$的那一方的资产类型和变动数额来确定。在刚才的例子中,A账户的流出价值和B账户的流入价值都是$$ 200 $$乘以当日B账户包含资产的价格。这个处理过程可以通过share_trade_flows视图观察到。
如果你确实需要按即时价格精确的计算流入流出价值,那么可以把一笔交易拆分成使用中间账户的两笔交易:
| 流出账户 | 流出数额 | 流入账户 | 流入数额 |
|---|---|---|---|
| A | -500 | X | 100 |
| X | -100 | B | 10 |
这个例子中X账户是中间账户,它是一个新建的内部账户,包含的是标准资产。X账户的变动数额体现了交易当时的即时流入流出价值。按这种方法录入交易,TataruBook 就可以精确的计算流入流出价值,而且不再需要使用prices表中的价格信息。
在股份拆分/合并交易中,由于只有股份数量发生变化,因此也会有一方账户的变动数额为$$ 0 $$。但是这类交易中并没有资金流入流出。因此记录股份拆分/合并交易时,应当使用包含标准资产的账户作为交易的另一方,以避免错误的产生流入流出价值。