If the previous example haven’t really impresses you yet, Luca gave us more serious example. This time we are going to retrieve and analyze stock informations.
The CSV data source will be obtained from Yahoo! Finance. To find out the URL to download, we need to:
- Visit Yahoo! Finance
- Enter the stock symbol in the search box, and press the “Get Quotes” button.
- On the new page, click Historical Prices menu on the left side of your screen.
- Scroll down, and obtain the CSV download URL.
Once you download and open it with text editor, you’ll see that the CSV data will looks something like this:
Date,Open,High,Low,Close,Volume,Adj Close 2012-09-07,31.04,31.07,30.73,30.95,42649100,30.95 2012-09-06,30.50,31.36,30.46,31.35,48371700,31.35 2012-09-05,30.22,30.53,30.21,30.39,33650000,30.39 2012-09-04,30.45,30.66,30.15,30.39,48556700,30.39
Now we will write the code to automatically retrieve and parse the CSV data:
open System.IO open System.Net let ticker = "msft" let url = "http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=8&e=10&f=2012&g=d&a=2&b=13&c=1986&ignore=.csv" let req = WebRequest.Create(url) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd() let prices = //split list of lines csv.Split([|'\n'|]) //Skip the first line |> Seq.skip 1 //For each line, split the line using the comma |> Seq.map (fun line -> line.Split([|','|])) //Now we have list that consists of list of String //We then filter it out, only selecting list that have 7 string values in it |> Seq.filter (fun values -> values |> Seq.length = 7) //Create a new tuple of (DateTime, Float) as the final result |> Seq.map (fun values -> System.DateTime.Parse(values.[0]), float values.[6])
To make above example reusable, we need to convert it into a function
let loadPrices ticker = let url = "http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=8&e=10&f=2012&g=d&a=2&b=13&c=1986&ignore=.csv" let req = WebRequest.Create(url) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd() let prices = csv.Split([|'\n'|]) |> Seq.skip 1 |> Seq.map (fun line -> line.Split([|','|])) |> Seq.filter (fun values -> values |> Seq.length = 7) |> Seq.map (fun values -> System.DateTime.Parse(values.[0]), float values.[6]) //return the list of tuples (DateTime, float) prices
Now we are going to create a class that analyze the output of loadPrices function.
type StockAnalyzer(lprices, days) = let prices = lprices //snd is a function that return the second element of a tuple |> Seq.map snd //return the first N element of the list |> Seq.take days //This is a factory method static member GetAnalyzers(tickers, days) = tickers |> Seq.map loadPrices |> Seq.map (fun prices -> new StockAnalyzer(prices, days)) member s.Return = let lastPrice = prices |> Seq.nth 0 let startPrice = prices |> Seq.nth (days-1) lastPrice/startPrice-1. //Calculate standard-deviation member s.StdDev = let logRets = prices |> Seq.pairwise |> Seq.map (fun (x,y) -> log (x/y)) let mean = logRets |> Seq.average let sqr x = x * x //calculate variance let var = logRets |> Seq.averageBy (fun r -> sqr(r-mean)) //return sqrt(variance) sqrt var
Now we can combine both into a proper API that can be used in other .NET languages. Note that I made some changes here because Luca’s code taken from the talk didn’t compile in Visual Studio 2012
namespace StockLibrary open System.IO open System.Net type internal StockLoader = static member loadPrices ticker = let url = "http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=8&e=10&f=2012&g=d&a=2&b=13&c=1986&ignore=.csv" let req = WebRequest.Create(url) let resp = req.GetResponse() let stream = resp.GetResponseStream() let reader = new StreamReader(stream) let csv = reader.ReadToEnd() let prices = csv.Split([|'\n'|]) |> Seq.skip 1 |> Seq.map (fun line -> line.Split([|','|])) |> Seq.filter (fun values -> values |> Seq.length = 7) |> Seq.map (fun values -> System.DateTime.Parse(values.[0]), float values.[6]) //return the list of tuples (DateTime, float) prices type StockAnalyzer(lprices, days) = let prices = lprices //snd is a function that return the second element of a tuple |> Seq.map snd //return the first N element of the list |> Seq.take days //This is a factory method static member GetAnalyzers(tickers, days) = tickers |> Seq.map StockLoader.loadPrices |> Seq.map (fun prices -> new StockAnalyzer(prices, days)) member s.Return = let lastPrice = prices |> Seq.nth 0 let startPrice = prices |> Seq.nth (days-1) lastPrice/startPrice-1. //Calculate standard-deviation member s.StdDev = let logRets = prices |> Seq.pairwise |> Seq.map (fun (x,y) -> log (x/y)) let mean = logRets |> Seq.average let sqr x = x * x //calculate variance let var = logRets |> Seq.averageBy (fun r -> sqr(r-mean)) //return sqrt(variance) sqrt var
loading...
About Hardono
Incoming Search
f#