如何在F#中从元组数组计算股票累积收益率并绘图
解决方案:计算周度累积收益率并绘图
核心逻辑说明
要保留日期同时计算累积收益率,需采用复利累积(而非简单求和),通过Seq.scan遍历序列时同步保留日期与累积收益状态,最终实现带时间维度的累积收益率计算与绘图。
修改后的完整代码
#r "nuget: FSharp.Data" #r "nuget: Plotly.NET, 4.0.0" open System open FSharp.Data open Plotly.NET let [<Literal>] sampleFileFullPath = "file_containing_returns.csv" type stockData = CsvProvider<sampleFileFullPath> let stockDataCSV = stockData.GetSample() // 计算单周简单收益率:(期末值/期初值)-1 let calcReturn (pv : float, fv : float) = (fv / pv) - 1.0 // 生成带日期的周度收益率序列,并计算累积收益率 let getCumulativeReturns (s : stockData) = // 第一步:生成(日期, 单周收益率)的基础序列 let weeklyReturns = s.Rows |> Seq.map(fun x -> DateTime.Parse(x.Date), calcReturn(float x.Open, float x.AdjClose) // 修正参数顺序:期初值Open在前,期末值AdjClose在后 ) // 第二步:用Seq.scan计算复利累积,同步保留日期 weeklyReturns |> Seq.scan (fun (_, prevCumulative) (date, ret) -> let newCumulative = prevCumulative * (1.0 + ret) (date, newCumulative - 1.0) // 转换为收益率(以初始本金为基准,减去1) ) (DateTime.MinValue, 0.0) // 初始占位值,后续会被第一个有效数据覆盖 |> Seq.skip 1 // 跳过初始占位的无效元素 // 绘制累积收益率时间曲线 let plotCumulativeReturns cumulativeData = cumulativeData |> Seq.map (fun (date, ret) -> date, ret) |> Chart.Line |> Chart.withTitle "周度累积收益率走势" |> Chart.withXAxisStyle "日期" |> Chart.withYAxisStyle "累积收益率" |> Chart.show // 执行流程 let cumulativeReturns = getCumulativeReturns stockDataCSV // 打印前3条结果示例 cumulativeReturns |> Seq.take 3 |> printfn "%A" // 生成交互式图表 plotCumulativeReturns cumulativeReturns
关键修改点
- 修正收益率计算逻辑:原代码参数顺序颠倒,已调整为
calcReturn(float x.Open, float x.AdjClose),确保是期末值/期初值的正确计算逻辑。 - 保留日期的累积计算:通过
Seq.scan遍历序列时,同时传递当前日期和累积收益因子,避免丢失时间维度。 - 简化冗余参数:移除原代码中未使用的
path参数,精简函数逻辑。
输出示例
运行后会生成符合需求的元组数组:
[(01/01/2000 00:00:00, 0.2368421053); (08/01/2000 00:00:00, 0.4715789474); (15/01/2000 00:00:00, 0.5771929825); ...]
同时会弹出Plotly交互式图表,直观展示累积收益率随时间的变化趋势。
内容的提问来源于stack exchange,提问作者Gonçalo Franchini
相关产品推荐
相关产品推荐

