我正在做一个项目,我发现自己处于以下情况:
我正在创建一个多空投资组合,其中我目前有每日回报。我的下一步是计算累积回报,但我在尝试这样做时遇到了麻烦。
有人可以帮忙吗?
提前致谢。
代码
let long = myFactorPorts.Rows |> Seq.filter(fun row -> row.PortfolioName = "Mine" && row.Index = Some 3)
let short = myFactorPorts.Rows |> Seq.filter(fun row -> row.PortfolioName = "Mine" && row.Index = Some 1)
type Return = { YearMonth : DateTime; Return : float }
let longShort =
let shortMap = short |> Seq.map(fun row -> row.YearMonth, row) |> Map
long
|> Seq.map(fun longObs ->
match Map.tryFind longObs.YearMonth shortMap with
| None -> failwith "probably your date variables are not aligned"
| Some shortObs -> { YearMonth = longObs.YearMonth; Return = longObs.Ret - shortObs.Ret })
|> Seq.toArray
longShort |> Array.take 3
let cumulativereturnslongshort = longShort |> ??
答案 0 :(得分:5)
您的问题有点不清楚,因为您向我们展示了一些与如何获取数据相关的代码,但您并没有过多说明您想做什么以及您遇到了什么问题。
但是,如果我理解的话,您有一个 Return
值数组。我将使用一个简单的例子:
type Return = { YearMonth : DateTime; Return : float }
let longShort =
[| { YearMonth = DateTime(2021,1,1); Return = 1.0 }
{ YearMonth = DateTime(2021,2,1); Return = -3.0 }
{ YearMonth = DateTime(2021,3,1); Return = 5.0 }
{ YearMonth = DateTime(2021,4,1); Return = -1.0 } |]
您说您想了解累积回报。我想这意味着只是将之前的回报相加,因此基于上述每月回报的累积回报将是 1、-2、3、2。如果是这种情况,您可以使用 Array.scan
:
longShort
|> Array.scan (fun prev item ->
{ item with Return = item.Return + prev.Return})
{ YearMonth = DateTime.MinValue; Return = 0.0 }
|> Array.skip 1
scan
函数允许您使用传递的某些状态为数组中的每个项目计算新值。在这里,我使用前一个 Return
值作为状态(并且传递给 scan
的函数只是将当前值添加到前一个返回值中)。一个技巧是你需要一些初始值,所以我用 Return
创建了一个 Return = 0.0
值,然后跳过这个以获得结果。