Downloading stock prices in F# - Part I - Data modeling
Luca -
☕ 3 min. read
Other parts:
- Part II - Html scraping
- Part III - Async loader for prices and divs
- Part IV - Async loader for splits
- Part V - Adjusting historical data
- Part VI - Code posted
Today we shipped the September CTP of F# !!! Evviva !! Read this blog post about it. To celebrate I decided to share one of my several F# project. It might make for a good sample; sort of a crash course on F#.
This application downloads stock prices, dividends and splits from Yahoo Historical Prices and performs computations on them. I will describe it file by file.
common.fs
I always have such a file in my projects. It is a repository for the types that I’m going to use in my program and the functions that are common across multiple modules. If I have a large program 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 instructs the compiler to use the lightweight syntax. You don’t want to know what the heavyweight syntax is. Just always put such a line at the start of your files. The next line opens up the System namespace. Then the good stuff starts.
I’m defining some units of measures. The simplest way to think about units of measures is: they are a type system for floats. You can do much more than that, but it is a good first approximation. For example, you cannot now sum a money type and a volume type. Also for each one I define a function that converts from a normal float type to it (if you come from a C# background, floats are doubles).
Then I define the data model for my application:
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 define, Span, represents the difference between two dates. It is just a little useful thing. A more fundamental record is Observation. An Observation is defined as something that happens on a particular Date. That something, an Event, can be one of three things: a Price, a Split or a Div. A Price is another record with a bunch of float
A Split is simply a float. Why not a float<>? Because it is just a number, a factor to be precise. It represents the number of new shares divided by the number of old shares. float
This is one way to model the problem. Infinite other ways are possible (and I tried many of them in a C# version of this code that ended up using polymorphism). Note that all of the types are records except Event that is a discriminated union.
Records are read only containers of data. Discriminated unions are what the name says: things that can be one of multiple things (even recursively). They are rather handy to represent the structure of the data. We will see how you use them using the match operator in upcoming posts.
Also notice the following common pattern in F# (and functional programming in general). You define your data and then you define transformations over it. F# has a third optional step, that is to expose these transformations as methods of a .NET objects.
We are almost done here. A handful of other functions 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 function that creates a span given the relevant info. date creates a date given year, month and day. now is a value that corresponds to the current date. idem is a function that returns its parameter (you’ll see how that can possibly be useful). someIdem is a function that unpack an Option type and gives his value. I could write all my code without these things, but it looks better (to me) with them.
Notice that in the F# code you have access to all the functions and type in the .NET framework. It is just another .NET language: it can create or consume .NET types.
All right, we are done for part one. In part II there will be some real code.
0 Webmentions
These are webmentions via the IndieWeb and webmention.io.
13 Comments
Comments
a-foton &raquo; Downloadin
2008-08-29T19:46:59ZPingBack from http://blog.a-foton.ru/2008/08/downloading-stock-prices-in-f-part-i-data-modeling/
Matthew Podwysocki
2008-08-30T01:17:59ZDon Syme just announced today the F# Community Technical Preview (CTP) Release September 2008 which is
Matthew Podwysocki's Blog
2008-08-30T01:20:06ZDon Syme just announced today the F# Community Technical Preview (CTP) Release September 2008 which is
Community Blogs
2008-08-30T01:55:30ZDon Syme just announced today 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 modeling [ reddit ] - Units of Measure in F#: Part One,
Chris Smith's completely uniqu
2008-08-31T01:26:53ZWow, what a busy week!  The F# CTP is out the door, and it's already making reverberations around
Luca Bolognese's WebLog
2008-09-05T14:41:19ZOther parts: Part I - Data modeling Getting stock prices and dividends is relatively easy given that,
Luca Bolognese's WebLog
2008-09-12T16:18:11ZOther parts: Part I - Data modeling Part II - Html scraping It is now time to load our data. There is
Luca Bolognese's WebLog
2008-09-19T17:59:38ZOther parts: Part I - Data modeling Part II - Html scraping Part III - Async loader for prices and divs
Carl
2008-09-24T06:50:12ZYou probably want to change your definition of now:
"let now() = DateTime.Now"
in stead of
"let now = DateTime.Now"
The current definition binds a constant value.
lucabol
2008-09-24T11:21:40ZYeah, you are right. It is a bug.
In this case it doesn't really matter because I use it just for my testcases. But it is a bug. I'll fix it in the post.
Luca Bolognese's WebLog
2008-09-26T16:04:18ZOther parts: Part I - Data modeling Part II - Html scraping Part III - Async loader for prices and divs
Luca Bolognese's WebLog
2008-10-20T18:45:51ZOther parts: Part I - Data modeling Part II - Html scraping Part III - Async loader for prices and divs