Here is the final program:
------------------------------------------------------------------------------
#light
open System
open System.Collections.Generic
open System.IO
open System.Data.SqlClient
open System.Text.RegularExpressions
open System.Net
[<Measure>] type dollars
[<Measure>] type volume
let money (f:float) = f * 1.<dollars>
let vol (f:float) = f * 1.<volume>
let toFloat (someBucks : float<dollars>) =
someBucks / 1.0<dollars>
type Span = { Start: DateTime; End: DateTime }
type Price = { Open: float<dollars>; High: float<dollars>; Low:float<dollars>; Close:float<dollars>; Volume: float<volume>}
type Event =
| StkPrice of Price
| Split of float
| Dividend of float<dollars>
type Observation = { Date: DateTime; Event: Event}
let span sy sm sd ey em ed = {Start = new DateTime(sy, sm, sd); End = new DateTime(ey, em, ed)}
let commonUrl ticker span =
@"http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&a="
+ (span.Start.Month - 1).ToString()
+ "&b=" + span.Start.Day.ToString()
+ "&c=" + span.Start.Year.ToString()
+ "&d=" + (span.End.Month - 1).ToString()
+ "&e=" + span.End.Day.ToString()
+ "&f=" + span.End.Year.ToString()
let priceUrl ticker span = commonUrl ticker span + "&g=d&ignore=.csv"
let parsePrice (line: string) =
let tokens = line.Split([|','|])
{ Date = DateTime.Parse(tokens.[0]);
Event = StkPrice ({Open = money (Double.Parse(tokens.[1]));
High = money (Double.Parse(tokens.[2]));
Low = money (Double.Parse(tokens.[3]));
Close = money (Double.Parse(tokens.[4]));
Volume = vol (Double.Parse(tokens.[5]))})}
let rec loadFromLineReader (reader:StringReader) listOfThings parseLineFunc =
match reader.ReadLine() with
| null -> listOfThings
| line -> loadFromLineReader reader (parseLineFunc line::listOfThings) parseLineFunc
let loadFromLineString text listOfThings parseLineFunc =
let reader = new StringReader(text)
reader.ReadLine ()|> ignore // skip header
loadFromLineReader reader listOfThings parseLineFunc
let loadWebStringAsync url =
async {
let req = WebRequest.Create(url: string)
use! response = req.AsyncGetResponse()
use reader = new StreamReader(response.GetResponseStream())
return! reader.AsyncReadToEnd()}
let loadFromUrlAsync url parseFunc =
async {
let! text = loadWebStringAsync url
return loadFromLineString text [] parseFunc }
let loadPricesAsync aURL = loadFromUrlAsync aURL
let aSpan = span 2009 5 1 2009 5 15
//Ticker for AT&T is T
let ticker = "T"
let aURL = priceUrl ticker aSpan
let results = Async.Run(loadPricesAsync aURL parsePrice)
for aObs in results do
let aPrice aObs =
match aObs.Event with
| StkPrice(p) -> toFloat(p.Close)
| Dividend(d) -> toFloat(d)
| _ -> -999.0
printfn "Here's AT&T: %s %10.5f" (aObs.Date.ToShortDateString()) (aPrice(aObs))
()
let userresp = Console.ReadLine()
------------------------------------------------------------------------------
When I run it, here is what I get.
