browse by category or date

By now our StockLibrary is functional. We can use it in C#, VB.NET or any other languages that Visual Studio supports. Unfortunately, it is now running in sequential and synchronous way. So if we use it to analyze multiple stock symbols it will be slow because GetAnalyzers will only create the StockAnalyzers sequentially. Another bottleneck is the WebRequest IO operation. Since it’s running synchronously, it will hog the thread while waiting for response from Yahoo’s server.

Now we know what to do:

  1. GetAnalyzers need to run in parallel.
  2. IO Processes need to run asynchronously.

In F# it is very easy to program in asynchronous. We only need to:

  1. Enclose the function with async { … } and use return at the end of the function
        //... SNIP ...
        static member loadPrices ticker = async {
        //... SNIP ...
        return prices }
        //... SNIP ...
    
  2. Add ‘bangs’/exclamation mark (!) after let and use the asynchronous version of the IO operation.
        //... SNIP ...
        let! resp = req.AsyncGetResponse()
        //... SNIP ...
        let! csv = reader.AsyncReadToEnd()
        //... SNIP ...
    

If you see how Luca is writing the code, he simply added ‘bangs’ and change the IO method into its Async version. But as I found out, we can’t do this anymore in Visual Studio 2012. In order to make the code complie, we need to do two things.

  1. Install F# Power Pack and add it into project’s References
  2. Import Microsoft.FSharp.Control.WebExtensions library.

Alright, back to the code. Since we have changed loadPrices into asynchronous, we also need to change the StockAnalyzer’s factory method to make it compile.

    //... SNIP ...
    static member GetAnalyzers(tickers, days) =
        tickers
        |> Seq.map StockLoader.loadPrices
        //Run every each loadPrices in Parallel
        |> Async.Parallel
        |> Async.RunSynchronously
        |> Seq.map (fun prices -> new StockAnalyzer(prices, days))
    //... SNIP ...

Putting everything into context:

namespace StockLibrary
open System.IO
open System.Net
open Microsoft.FSharp.Control.WebExtensions

type internal StockLoader =
    static member loadPrices ticker = async {
        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.AsyncGetResponse()
        let stream = resp.GetResponseStream()
        let reader = new StreamReader(stream)
        let! csv = reader.AsyncReadToEnd()
 
        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)
        return 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
        |> Async.Parallel
        |> Async.RunSynchronously
        |> 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

That’s it! We can now create an asynchronous and parallel program in F# with much clarity. I am now very excited to materialize this knowledge to solve problems. What do you think? Do you have any ideas that would be good to be implemented with F#?

GD Star Rating
loading...
Falling in Love to F#, 3.0 out of 5 based on 1 rating

Possibly relevant:

About Hardono

Howdy! I'm Hardono. I am working as a Software Developer. I am working mostly in Windows, dealing with .NET, conversing in C#. But I know a bit of Linux, mainly because I need to keep this blog operational. I've been working in Logistics/Transport industry for more than 11 years.

Incoming Search

f#

1 Trackback

 

No Comment

Add Your Comment