These exercises work with functions from the List
module.
You can find examples of using them F# core docs.
There are similar functions for arrays and sequences.
We're going to use the following data in the questions
#r "nuget: FSharp.Stats, 0.5.0"
open System
open FSharp.Stats
type ReturnOb = { Symbol : string; Date : DateTime; Return : float }
type ValueOb = { Symbol : string; Date : DateTime; Value : float }
let seed = 1
Random.SetSampleGenerator(Random.RandBasic(seed))
let normal = Distributions.Continuous.Normal.Init 0.0 0.1
let returns =
[
for symbol in ["AAPL"; "TSLA"] do
for month in [1..2] do
for day in [1..3] do
{ Symbol = symbol
Date = DateTime(2021, month, day)
Return = normal.Sample()}
]
Question 1
Given the list below, filter the list so that only numbers greater than 2
remain.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.filter(fun x -> x > 2)
val it: int list = [7]
Question 2
Given the list below, take elements until you find one that is greater than 4
.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.takeWhile(fun x -> x <= 4)
val it: int list = [1; -4]
Question 3
Given the list below, skip elements until you find one that is greater than 4
.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.skipWhile(fun x -> x <= 4)
val it: int list = [7; 2; -10]
Question 4
Take a list
containing floats 1.0 .. 10.0
. Create a new list
that contains each number in the original list divided by 3.0
.
answer// either of these is correct
// Option 1:
[ for x in [1.0 .. 10.0] do x / 3.0 ]
// Option 2:
[ 1.0 .. 10.0]
|> List.map (fun x -> x / 3.0)
val it: float list =
[0.3333333333; 0.6666666667; 1.0; 1.333333333; 1.666666667; 2.0; 2.333333333;
2.666666667; 3.0; 3.333333333]
Question 5
Take a list
containing floats 1.0 .. 10.0
. Group the elements based on whether the elements are greater than or equal to 4.0
.
answer[ 1.0 .. 10.0]
|> List.groupBy (fun x -> x >= 4.0)
val it: (bool * float list) list =
[(false, [1.0; 2.0; 3.0]); (true, [4.0; 5.0; 6.0; 7.0; 8.0; 9.0; 10.0])]
Question 6
Take a list
containing floats 1.0 .. 10.0
. Filter it so that you are left with the elements > 5.0
.
answer[ 1.0 .. 10.0]
|> List.filter (fun x -> x > 5.0)
val it: float list = [6.0; 7.0; 8.0; 9.0; 10.0]
Question 7
Given the list below, return tuples of all consecutive pairs.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.pairwise
val it: (int * int) list = [(1, -4); (-4, 7); (7, 2); (2, -10)]
Question 8
Given the list below, return sliding windows of 3 consecutive observations.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.windowed 3
val it: int list list = [[1; -4; 7]; [-4; 7; 2]; [7; 2; -10]]
Question 9
Given the list below, sum all the elements.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.sum
val it: int = -4
Question 10
Given the list below, add 1
to all the elements and then calculate the sum.
[ 1; -4; 7; 2; -10]
answer[ 1; -4; 7; 2; -10]
|> List.sumBy(fun x -> x + 1)
val it: int = 1
Question 11
Given the list below, calculate the average
of the elements in the list.
[ 1.0; -4.0; 7.0; 2.0; -10.0]
answer[ 1.0; -4.0; 7.0; 2.0; -10.0]
|> List.average
val it: float = -0.8
Question 12
Given the list below, convert each element to a decimal
and then calculate the average
of the elements in the list.
[ 1.0; -4.0; 7.0; 2.0; -10.0]
answer Since [ 1.0; -4.0; 7.0; 2.0; -10.0]
|> List.averageBy(fun x -> decimal x)
val it: decimal = -0.8M {Scale = 1uy;}
decimal
is a function that converts to
the decimal
type, you could also do.
The FSharp linter shouLd show you a blue squiggly
in the above code telling you this.[ 1.0; -4.0; 7.0; 2.0; -10.0]
|> List.averageBy decimal
val it: decimal = -0.8M {Scale = 1uy;}
Question 13
Take a list
containing floats 1.0 .. 10.0
. Use List.groupBy
to group the elements based on if they're >= 5.0
. Then use List.map
to get the maxiumum element that is < 5.0
and the minimum value that is >= 5.0
.
answerlet groupedAboveBelow5 =
[ 1.0 .. 10.0]
|> List.groupBy(fun x -> x >= 5.0)
// to see groups and observations
[ for (gt5, xs) in groupedAboveBelow5 do (gt5, xs) ]
// to see just groups
[ for (gt5, xs) in groupedAboveBelow5 do gt5 ]
// to see just observations in each group
[ for (gt5, xs) in groupedAboveBelow5 do xs ]
// to see first group
groupedAboveBelow5[0]
// to see second group
groupedAboveBelow5[1]
[ for (gt5, xs) in groupedAboveBelow5 do
if gt5 then
xs |> List.min
else
xs |> List.max ]
// equivalently
[ 1.0 .. 10.0]
|> List.groupBy(fun x -> x >= 5.0)
|> List.map (fun (gt5, xs) ->
if gt5 then
xs |> List.min
else
xs |> List.max )
val groupedAboveBelow5: (bool * float list) list =
[(false, [1.0; 2.0; 3.0; 4.0]); (true, [5.0; 6.0; 7.0; 8.0; 9.0; 10.0])]
val it: float list = [4.0; 5.0]
Question 14
Take a list
containing floats 1.0 .. 10.0
. Use functions from the List module to sort it in descending order. Then take the 3rd element of the reversed list and add 7.0
to it.
answerlet descendingList =
[1.0 .. 10.0]
|> List.sortByDescending id
// index 2 = 3rd item because it is 0-indexed
let thirdItem = descendingList[2]
thirdItem + 7.0
val descendingList: float list =
[10.0; 9.0; 8.0; 7.0; 6.0; 5.0; 4.0; 3.0; 2.0; 1.0]
val thirdItem: float = 8.0
val it: float = 15.0
Question 15
Take this list of lists, add 1.0
to each element of the "inner" lists,
and then concatenate all the inner lists together.
[ [ 1.0; 2.0]
[ 3.0; 4.0] ]
answer v2, this is not a correct answer.
it has not concatenated the inner lists
into one big list v3 and v4 below are correct, the same output as v1let listsToAdd =
[ [ 1.0; 2.0]
[ 3.0; 4.0] ]
// Compare the output of these different versions.
//v1
[ for list in listsToAdd do
for x in list do x + 1.0 ]
val listsToAdd: float list list = [[1.0; 2.0]; [3.0; 4.0]]
val it: float list = [2.0; 3.0; 4.0; 5.0]
[ for xs in listsToAdd do
[ for x in xs do x + 1.0] ]
val it: float list list = [[2.0; 3.0]; [4.0; 5.0]]
//v3
[ for xs in listsToAdd do
[ for x in xs do x + 1.0] ]
|> List.concat
// v4
listsToAdd
|> List.collect(fun xs ->
[ for x in xs do x + 1.0 ])
val it: float list = [2.0; 3.0; 4.0; 5.0]
Question 16
Given returns : ReturnOb list
, calculate the arithmetic average return
for every symbol each month.
Give the result as a ReturnOb list
where the date is the last date for the symbol
each month.
answerreturns
|> List.groupBy(fun x -> x.Symbol, x.Date.Year, x.Date.Month)
|> List.map(fun ((symbol, _year, _month), xs) ->
{ Symbol = symbol
Date = xs |> List.map(fun x -> x.Date) |> List.max
Return = xs |> List.averageBy(fun x -> x.Return) })
val it: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.04724914955 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.01260338828 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.05050316065 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.06336462869 }]
Question 17
Given returns : ReturnOb list
, calculate the monthly return
for every symbol each month.
Give the result as a ReturnOb list
where the date is the last date for the symbol
each month.
answerlet groupsForMonthlyReturn =
returns
|> List.groupBy(fun x -> x.Symbol, x.Date.Year, x.Date.Month)
// look at the groups
[ for (group, obs) in groupsForMonthlyReturn do group ]
// look at the first observation for each group
// This works:
[ for (group, obs) in groupsForMonthlyReturn do obs ]
// but some custom printing makes it more clear
for (group, obs) in groupsForMonthlyReturn do
printfn $"-------"
printfn $"group: {group}"
printfn $"Observations:"
obs |> List.iter (printfn "%A")
printfn $"-------\n"
// remember how we can calculate cumulative returns
let exampleSimpleReturns =
[ 0.1; -0.2; 0.3 ]
let exampleLogReturns =
[ for ret in exampleSimpleReturns do log(1.0 + ret) ]
let cumulativeLogReturns = exampleLogReturns |> List.sum
let cumulativeSimpleReturns = exp(cumulativeLogReturns) - 1.0
// compare cumulativeSimpleReturns to
(1.0 + 0.1)*(1.0+ -0.2)*(1.0 + 0.3)-1.0
// now the returns
[ for ((symbol, year, month), obs) in groupsForMonthlyReturn do
let cumulativeLogReturn =
obs
|> List.sumBy (fun ob -> log(1.0 + ob.Return))
let cumulativeSimpleReturn = exp(cumulativeLogReturn) - 1.0
let maxDate =
obs
|> List.map (fun ob -> ob.Date)
|> List.max
{ Symbol = symbol
Date = maxDate
Return = cumulativeSimpleReturn } ]
// The above code assigned intermediate values
// to make each of the steps easy to see.
// It is good to see intermediate values when you are learning.
// But when you have more experience, you can tell from the types
// what is going on and it becomes less necessary to assign
// intermediate values.
//
// Thus it would also be possible to do the same thing
// without assigning intermediate values using the code below.
//
// use whichever style is easiest for you.
returns
|> List.groupBy(fun x -> x.Symbol, x.Date.Year, x.Date.Month)
|> List.map(fun ((symbol, year, month), obs) ->
let cumulativeLogReturn = obs |> List.sumBy (fun ob -> log (1.0+ ob.Return))
{ Symbol = symbol
Date = obs |> List.map(fun ob -> ob.Date) |> List.max
Return = exp(cumulativeLogReturn) - 1.0 })
val groupsForMonthlyReturn: ((string * int * int) * ReturnOb list) list =
[(("AAPL", 2021, 1),
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }]);
(("AAPL", 2021, 2),
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }; { Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]);
(("TSLA", 2021, 1),
[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }]);
(("TSLA", 2021, 2),
[{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }; { Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }])]
val exampleSimpleReturns: float list = [0.1; -0.2; 0.3]
val exampleLogReturns: float list =
[0.0953101798; -0.2231435513; 0.2623642645]
val cumulativeLogReturns: float = 0.134530893
val cumulativeSimpleReturns: float = 0.144
val it: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1331495388 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.02704464906 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.1609068633 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.2013744809 }]
Question 18
Given returns : ReturnOb list
, calculate the standard deviation of daily returns
for every symbol each month.
Give the result as a ValueOb list
where the date in each ValueOb
is the last date for the symbol
each month.
answerreturns
|> List.groupBy(fun x -> x.Symbol, x.Date.Year, x.Date.Month)
|> List.map(fun ((symbol, _year, _month), xs) ->
let sd = xs |> stDevBy(fun x -> x.Return)
{ Symbol = symbol
Date = xs |> List.map(fun x -> x.Date) |> List.max
Value = sd })
val it: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.106796419 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.136976765 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.03113263046 }]
Question 19
Given returns : ReturnOb list
, calculate the standard deviation of daily returns
for every symbol using rolling 3 day windows.
Give the result as a ValueOb list
where the date in each ValueOb
is the last date for the symbol
in the window.
answer Breaking this answer down,
If you're unsure, it's helpful to work through things step by step.
then build up from there. Now take the inner-most code operating on a single window
and make a function by copying and pasting inside a function.
often using more general variable names test it on your window check now a function to create the windows check so now we can do Cool, now first obs was the obs from the first group.
we could do function to operate on a group.
our group is a tuple of test it on the first group now make the group and apply my
group function to each group Okay, but this is an list of is the first group of results is the second group. I don't want an list of lists.
I just want one list of value obs. So what's the first thing in the list? check, this should evaluate to why did I write the answer using an anonymous function instead of functions like this?
I use reusable functions for something I'm going to use multiple times.
If it's something I'll do once, and it's not too many lines, then I use
the anonymous lambda function. As you get more experience, you can code using
the type signatures to tell you what everything is. And I don't actually
have to running it step by step.
however, starting out especially, I think you'll find it helpful
to kinda break things down like I did here. first group of windows second group of windows Now concatenate the windows. same as if I'd used collect instead of map and then concat compare them If they're not true, make sure they're sorted the same before you take the first obs. Now, standard deviations of the windows' returnsreturns
|> List.groupBy(fun x -> x.Symbol)
|> List.collect(fun (_symbol, xs) ->
xs
|> List.sortBy(fun x -> x.Date)
|> List.windowed 3
|> List.map(fun ys ->
let last = ys |> List.last
{ Symbol = last.Symbol
Date = last.Date
Value = ys |> stDevBy(fun x -> x.Return)}))
val it: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1401026193 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.106796419 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.136976765 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1079983767 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.03113263046 }]
let groups =
returns
|> List.groupBy(fun x -> x.Symbol)
val groups: (string * ReturnOb list) list =
[("AAPL",
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]);
("TSLA",
[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }])]
let firstGroup = groups[0] // or groups |> List.head
let firstSymbol, firstObs = firstGroup // like let a,b = (1,2)
let windowedFirstObs =
firstObs
|> List.sortBy(fun x -> x.Date)
|> List.windowed 3
let firstWindow = windowedFirstObs[0]
let lastDayOfFirstWindow = firstWindow |> List.last
let firstWindowReturnStdDev = firstWindow |> stDevBy(fun x -> x.Return)
let firstWindowResult =
{ Symbol = lastDayOfFirstWindow.Symbol
Date = lastDayOfFirstWindow.Date
Value = firstWindowReturnStdDev }
val firstGroup: string * ReturnOb list =
("AAPL",
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }])
val firstSymbol: string = "AAPL"
val firstObs: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]
val windowedFirstObs: ReturnOb list list =
[[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }];
[{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 }; { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }];
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }];
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }; { Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]]
val firstWindow: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }]
val lastDayOfFirstWindow: ReturnOb = { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }
val firstWindowReturnStdDev: float = 0.1241051372
val firstWindowResult: ValueOb = { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }
let resultForWindow window =
let lastDay = window |> List.last
let stddev = window |> stDevBy(fun x -> x.Return)
{ Symbol = lastDay.Symbol
Date = lastDay.Date
Value = stddev }
val resultForWindow: window: ReturnOb list -> ValueOb
let firstWindowFunctionResult = resultForWindow firstWindow
val firstWindowFunctionResult: ValueOb = { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }
firstWindowResult = firstWindowFunctionResult // evaluates to true
val it: bool = true
let createWindows (days: ReturnOb list) =
days
|> List.sortBy(fun day -> day.Date)
|> List.windowed 3
val createWindows: days: ReturnOb list -> ReturnOb list list
(createWindows firstObs) = windowedFirstObs // evaluates to true
val it: bool = true
firstObs
|> createWindows
|> List.map resultForWindow
val it: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1401026193 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.106796419 }]
(string,ReturnObs list)
.
We're not going to use the string
variable, so we'll preface it
with _ to let the compiler know we're leaving it out o purpose.
the _ is not necessary but it's good practicelet resultsForGroup (_symbol, xs) =
xs
|> createWindows
|> List.map resultForWindow
val resultsForGroup: _symbol: 'a * xs: ReturnOb list -> ValueOb list
resultsForGroup firstGroup
val it: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1401026193 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.106796419 }]
let resultsForEachGroup =
returns
|> List.groupBy(fun x -> x.Symbol)
|> List.map resultsForGroup
val resultsForEachGroup: ValueOb list list =
[[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Value = 0.1401026193 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Value = 0.106796419 }];
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Value = 0.136976765 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Value = 0.1079983767 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Value = 0.03113263046 }]]
ValueOb list
(that's what ValueOb list list
means).
What happened is that I had an list of groups, and then I transformed each group.
so it's still one result per group. For instanceresultsForEachGroup[0]
val it: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1401026193 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.106796419 }]
resultsForEachGroup[1]
val it: ValueOb list =
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.136976765 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1079983767 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.03113263046 }]
concat
them.let resultsForEachGroupConcatenated =
resultsForEachGroup |> List.concat
val resultsForEachGroupConcatenated: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Value = 0.1401026193 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Value = 0.106796419 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Value = 0.136976765 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Value = 0.1079983767 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Value = 0.03113263046 }]
resultsForEachGroupConcatenated[0]
val it: ValueOb = { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Value = 0.1241051372 }
Collect
does the map
and concat
in one step.let resultsForEachGroupCollected =
returns
|> List.groupBy(fun x -> x.Symbol)
|> List.collect resultsForGroup
val resultsForEachGroupCollected: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Value = 0.1401026193 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Value = 0.106796419 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Value = 0.136976765 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Value = 0.1079983767 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Value = 0.03113263046 }]
true
resultsForEachGroupConcatenated[0] = resultsForEachGroupCollected[0]
val it: bool = true
Another way you can do it, similar to the first answer using
an anonymous lambda function, but now we'll do it with fewer
nested lists by concatenating/collecting the windows
into the parent list before doing the standard deviations.let m2Groups =
returns
|> List.groupBy(fun x -> x.Symbol)
let m2GroupsOfWindows =
m2Groups
|> List.map(fun (symbol, xs) ->
xs
|> List.sortBy(fun x -> x.Date)
|> List.windowed 3
)
val m2Groups: (string * ReturnOb list) list =
[("AAPL",
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]);
("TSLA",
[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }])]
val m2GroupsOfWindows: ReturnOb list list list =
[[[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }];
[{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 }; { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }];
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }];
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }; { Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }]];
[[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }];
[{ Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 }; { Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }];
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 }];
[{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }; { Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }]]]
m2GroupsOfWindows[0]
val it: ReturnOb list list =
[[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM {Date = 1/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Friday;
DayOfYear = 1;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637450560000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.02993466474 };
{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM {Date = 1/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Saturday;
DayOfYear = 2;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637451424000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1904072042 }];
[{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM {Date = 1/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Saturday;
DayOfYear = 2;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637451424000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.01626157984 }];
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.0767937252 }];
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1308654699 }]]
m2GroupsOfWindows[1]
val it: ReturnOb list list =
[[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM {Date = 1/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Friday;
DayOfYear = 1;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637450560000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.1487757845 };
{ Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM {Date = 1/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Saturday;
DayOfYear = 2;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637451424000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.108695795 }];
[{ Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM {Date = 1/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Saturday;
DayOfYear = 2;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637451424000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.108695795 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.04571273462 }];
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM {Date = 1/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Sunday;
DayOfYear = 3;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 1;
Nanosecond = 0;
Second = 0;
Ticks = 637452288000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = -0.108695795 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.099311576 }];
[{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM {Date = 2/1/2021 12:00:00 AM;
Day = 1;
DayOfWeek = Monday;
DayOfYear = 32;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637477344000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM {Date = 2/2/2021 12:00:00 AM;
Day = 2;
DayOfWeek = Tuesday;
DayOfYear = 33;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637478208000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.099311576 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM {Date = 2/3/2021 12:00:00 AM;
Day = 3;
DayOfWeek = Wednesday;
DayOfYear = 34;
Hour = 0;
Kind = Unspecified;
Microsecond = 0;
Millisecond = 0;
Minute = 0;
Month = 2;
Nanosecond = 0;
Second = 0;
Ticks = 637479072000000000L;
TimeOfDay = 00:00:00;
Year = 2021;}
Return = 0.04506957545 }]]
let m2GroupsOfWindowsConcatenated = m2GroupsOfWindows |> List.concat
val m2GroupsOfWindowsConcatenated: ReturnOb list list =
[[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }];
[{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 }; { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }];
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }];
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }; { Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }];
[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }];
[{ Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 }; { Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }];
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 }];
[{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }; { Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }]]
let m2GroupsOfWindowsCollected =
m2Groups
|> List.collect(fun (symbol, xs) ->
xs
|> List.sortBy(fun x -> x.Date)
|> List.windowed 3
)
val m2GroupsOfWindowsCollected: ReturnOb list list =
[[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }];
[{ Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 }; { Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 };
{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }];
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 }];
[{ Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Return = -0.01626157984 }; { Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Return = -0.0767937252 };
{ Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Return = 0.1308654699 }];
[{ Symbol = "TSLA"
Date = 1/1/2021 12:00:00 AM
Return = -0.1487757845 }; { Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }];
[{ Symbol = "TSLA"
Date = 1/2/2021 12:00:00 AM
Return = 0.1059620976 }; { Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 };
{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }];
[{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Return = -0.108695795 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 }];
[{ Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Return = 0.04571273462 }; { Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Return = 0.099311576 };
{ Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Return = 0.04506957545 }]]
let m2FirstConcatenated = m2GroupsOfWindowsConcatenated[0]
let m2FirstCollected = m2GroupsOfWindowsCollected[0]
m2FirstCollected = m2FirstConcatenated // true.
val m2FirstConcatenated: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }]
val m2FirstCollected: ReturnOb list =
[{ Symbol = "AAPL"
Date = 1/1/2021 12:00:00 AM
Return = -0.02993466474 }; { Symbol = "AAPL"
Date = 1/2/2021 12:00:00 AM
Return = -0.01872509079 };
{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Return = 0.1904072042 }]
val it: bool = true
let m2Result =
m2GroupsOfWindowsCollected
|> List.map(fun window ->
let lastDay = window |> List.last
{ Symbol = lastDay.Symbol
Date = lastDay.Date
Value = window |> stDevBy(fun x -> x.Return )})
val m2Result: ValueOb list =
[{ Symbol = "AAPL"
Date = 1/3/2021 12:00:00 AM
Value = 0.1241051372 }; { Symbol = "AAPL"
Date = 2/1/2021 12:00:00 AM
Value = 0.1200377524 };
{ Symbol = "AAPL"
Date = 2/2/2021 12:00:00 AM
Value = 0.1401026193 }; { Symbol = "AAPL"
Date = 2/3/2021 12:00:00 AM
Value = 0.106796419 };
{ Symbol = "TSLA"
Date = 1/3/2021 12:00:00 AM
Value = 0.136976765 }; { Symbol = "TSLA"
Date = 2/1/2021 12:00:00 AM
Value = 0.1107173508 };
{ Symbol = "TSLA"
Date = 2/2/2021 12:00:00 AM
Value = 0.1079983767 }; { Symbol = "TSLA"
Date = 2/3/2021 12:00:00 AM
Value = 0.03113263046 }]
namespace FSharp
--------------------
namespace Microsoft.FSharp
val string: value: 'T -> string
--------------------
type string = String
[<Struct>] type DateTime = new: year: int * month: int * day: int -> unit + 16 overloads member Add: value: TimeSpan -> DateTime member AddDays: value: float -> DateTime member AddHours: value: float -> DateTime member AddMicroseconds: value: float -> DateTime member AddMilliseconds: value: float -> DateTime member AddMinutes: value: float -> DateTime member AddMonths: months: int -> DateTime member AddSeconds: value: float -> DateTime member AddTicks: value: int64 -> DateTime ...
<summary>Represents an instant in time, typically expressed as a date and time of day.</summary>
--------------------
DateTime ()
(+0 other overloads)
DateTime(ticks: int64) : DateTime
(+0 other overloads)
DateTime(ticks: int64, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int) : DateTime
(+0 other overloads)
DateTime(date: DateOnly, time: TimeOnly, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, kind: DateTimeKind) : DateTime
(+0 other overloads)
DateTime(year: int, month: int, day: int, hour: int, minute: int, second: int, calendar: Globalization.Calendar) : DateTime
(+0 other overloads)
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = Double
--------------------
type float<'Measure> = float
type Random = new: unit -> unit + 1 overload member GetItems<'T> : choices: ReadOnlySpan<'T> * length: int -> 'T array + 2 overloads member Next: unit -> int + 2 overloads member NextBytes: buffer: byte array -> unit + 1 overload member NextDouble: unit -> float member NextInt64: unit -> int64 + 2 overloads member NextSingle: unit -> float32 member Shuffle<'T> : values: Span<'T> -> unit + 1 overload static member Shared: Random
<summary>Represents a pseudo-random number generator, which is an algorithm that produces a sequence of numbers that meet certain statistical requirements for randomness.</summary>
--------------------
Random() : Random
Random(Seed: int) : Random
<summary> Sets the random number generator used for sampling. </summary>
type RandBasic = interface IRandom new: unit -> RandBasic + 1 overload val mutable rnd: Random
--------------------
new: unit -> Random.RandBasic
new: n: int -> Random.RandBasic
<summary> Normal distribution. </summary>
module List from FSharp.Stats
<summary> Module to compute common statistical measure on list </summary>
--------------------
module List from Microsoft.FSharp.Collections
--------------------
type List = new: unit -> List static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float list static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float list
--------------------
type List<'T> = | op_Nil | op_ColonColon of Head: 'T * Tail: 'T list interface IReadOnlyList<'T> interface IReadOnlyCollection<'T> interface IEnumerable interface IEnumerable<'T> member GetReverseIndex: rank: int * offset: int -> int member GetSlice: startIndex: int option * endIndex: int option -> 'T list static member Cons: head: 'T * tail: 'T list -> 'T list member Head: 'T member IsEmpty: bool member Item: index: int -> 'T with get ...
--------------------
new: unit -> List
val decimal: value: 'T -> decimal (requires member op_Explicit)
--------------------
type decimal = Decimal
--------------------
type decimal<'Measure> = decimal
val list: float list
--------------------
type 'T list = List<'T>
<summary>Gets the year component of the date represented by this instance.</summary>
<returns>The year, between 1 and 9999.</returns>
<summary>Gets the month component of the date represented by this instance.</summary>
<returns>The month component, expressed as a value between 1 and 12.</returns>
<summary> Computes the sample standard deviation </summary>
<param name="f">A function applied to transform each element of the sequence.</param>
<param name="items">The input sequence.</param>
<remarks>Returns NaN if data is empty or if any entry is NaN.</remarks>
<returns>standard deviation of a sample (Bessel's correction by N-1)</returns>