Downloading stock prices in F# - Part I - Data modeling

-

Other parts:

Today we shipped the September CTP of F# !!! Evviva !! Read this blog post about it. To cel­e­brate I de­cided to share one of my sev­eral F# pro­ject. It might make for a good sam­ple; sort of a crash course on F#.

This ap­pli­ca­tion down­loads stock prices, div­i­dends and splits from Yahoo Historical Prices and per­forms com­pu­ta­tions on them. I will de­scribe it file by file.

com­mon.fs

I al­ways have such a file in my pro­jects. It is a repos­i­tory for the types that I’m go­ing to use in my pro­gram and the func­tions that are com­mon across mul­ti­ple mod­ules. If I have a large pro­gram I also have a types.fs just for the types.

This one starts like this:

#light
open System
[<Measure>] type money
let money (f:float) = f * 1.<money>
[<Measure>] type shares
let shares (f:float) = f * 1.<shares>
[<Measure>] type volume
let volume (f:float) = f * 1.<volume>
[<Measure>] type rateOfReturn
let rateOfReturn (f:float) = f * 1.<rateOfReturn>

The first line in­structs the com­piler to use the light­weight syn­tax. You don’t want to know what the heavy­weight syn­tax is. Just al­ways put such a line at the start of your files. The next line opens up the System name­space. Then the good stuff starts.

I’m defin­ing some units of mea­sures. The sim­plest way to think about units of mea­sures is: they are a type sys­tem for floats. You can do much more than that, but it is a good first ap­prox­i­ma­tion. For ex­am­ple, you can­not now sum a money type and a vol­ume type. Also for each one I de­fine a func­tion that con­verts from a nor­mal float type to it (if you come from a C# back­ground, floats are dou­bles).

Then I de­fine the data model for my ap­pli­ca­tion:

type Span = { Start: DateTime; End: DateTime }
type Price = { Open: float<money>; High: float<money>; Low:float<money>; 
Close:float<money>; Volume: float<volume>} type Event = | Price of Price | Split of float | Div of float<money> type Observation = { Date: DateTime; Event: Event}

The first record that I de­fine, Span,  rep­re­sents the dif­fer­ence be­tween two dates. It is just a lit­tle use­ful thing. A more fun­da­men­tal record is Observation. An Observation is de­fined as some­thing that hap­pens on a par­tic­u­lar Date. That some­thing, an Event, can be one of three things: a Price, a Split or a Div. A Price is an­other record with a bunch of float fields and on float field. If you go to the Yahoo site, you’ll see what it rep­re­sents.

A Split is sim­ply a float. Why not a float<>? Because it is just a num­ber, a fac­tor to be pre­cise. It rep­re­sents the num­ber of new shares di­vided by the num­ber of old shares. float / float = float. A Div is a float.

This is one way to model the prob­lem. Infinite other ways are pos­si­ble (and I tried many of them in a C# ver­sion of this code that ended up us­ing poly­mor­phism). Note that all of the types are records ex­cept Event that is a dis­crim­i­nated union.

Records are read only con­tain­ers of data. Discriminated unions are what the name says: things that can be one of mul­ti­ple things (even re­cur­sively). They are rather handy to rep­re­sent the struc­ture of the data. We will see how you use them us­ing the match op­er­a­tor in up­com­ing posts.

Also no­tice the fol­low­ing com­mon pat­tern in F# (and func­tional pro­gram­ming in gen­eral). You de­fine your data and then you de­fine trans­for­ma­tions over it. F# has a third op­tional step, that is to ex­pose these trans­for­ma­tions as meth­ods of a .NET ob­jects.

We are al­most done here. A hand­ful of other func­tions are in my file :

let span sy sm sd ey em ed =
{Start = new DateTime(sy, sm, sd); End = new DateTime(ey, em, ed)} let date y m d = new DateTime(y, m, d) let now () = DateTime.Now let idem x = x let someIdem x = Some(x)

Span is a func­tion that cre­ates a span given the rel­e­vant info. date cre­ates a date given year, month and day. now is a value that cor­re­sponds to the cur­rent date. idem is a func­tion that re­turns its pa­ra­me­ter (you’ll see how that can pos­si­bly be use­ful). someI­dem is a func­tion that un­pack an Option type and gives his value. I could write all my code with­out these things, but it looks bet­ter (to me) with them.

Notice that in the F# code you have ac­cess to all the func­tions and type in the .NET frame­work. It is just an­other .NET lan­guage: it can cre­ate or con­sume .NET types.

All right, we are done for part one. In part II there will be some real code.

Tags

13 Comments

Comments

Matthew Podwysocki

2008-08-30T01:17:59Z

Don Syme just an­nounced to­day the F# Community Technical Preview (CTP) Release September 2008 which is

Matthew Podwysocki's Blog

2008-08-30T01:20:06Z

Don Syme just an­nounced to­day the F# Community Technical Preview (CTP) Release September 2008 which is

Community Blogs

2008-08-30T01:55:30Z

Don Syme just an­nounced to­day the F# Community Technical Preview (CTP) Release September 2008 which is

Jomo Fisher -- Sharp Things

2008-08-30T11:37:32Z

- Downloading stock prices in F# - Part I - Data mod­el­ing [ red­dit ] - Units of Measure in F#: Part One,

Chris Smith's completely uniqu

2008-08-31T01:26:53Z

Wow, what a busy week!&#160 The F# CTP is out the door, and it’s al­ready mak­ing re­ver­ber­a­tions around

Luca Bolognese's WebLog

2008-09-05T14:41:19Z

Other parts: Part I - Data mod­el­ing Getting stock prices and div­i­dends is rel­a­tively easy given that,

Luca Bolognese's WebLog

2008-09-12T16:18:11Z

Other parts: Part I - Data mod­el­ing Part II - Html scrap­ing It is now time to load our data. There is

Luca Bolognese's WebLog

2008-09-19T17:59:38Z

Other parts: Part I - Data mod­el­ing Part II - Html scrap­ing Part III - Async loader for prices and divs

You prob­a­bly want to change your de­f­i­n­i­tion of now:
 “let now() = DateTime.Now”
in stead of
 “let now = DateTime.Now”
The cur­rent de­f­i­n­i­tion binds a con­stant value.

Yeah, you are right. It is a bug.
In this case it does­n’t re­ally mat­ter be­cause I use it just for my test­cases. But it is a bug. I’ll fix it in the post.

Luca Bolognese's WebLog

2008-09-26T16:04:18Z

Other parts: Part I - Data mod­el­ing Part II - Html scrap­ing Part III - Async loader for prices and divs

Luca Bolognese's WebLog

2008-10-20T18:45:51Z

Other parts: Part I - Data mod­el­ing Part II - Html scrap­ing Part III - Async loader for prices and divs