Header menu logo Teaching

Script

module Portfolio

open System

/// Misc
/// 

type SecurityId =
    | Ticker of string
    | Cusip of string
    | Bloomberg of string
    | Permno of int
    | Other of string

type InvestmentUniverse = 
    { FormationMonth : DateTime 
      Securities : SecurityId list }

type SecuritySignal = 
    { SecurityId : SecurityId
      Signal : float }

type SecuritiesWithSignals =
    { FormationMonth : DateTime 
      Signals : SecuritySignal list }

type PortfolioId = 
    | Named of string
    | Indexed of {| Name: string; Index: int |}
    override this.ToString() = 
        match this with
        | Named name -> name
        | Indexed p -> $"{p.Name}: {p.Index}"

type AssignedPortfolio =
    { PortfolioId : PortfolioId
      FormationMonth : DateTime 
      Signals : SecuritySignal list }


let assignSignalSort name n (xs: SecuritiesWithSignals) =
    xs.Signals
    |> List.sortBy(fun x -> x.Signal)
    |> List.splitInto n
    |> List.mapi(fun i ys -> 
        // because lists are 0-indexed and I want the minimum
        // portfolio index to be 1, I'm doing index = i+1.
        { PortfolioId = Indexed {| Name = name; Index=i+1 |}
          FormationMonth = xs.FormationMonth
          Signals = ys })

type Position =
    { SecurityId : SecurityId 
      Weight : float }

type Portfolio = 
    { PortfolioId: PortfolioId
      FormationMonth : DateTime
      Positions : Position list }

type PortfolioReturn =
    { PortfolioId: PortfolioId
      YearMonth : DateTime
      Return : float }

// This type alias defines the type of a function that has
// a tuple input of SecurityId * YearMonth and outputs
// a (SecurityId * float) Option. Think of it like
// using types to write documentation of the functions.
type GetsMarketCaps = SecurityId * DateTime -> (SecurityId * float) Option

// Defining this type alias makes it easier to read the type of the function that I want for
// marketCapGetter in the function that I have below. Otherwise it might look something like
// let giveValueWeights (marketCapGetter: (SecurityId * YearMonth -> (SecurityId * float) Option) ...
// which is the same thing but not as clear what we're trying to do.
let giveValueWeights (marketCapGetter: GetsMarketCaps) (x: AssignedPortfolio) =
    let mktCaps =
        x.Signals
        // List.choose throws away None results, so this means 
        // that if the market cap getter returns None
        // then we will not have that security in our portfolio.
        |> List.choose(fun signal -> marketCapGetter (signal.SecurityId, x.FormationMonth))

    let totMktCap = mktCaps |> List.sumBy snd

    let pos =
        mktCaps
        |> List.map(fun (id, mktCap) ->
            { SecurityId = id 
              Weight = mktCap / totMktCap })
    { PortfolioId = x.PortfolioId
      FormationMonth = x.FormationMonth 
      Positions = pos }

// This type alias defines the type of a function that has
// a tuple input of SecurityId * YearMonth and outputs
// a (SecurityId * float). Think of it like
// using types to write documentation of the functions.
type GetsReturn = SecurityId * DateTime -> (SecurityId * float)

// Defining this type alias makes it easier to read the type of the function that I want for
// marketCapGetter in the function that I have below. Otherwise it might look something like
// let giveValueWeights (marketCapGetter: (SecurityId * YearMonth -> (SecurityId * float) Option) ...
// which is the same thing but not as clear what we're trying to do.
let getPortfolioReturn (returnGetter: GetsReturn) (x: Portfolio) =
    let returnMonth = x.FormationMonth.AddMonths(1)
    let portRet =
        x.Positions
        |> List.sumBy(fun pos -> 
            let (_id, ret) = returnGetter (pos.SecurityId, returnMonth)
            pos.Weight * ret)
    { PortfolioId = x.PortfolioId
      YearMonth = returnMonth
      Return = portRet }


/// This function takes a sample start and sample end
/// and returns a list with all months from start to end.
/// Don't worry about understanding what this function does.
/// The details are beyond the scope of the class, but if you're
/// curious it's a recursive function:
/// https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/functions/recursive-functions-the-rec-keyword
let getSampleMonths (sampleStart:DateTime, sampleEnd:DateTime) =
    let sampleStart = DateTime(sampleStart.Year, sampleStart.Month,1)
    let sampleEnd = DateTime(sampleEnd.Year, sampleEnd.Month,1)
    if sampleEnd <= sampleStart then failwith "sampleEnd should be after sampleStart"
    let rec loop (sampleEnd:DateTime) window = 
        match window with
        | [] -> failwith "Need a starting point"
        | lastMonth::_monthsBeforeThat ->
            if lastMonth < sampleEnd then 
                loop sampleEnd (lastMonth.AddMonths(1)::window)
            else window
    loop sampleEnd [sampleStart]
    |> List.rev
type Portfolio = { PortfolioId: PortfolioId FormationMonth: DateTime Positions: Position list }
namespace System
type SecurityId = | Ticker of string | Cusip of string | Bloomberg of string | Permno of int | Other of string
 Misc
 
Multiple items
val string: value: 'T -> string

--------------------
type string = String
Multiple items
val int: value: 'T -> int (requires member op_Explicit)

--------------------
type int = int32

--------------------
type int<'Measure> = int
type InvestmentUniverse = { FormationMonth: DateTime Securities: SecurityId list }
Multiple items
[<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)
type 'T list = List<'T>
type SecuritySignal = { SecurityId: SecurityId Signal: float }
Multiple items
val float: value: 'T -> float (requires member op_Explicit)

--------------------
type float = Double

--------------------
type float<'Measure> = float
type SecuritiesWithSignals = { FormationMonth: DateTime Signals: SecuritySignal list }
Multiple items
[<Struct>] type Index = new: value: int * ?fromEnd: bool -> unit member Equals: other: Index -> bool + 1 overload member GetHashCode: unit -> int member GetOffset: length: int -> int member ToString: unit -> string static member FromEnd: value: int -> Index static member FromStart: value: int -> Index static member op_Implicit: value: int -> Index member IsFromEnd: bool member Value: int ...
<summary>Represents a type that can be used to index a collection either from the beginning or the end.</summary>

--------------------
Index ()
Index(value: int, ?fromEnd: bool) : Index
val this: PortfolioId
union case PortfolioId.Named: string -> PortfolioId
val name: string
union case PortfolioId.Indexed: {| Index: int; Name: string |} -> PortfolioId
val p: {| Index: int; Name: string |}
anonymous record field Name: string
type AssignedPortfolio = { PortfolioId: PortfolioId FormationMonth: DateTime Signals: SecuritySignal list }
type PortfolioId = | Named of string | Indexed of {| Index: int; Name: string |} override ToString: unit -> string
val assignSignalSort: name: string -> n: int -> xs: SecuritiesWithSignals -> AssignedPortfolio list
val n: int
val xs: SecuritiesWithSignals
SecuritiesWithSignals.Signals: SecuritySignal list
Multiple items
module List from Microsoft.FSharp.Collections

--------------------
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 ...
val sortBy: projection: ('T -> 'Key) -> list: 'T list -> 'T list (requires comparison)
val x: SecuritySignal
SecuritySignal.Signal: float
val splitInto: count: int -> list: 'T list -> 'T list list
val mapi: mapping: (int -> 'T -> 'U) -> list: 'T list -> 'U list
val i: int
val ys: SecuritySignal list
SecuritiesWithSignals.FormationMonth: DateTime
type Position = { SecurityId: SecurityId Weight: float }
type PortfolioReturn = { PortfolioId: PortfolioId YearMonth: DateTime Return: float }
type GetsMarketCaps = SecurityId * DateTime -> Option<SecurityId * float>
module Option from Microsoft.FSharp.Core
val giveValueWeights: marketCapGetter: GetsMarketCaps -> x: AssignedPortfolio -> Portfolio
val marketCapGetter: GetsMarketCaps
val x: AssignedPortfolio
val mktCaps: (SecurityId * float) list
AssignedPortfolio.Signals: SecuritySignal list
val choose: chooser: ('T -> 'U option) -> list: 'T list -> 'U list
val signal: SecuritySignal
SecuritySignal.SecurityId: SecurityId
AssignedPortfolio.FormationMonth: DateTime
val totMktCap: float
val sumBy: projection: ('T -> 'U) -> list: 'T list -> 'U (requires member (+) and member Zero)
val snd: tuple: ('T1 * 'T2) -> 'T2
val pos: Position list
val map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
val id: SecurityId
val mktCap: float
AssignedPortfolio.PortfolioId: PortfolioId
type GetsReturn = SecurityId * DateTime -> SecurityId * float
val getPortfolioReturn: returnGetter: GetsReturn -> x: Portfolio -> PortfolioReturn
val returnGetter: GetsReturn
val x: Portfolio
val returnMonth: DateTime
Portfolio.FormationMonth: DateTime
DateTime.AddMonths(months: int) : DateTime
val portRet: float
Portfolio.Positions: Position list
val pos: Position
val _id: SecurityId
val ret: float
Position.SecurityId: SecurityId
Position.Weight: float
Portfolio.PortfolioId: PortfolioId
val getSampleMonths: sampleStart: DateTime * sampleEnd: DateTime -> DateTime list
 This function takes a sample start and sample end
 and returns a list with all months from start to end.
 Don't worry about understanding what this function does.
 The details are beyond the scope of the class, but if you're
 curious it's a recursive function:
 https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/functions/recursive-functions-the-rec-keyword
val sampleStart: DateTime
val sampleEnd: DateTime
property DateTime.Year: int with get
<summary>Gets the year component of the date represented by this instance.</summary>
<returns>The year, between 1 and 9999.</returns>
property DateTime.Month: int with get
<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>
val failwith: message: string -> 'T
val loop: sampleEnd: DateTime -> window: DateTime list -> DateTime list
val window: DateTime list
val lastMonth: DateTime
val _monthsBeforeThat: DateTime list
val rev: list: 'T list -> 'T list

Type something to start searching.