Header menu logo Teaching

BinderScriptNotebook

Submitting your trading signal preferences.

You need to select your main trading signal. Everybody will examine a different signal, so you need to give me an ordered list of your preferred signals.

I will randomly iterate through students and assign them their top choice from among the signals remaining.

The signals are listed in the "Project signals list.xlsx" file that you can find on moodle. - Use the VARIABLE column to identify the variable that you want. - Do not use any other columns to identify your variable. - Only variables from that excel file are valid.

You will submit your choices as a .csv file. Here's how to do that.

Use the FSharp.Data CsvProvider to construct your csv file. All the csv related stuff below comes from things discussed somewhere on that webpage.

First construct a sample, then use the type provider to define the type from the sample.

Below you will find a variable named "signals". Do not modify it. This is to check that you do not have a typo in your preferred signals. The code that you use starts after the "Code starts now" section.

//****************************************
//*****Code starts below this section*****
//****************************************
// Do not modify the signals variable
let signals =
    ["niq_su"
     "ret_6_1"
     "ret_12_1"
     "saleq_su"
     "tax_gr1a"
     "ni_inc8q"
     "prc_highprc_252d"
     "resff3_6_1"
     "resff3_12_1"
     "be_me"
     "debt_me"
     "at_me"
     "ret_60_12"
     "ni_me"
     "fcf_me"
     "div12m_me"
     "eqpo_me"
     "eqnpo_me"
     "sale_gr3"
     "sale_gr1"
     "ebitda_mev"
     "sale_me"
     "ocf_me"
     "intrinsic_value"
     "bev_mev"
     "netdebt_me"
     "eq_dur"
     "capex_abn"
     "at_gr1"
     "ppeinv_gr1a"
     "noa_at"
     "noa_gr1a"
     "lnoa_gr1a"
     "capx_gr1"
     "capx_gr2"
     "capx_gr3"
     "chcsho_12m"
     "eqnpo_12m"
     "debt_gr3"
     "inv_gr1"
     "inv_gr1a"
     "oaccruals_at"
     "taccruals_at"
     "cowc_gr1a"
     "coa_gr1a"
     "col_gr1a"
     "nncoa_gr1a"
     "ncoa_gr1a"
     "ncol_gr1a"
     "nfna_gr1a"
     "sti_gr1a"
     "lti_gr1a"
     "fnl_gr1a"
     "be_gr1a"
     "oaccruals_ni"
     "taccruals_ni"
     "netis_at"
     "eqnetis_at"
     "dbnetis_at"
     "niq_be"
     "niq_be_chg1"
     "niq_at"
     "niq_at_chg1"
     "ebit_bev"
     "ebit_sale"
     "sale_bev"
     "at_turnover"
     "gp_at"
     "gp_atl1"
     "ope_be"
     "ope_bel1"
     "op_at"
     "op_atl1"
     "cop_at"
     "cop_atl1"
     "f_score"
     "o_score"
     "z_score"
     "pi_nix"
     "at_be"
     "saleq_gr1"
     "rd_me"
     "rd_sale"
     "opex_at"
     "emp_gr1"
     "rd5_at"
     "age"
     "dsale_dinv"
     "dsale_drec"
     "dgp_dsale"
     "dsale_dsga"
     "sale_emp_gr1"
     "tangibility"
     "kz_index"
     "ocfq_saleq_std"
     "cash_at"
     "ni_ar1"
     "ni_ivol"
     "earnings_variability"
     "aliq_at"
     "aliq_mat"
     "seas_1_1an"
     "seas_1_1na"
     "seas_2_5an"
     "seas_2_5na"
     "seas_6_10an"
     "seas_6_10na"
     "seas_11_15an"
     "seas_11_15na"
     "seas_16_20an"
     "seas_16_20na"
     "market_equity"
     "ivol_ff3_21d"
     "ivol_capm_252d"
     "ivol_capm_21d"
     "ivol_hxz4_21d"
     "rvol_21d"
     "beta_60m"
     "betabab_1260d"
     "beta_dimson_21d"
     "turnover_126d"
     "turnover_var_126d"
     "dolvol_126d"
     "dolvol_var_126d"
     "prc"
     "ami_126d"
     "zero_trades_21d"
     "zero_trades_126d"
     "zero_trades_252d"
     "rmax1_21d"
     "rskew_21d"
     "iskew_capm_21d"
     "iskew_ff3_21d"
     "iskew_hxz4_21d"
     "coskew_21d"
     "ret_1_0"
     "betadown_252d"
     "bidaskhl_21d"
     "ret_3_1"
     "ret_9_1"
     "ret_12_7"
     "corr_1260d"
     "rmax5_21d"
     "rmax5_rvol_21d"
     "ni_be"
     "ocf_at"
     "ocf_at_chg1"
     "mispricing_perf"
     "mispricing_mgmt"
     "qmj"
     "qmj_prof"
     "qmj_growth"
     "qmj_safety"]
    |> set 

//****************************************
//****Code starts now*********************
//****************************************
#r "nuget: FSharp.Data, 5.0.2"

open FSharp.Data
[<Literal>]
let submissionCsvSample = "StudentId (int), Preference (int), Signal (string)"

type SubmissionCsv = CsvProvider<submissionCsvSample>

What are your (ordered) preferences?

  1. Fill in with your student id so that I know who you are.
let myStudentId = 007

// check that you are paying attention:
if myStudentId = 007 then failwith "Are you sure that 007 is your student id number?"
  1. Fill in with your preferences
let myPreferences =
    // **Make sure you use the exact string from the VARIABLE column**
    // do as many choices as you want.
    // If you give me 3 and you run out of choices because
    // everybody else already took your top 3 choices,
    // then I will just randomly assign you something.
    //
    // So if you care it's probably best to give more choices.
    [
        "eqpo_me" // first choice **Use VARIABLE, not the name "Payout Yield"**
        "eqnpo_me"// second choice
        "sale_gr3"// third choice
        "sale_gr1"// fourth choice
    ]

This code checks if you have a typo in myPreferences Run it. If there's typo you will see an exception.

let typos =
    //[|"eqpo_me1";"eqpo_me2"|]
    myPreferences 
    |> List.filter (fun signal -> not (signals.Contains signal))
if not (List.isEmpty typos) then 
    let typos = typos |> String.concat " and "
    failwith ($"{typos} is not a signal. Check spelling.")
else printfn "%s" "Congrats, no typos"

let rowCreator i signal =
    // Csv types have a member .Row that constructs a row.
    // Technically, the Csv is a class and .Row is a member of that
    // class. But none of this matters. Just think of .Row as a
    // function that goes with the csv type that allows you to use
    // named parameters.
    //
    // if you hover over ".Row" below, you can see what the columns of the row
    // are (studentId,preference,signal). Intellisense should also
    // pop them up for you if you were typing it from scratch. Such
    // as delete the comma from "myStudentId," and then retype the comma.
    // you should see a popup with the column info saying what is in
    // a row.
    SubmissionCsv.Row
        (studentId=myStudentId,
         preference=i,
         signal=signal)

// test
let test1 = rowCreator 0 "sale_gr1"
test1.StudentId
test1.Signal
test1.Preference

We'll use List.mapi to create our rows. List.mapi is like List.map, but it adds the index of the list (i) as a parameter to the function. This is useful when you want to use the index of the element in the list as part of your function.

Here, we've ordered our list myPreferences based on our first, second, 3rd choice etc. So we're using the index of the element in the list as our preference column.

0 is first choice, 1 is second choice, 2 is 3rd choice ...

let mySubmission =
    myPreferences
    // What we have below is the same as
    // |> List.mapi(fun i x -> rowCreator i x)
    //
    // but because we wrote rowCreator to accept i and x
    // as the first two function inputs, we can 
    // take the shortcut and do below.
    |> List.mapi rowCreator

This is an array of rows.

Check your first preference

let myFirstPreference = mySubmission |> List.head

myFirstPreference.StudentId // make sure it's not 7
myFirstPreference.Preference // should be 0
myFirstPreference.Signal // choose wisely

(*
Rather than an "list of csv rows", we want a "csv file".

Here's how we do that. We pass the SubmissionCsv.Rows contained
in the mySubmission array  to the
SubmissionCsv type constructor like so.
*)
let mySubmissionFile = new SubmissionCsv(mySubmission)

Ok, let's write the file. Remember that __SOURCE_DIRECTORY__ is a magic variable that points to whatever folder this script file (aka the source code file) is contained in.

So this will write a csv file in the current directory.

let fileName = $"{myStudentId}.csv"
let fullFilePath = __SOURCE_DIRECTORY__}/{fileName}"

mySubmissionFile.Save(fullFilePath)

Now find that file and submit it. Also click on it in visual studio code; you should be able to see what the file looks like. It's just a text file with a .csv extension.

and if you want to read the data back in from the file to see that it works:

let backIn = SubmissionCsv.Load(fullFilePath)

backIn.Rows
|> Seq.toList
|> List.map(fun row -> row.Preference, row.Signal)
val signals: Set<string>
val set: elements: 'T seq -> Set<'T> (requires comparison)
Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
Multiple items
namespace FSharp.Data

--------------------
namespace Microsoft.FSharp.Data
Multiple items
type LiteralAttribute = inherit Attribute new: unit -> LiteralAttribute

--------------------
new: unit -> LiteralAttribute
[<Literal>] val submissionCsvSample: string = "StudentId (int), Preference (int), Signal (string)"
type SubmissionCsv = CsvProvider<...>
type CsvProvider
<summary>Typed representation of a CSV file.</summary> <param name='Sample'>Location of a CSV sample file or a string containing a sample CSV document.</param> <param name='Separators'>Column delimiter(s). Defaults to <c>,</c>.</param> <param name='InferRows'>Number of rows to use for inference. Defaults to <c>1000</c>. If this is zero, all rows are used.</param> <param name='Schema'>Optional column types, in a comma separated list. Valid types are <c>int</c>, <c>int64</c>, <c>bool</c>, <c>float</c>, <c>decimal</c>, <c>date</c>, <c>datetimeoffset</c>, <c>timespan</c>, <c>guid</c>, <c>string</c>, <c>int?</c>, <c>int64?</c>, <c>bool?</c>, <c>float?</c>, <c>decimal?</c>, <c>date?</c>, <c>datetimeoffset?</c>, <c>timespan?</c>, <c>guid?</c>, <c>int option</c>, <c>int64 option</c>, <c>bool option</c>, <c>float option</c>, <c>decimal option</c>, <c>date option</c>, <c>datetimeoffset option</c>, <c>timespan option</c>, <c>guid option</c> and <c>string option</c>. You can also specify a unit and the name of the column like this: <c>Name (type&lt;unit&gt;)</c>, or you can override only the name. If you don't want to specify all the columns, you can reference the columns by name like this: <c>ColumnName=type</c>.</param> <param name='HasHeaders'>Whether the sample contains the names of the columns as its first line.</param> <param name='IgnoreErrors'>Whether to ignore rows that have the wrong number of columns or which can't be parsed using the inferred or specified schema. Otherwise an exception is thrown when these rows are encountered.</param> <param name='SkipRows'>Skips the first n rows of the CSV file.</param> <param name='AssumeMissingValues'>When set to true, the type provider will assume all columns can have missing values, even if in the provided sample all values are present. Defaults to false.</param> <param name='PreferOptionals'>When set to true, inference will prefer to use the option type instead of nullable types, <c>double.NaN</c> or <c>""</c> for missing values. Defaults to false.</param> <param name='Quote'>The quotation mark (for surrounding values containing the delimiter). Defaults to <c>"</c>.</param> <param name='MissingValues'>The set of strings recognized as missing values specified as a comma-separated string (e.g., "NA,N/A"). Defaults to <c>NaN,NA,N/A,#N/A,:,-,TBA,TBD</c>.</param> <param name='CacheRows'>Whether the rows should be caches so they can be iterated multiple times. Defaults to true. Disable for large datasets.</param> <param name='Culture'>The culture used for parsing numbers and dates. Defaults to the invariant culture.</param> <param name='Encoding'>The encoding used to read the sample. You can specify either the character set name or the codepage number. Defaults to UTF8 for files, and to ISO-8859-1 the for HTTP requests, unless <c>charset</c> is specified in the <c>Content-Type</c> response header.</param> <param name='ResolutionFolder'>A directory that is used when resolving relative file references (at design time and in hosted execution).</param> <param name='EmbeddedResource'>When specified, the type provider first attempts to load the sample from the specified resource (e.g. 'MyCompany.MyAssembly, resource_name.csv'). This is useful when exposing types generated by the type provider.</param>
val myStudentId: int
val failwith: message: string -> 'T
val myPreferences: string list
val typos: string 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 filter: predicate: ('T -> bool) -> list: 'T list -> 'T list
val signal: string
member Set.Contains: value: 'T -> bool
val isEmpty: list: 'T list -> bool
val typos: string
module String from Microsoft.FSharp.Core
val concat: sep: string -> strings: string seq -> string
val printfn: format: Printf.TextWriterFormat<'T> -> 'T
val rowCreator: i: int -> signal: string -> CsvProvider<...>.Row
val i: int
type Row = inherit int * int * string new: studentId: int * preference: int * signal: string -> Row member Preference: int member Signal: string member StudentId: int
val test1: CsvProvider<...>.Row
property CsvProvider<...>.Row.StudentId: int with get
property CsvProvider<...>.Row.Signal: string with get
property CsvProvider<...>.Row.Preference: int with get
val mySubmission: CsvProvider<...>.Row list
val mapi: mapping: (int -> 'T -> 'U) -> list: 'T list -> 'U list
val myFirstPreference: CsvProvider<...>.Row
val head: list: 'T list -> 'T
val mySubmissionFile: SubmissionCsv
val fileName: string
val fullFilePath: string
member Runtime.CsvFile.Save: path: string * [<System.Runtime.InteropServices.Optional>] ?separator: char * [<System.Runtime.InteropServices.Optional>] ?quote: char -> unit
member Runtime.CsvFile.Save: stream: System.IO.Stream * [<System.Runtime.InteropServices.Optional>] ?separator: char * [<System.Runtime.InteropServices.Optional>] ?quote: char -> unit
member Runtime.CsvFile.Save: writer: System.IO.TextWriter * [<System.Runtime.InteropServices.Optional>] ?separator: char * [<System.Runtime.InteropServices.Optional>] ?quote: char -> unit
val backIn: CsvProvider<...>
CsvProvider<...>.Load(uri: string) : CsvProvider<...>
Loads CSV from the specified uri
CsvProvider<...>.Load(reader: System.IO.TextReader) : CsvProvider<...>
Loads CSV from the specified reader
CsvProvider<...>.Load(stream: System.IO.Stream) : CsvProvider<...>
Loads CSV from the specified stream
property Runtime.CsvFile.Rows: CsvProvider<...>.Row seq with get
<summary> The rows with data </summary>
module Seq from Microsoft.FSharp.Collections
val toList: source: 'T seq -> 'T list
val map: mapping: ('T -> 'U) -> list: 'T list -> 'U list
val row: CsvProvider<...>.Row

Type something to start searching.