如何从 F 中的元组数组计算累积股票回报#

How to calculate cumulative stock returns from an array of tuples in F#

提问人:Gonçalo Franchini 提问时间:6/12/2023 最后编辑:Gonçalo Franchini 更新时间:6/14/2023 访问量:98

问:

我正在尝试从元组数组中计算每周股票回报时间序列的累积回报 - 其中第一个元素是一个对象,第二个元素是相应的每周回报 - 并绘制它。然而,我的追求没有成功。这是我的代码示例:DateTimefloat

#r "nuget: FSharp.Data"
#r "nuget: Plotly.NET, 4.0.0"
open System
open System.IO
open FSharp.Data
open Plotly.NET

let [<Literal>] sampleFileFullPath = "file_containing_returns.csv"
type stockData = CsvProvider<sampleFileFullPath>
let stockDataCSV = stockData.GetSample()

let calcReturn (pv : float, fv : float) = (fv / pv) - 1.0

let returns (s : stockData) (path : string) =
    let dateTimeFormat = "dd/mm/yyyy"
    let sequence = 
        s.Rows
        |> Seq.map(fun x -> System.DateTime.Parse(x.Date), calcReturn(float x.AdjClose, float x.Open))
    let array =
        sequence
        |> Seq.toArray |> Array.map snd
   printfn "%A" array

正如你在上面看到的,我试图提取(股票回报)的第二个元素。虽然我随后设法获得了时间序列长度内的累积回报总和,但我无法保留相应的 .删除最后一个管道操作将使该函数产生以下输出:tupleDateTime

[|(01/01/2000 00:00:00, 0.2368421053); (08/01/2000 00:00:00, 0.1973684211); 
  (15/01/2000 00:00:00, 0.07142857143); (22/01/2000 00:00:00, 0.2597402597);
  (29/01/2000 00:00:00, 0.09756097561); (05/02/2000 00:00:00, 0.156626506); 
  (12/02/2000 00:00:00, 0.1666666667); (19/02/2000 00:00:00, 0.1666666667); 
  (26/02/2000 00:00:00, 0.01030927835); (04/03/2000 00:00:00, 0.1894736842);
...|]

任何帮助将不胜感激。

感谢您抽出宝贵时间接受采访!

编辑

(工作)示例数据如下所示:

Date, Open , High , Low , Close , AdjClose , Volume 
01/01/2000,0.94,1.00,0.85,0.89,0.76,3055203200.00
08/01/2000,0.91,0.91,0.77,0.90,0.76,3345742400.00
15/01/2000,0.90,1.08,0.90,0.99,0.84,3383878400.00
22/01/2000,0.97,1.02,0.90,0.91,0.77,2068673600.00
29/01/2000,0.90,0.98,0.84,0.96,0.82,2384424000.00
05/02/2000,0.96,1.05,0.95,0.97,0.83,1664308800.00
12/02/2000,0.98,1.07,0.97,0.99,0.84,1754468800.00
19/02/2000,0.98,1.06,0.95,0.99,0.84,1520971200.00
26/02/2000,0.98,1.18,0.97,1.14,0.97,2408918400.00
04/03/2000,1.13,1.15,1.06,1.12,0.95,1280126400.00
11/03/2000,1.09,1.13,1.02,1.12,0.95,1859289600.00
18/03/2000,1.10,1.34,1.09,1.24,1.05,2306292800.00
25/03/2000,1.23,1.29,1.12,1.21,1.03,1541019200.00
01/04/2000,1.21,1.25,1.04,1.18,1.00,1948620800.00
08/04/2000,1.18,1.19,0.94,1.00,0.85,2892668800.00
15/04/2000,0.98,1.16,0.97,1.06,0.90,2042756800.00
22/04/2000,1.03,1.15,1.02,1.11,0.94,1778358400.00
29/04/2000,1.11,1.13,0.99,1.01,0.86,1636017600.00
06/05/2000,1.00,1.02,0.88,0.96,0.82,1853790400.00
13/05/2000,0.96,0.97,0.83,0.84,0.71,2631921600.00
20/05/2000,0.84,0.84,0.74,0.77,0.66,2539454400.00
27/05/2000,0.78,0.89,0.72,0.83,0.70,2843254400.00

从这个数据集中,我只取 和 列。在计算简单的回报(通过函数)后,我只剩下 ,然后将其转换为函数正在启动的返回。DateOpenAdjCloseCalcReturnsequencearray

输出应如下所示(例如,假设周回报率为 23%,周回报率为 17%,周回报率为 12%):firstsecondthird

[|(01/01/2000 00:00:00, 0.23); (08/01/2000 00:00:00, 0.40);
(15/01/2000 00:00:00, 0.52);...|]

同样,目标是绘制一段时间内的累积回报。 希望这能使问题更清楚!

数组 F# 元组序列

评论

0赞 Koenig Lear 6/12/2023
不清楚你想实现什么,你能显示一个预期的输出样本吗?
0赞 Jim Foye 6/12/2023
你放弃了日期,所以是的,日期不存在。请发布您希望最终数据的样子。它还有助于使输入文件可访问,或者只是创建一些示例数据。
0赞 Jim Foye 6/12/2023
您添加的示例数据不是逗号分隔的,CsvProvider 会解析吗?(我没试过)。最好进一步修改您的示例,只需向 CsvProvider 提供字符串(如果需要,并使用逗号修复数据)。一个可以直接粘贴到脚本中的完整工作示例将使回答这个问题变得更加容易。

答:

0赞 Brian Berns 6/13/2023 #1

F# 提供了一系列称为 scan 的函数,这些函数适用于计算运行总数。正如您所指出的,挑战在于将相关日期与每个总数保持一致。我认为最简单的方法是这样的:

open System

let input =
    [
        DateOnly(2000, 1, 1), 0.23
        DateOnly(2000, 1, 8), 0.17
        DateOnly(2000, 1, 15), 0.12
    ]

input
    |> Seq.scan (fun (_, acc) (date, value) ->
        date, acc + value) (DateOnly.MinValue, 0.0)
    |> Seq.skip 1   // skip initial value of 0.0
    |> printfn "%A"

输出为:

seq [(1/1/2000, 0.23); (1/8/2000, 0.4); (1/15/2000, 0.52)]

为清楚起见,我使用并避免了我认为您已经很好地处理的 CSV 和日期格式问题。DateOnlyDateTime