Stata:估计投资组合的月度加权平均值

Stata:估计投资组合的月度加权平均值,stata,weighted-average,Stata,Weighted Average,我一直在努力编写最佳代码来估计投资组合回报的月度加权平均值 我有以下变量: 公司股票收益率(ret) 月1、年1和日期 投资组合(port1):定义公司股票收益的投资组合 市值(mcap):估计权重(按1年1月1日) 我想计算每个月的加权回报率和按市值加权的投资组合。(mcap)每个公司的 我已经编写了以下代码,这些代码可以正常工作,但需要很长时间,而且效率很低: foreach x in 11 12 13 21 22 23 { display `x' forvalues y = 1980

我一直在努力编写最佳代码来估计投资组合回报的月度加权平均值

我有以下变量:

  • 公司股票收益率(ret)

  • 月1、年1和日期

  • 投资组合(port1):定义公司股票收益的投资组合

  • 市值(mcap):估计权重(按1年1月1日)

我想计算每个月的加权回报率和按市值加权的投资组合。(mcap)每个公司的

我已经编写了以下代码,这些代码可以正常工作,但需要很长时间,而且效率很低:

foreach x in 11 12 13 21 22 23 {
display `x'

forvalues y = 1980/2010 {
display `y'

forvalues m = 1/12 {
display `m'
tempvar tmp_wt tmp_tm tmp_p
egen `tmp_tm' = total(mcap) if month1==`m' & year1==`y' & port1 ==`x'
gen `tmp_wt' = mcap/`tmp_tm' if month1==`m' & year1==`y' & port1 ==`x'
gen `tmp_p' = ret*`tmp_wt' if month1==`m' & year1==`y' & port1 ==`x'
gen port_ret_`m'_`y'_`x' = `tmp_p'

}
}
}

数据如图所示:![价值加权投资组合回报数据][1]

这似乎是一个案例,说明了如何尽可能慢地做事,当然你不是故意这么做的。它所缺少的只是一个循环来计算总数。因此,好消息是,你确实应该能够加快这一进程

这似乎归结为

gen double wanted = . 
bysort port1 year month : replace wanted = sum(mcap) 
by port1 year month : replace wanted = (mcap * ret) / wanted[_N] 
原则。要获得单个标量中的和,请使用
summary,meanonly
而不是使用
egen,total()
重复将该标量放入变量,而是使用
sum()
by:
在需要时将组和放入变量,如下所示
sum()
返回累积和,因此需要累积和的最后一个值

原则。如果可以在
by:
的支持下进行分组计算,则不需要循环(此处使用
foreach
)。这是Stata程序员需要学习的强大构造

原则。创建大量临时变量,其中6*31*12*3=6696个,会降低速度,并使用比需要更多的内存。每次执行
tempvar
并执行
generate
命令时,还有三个临时变量,它们的大小与数据集中的一列大小相同(这就是Stata中的一个变量),但一旦使用它们,它们就会留在内存中,不再查看。临时变量的微妙之处在于,
tempvar
每次都分配一个新名称,但应该清楚的是,
generate
每次都创建一个新变量<代码>生成永远不会覆盖现有变量。临时变量将在程序结束时全部删除,但在该程序结束时,您将不必要地持有大量内容,可能是数据集的大小乘以大约1000。如果临时扩展的数据集无法全部放入内存,则将Stata翻转为爬网

原则。使用
if
要求Stata依次检查每个观察结果;在这种情况下,大多数与正在执行的循环的特定交集无关,并且在对数据集的1/2232执行每个特定计算时,让Stata检查几乎所有的数据集(2231/2232的一小部分,几乎是1)。如果你有更多的年数,或者更多的投资组合,那么不相关的比例会更高

本质上,Stata将遵守您的指示(并且不会尝试任何类型的优化——您的代码完全按照字面解释),但是
by:
将更快地给出交叉组合

注意。我不知道这些数字会有多大或接近零,所以我给了你一个
double
。就我所知,
float
对您来说很好


评论。我猜您受到了其他语言编码经验的影响,在这些语言中,创建变量意味着类似于保持常量的
x=42
。您也可以在Stata中使用标量或局部或全局宏来实现这一点,更不用说Mata了。请记住,Stata中的一个新变量是数据集中的一个完整的新列,无论它在每个观察值中是保持常量还是不同的值。你会得到你想要的,但这更像是每次都得到一个数组。同样,似乎最终只需要一个新变量,实际上根本不需要临时创建任何其他变量

这似乎是一个案例,说明了如何尽可能慢地做事,当然你不是故意这么做的。它所缺少的只是一个循环来计算总数。因此,好消息是,你确实应该能够加快这一进程

这似乎归结为

gen double wanted = . 
bysort port1 year month : replace wanted = sum(mcap) 
by port1 year month : replace wanted = (mcap * ret) / wanted[_N] 
原则。要获得单个标量中的和,请使用
summary,meanonly
而不是使用
egen,total()
重复将该标量放入变量,而是使用
sum()
by:
在需要时将组和放入变量,如下所示
sum()
返回累积和,因此需要累积和的最后一个值

原则。如果可以在
by:
的支持下进行分组计算,则不需要循环(此处使用
foreach
)。这是Stata程序员需要学习的强大构造

原则。创建大量临时变量,其中6*31*12*3=6696个,会降低速度,并使用比需要更多的内存。每次执行
tempvar
并执行
generate
命令时,还有三个临时变量,它们的大小与数据集中的一列大小相同(这就是Stata中的一个变量),但一旦使用它们,它们就会留在内存中,不再查看。临时变量的微妙之处在于,
tempvar
每次都分配一个新名称,但应该清楚的是,
generate
每次都创建一个新变量<代码>生成永远不会覆盖现有变量。临时变量都会在程序结束时被删除,但在程序结束时,您会不必要地持有很多东西,可能是