1
votes

I'm not an F# programmer. I'm modifying an existing library.

I'm trying and slowly picking it up.

What I'm trying to do is divide two functions.

I can see it done through the rest of the library so I know it's possible however when i try and divide i get the error

"Expecting a type supporting the operator '/' but given a function type. You may be missing an argument to a function"

This is where the errors occurring

let sharpeRatio2 pfRets bmkRets x  =
    let top pfRets bmkRets = excessReturns2 pfRets bmkRets
    let bottom pfRets x = volatilty pfRets false x
    let result = top / bottom
    result

The sub functions called i think are all good, with the only question mark on the volatility one which i created it should multiply the std result by sqrt(12)

Top (Returns)

let excessReturns2 (pfRets: seq<float>) bmkRets =
    Seq.zip pfRets bmkRets |> Seq.map activeReturn
    |> Seq.zip

let inline activeReturn (ret, bmkRet) = ret - bmkRet

Bottom (Volatility)

    let var xs nmethod = 
    match Seq.fold (fun (i, s, sumsq) x -> i + 1, s + x, sumsq + x * x) (0, 0., 0.) xs with
    | 0, _, _ -> 0.
    | 1, _, _ when not nmethod -> 0.
    | n, xsum, xsumsq ->
        // denominator is (n-1) or n
        let d = if nmethod then float n else float n - 1.
        (xsumsq - xsum * xsum / float n) / d

    let std xs nmethod = sqrt (var xs nmethod)

    let volatilty xs nmethod x = (std xs nmethod) * sqrt (x)

Any thoughts welcome please

Thanks gws

2
this is where the type inference makes it a bit difficult to see what's going on. Can you show the type signature of both the top and bottom functions? You can just copy it from the REPL if necessary. - s952163
My guess is that maybe you didn't supply all the arguments to your function so top or bottom is not a number (yet). - s952163
I'm sorry I'll have to work out what you mean. I believe TOP is seq<float>->seq<float>->seq<'d>->seq<float*'d> and bottom <seq<float> -> float -> float - Glenn Sampson
Yes, that's exactly what I mean, and you can see that you are trying to divide a list of numbers with one number. Which of course you cannot do. Please see my answer below. If you want a series of sharpe ratios for each day or month return you can use Seq.map. - s952163
You also mispelt "volatility" :-) - s952163

2 Answers

2
votes

When you write

let top pfRets bmkRets = excessReturns2 pfRets bmkRets

you are not calculating the value of top based on the passed-in variables pfRets2 and bmkRets. Instead, you are only defining a function, top, that happens to use the same names for its arguments as shapeRatio2 - but those arguments are left unspecified.

That is, both function take arguments called pfRets and bmkRets, but calling excessReturns2 does not automatically also call top with those same parameters; it only records its definition.

The same, obviously, applies to bottom.

Since you want top and bottom to be values, you need to define them without arguments (that's the simplest difference between values and functions: the latter take arguments, the former do not):

let sharpeRatio2 pfRets bmkRets x  =
    let top = excessReturns2 pfRets bmkRets
    let bottom = volatilty pfRets false x
    let result = top / bottom
    result
2
votes

This should work for you:

open System
let rnd = Random()
rnd.NextDouble()

let ret1 = List.init 100 (fun _ -> rnd.NextDouble() - 0.5)
let ret2 = List.init 100 (fun _ -> rnd.NextDouble() - 0.5)

let inline activeReturn (ret, bmkRet) = ret - bmkRet
let excessReturns2 (pfRets: seq<float>) bmkRets =
    Seq.zip pfRets bmkRets |> Seq.map activeReturn |> Seq.sum

let var xs nmethod = 
    match Seq.fold (fun (i, s, sumsq) x -> i + 1, s + x, sumsq + x * x) (0, 0., 0.) xs with
    | 0, _, _ -> 0.
    | 1, _, _ when not nmethod -> 0.
    | n, xsum, xsumsq ->
        // denominator is (n-1) or n
        let d = if nmethod then float n else float n - 1.
        (xsumsq - xsum * xsum / float n) / d

let std xs nmethod = sqrt (var xs nmethod)
let volatilty xs nmethod x = (std xs nmethod) * sqrt (x)


let sharpeRatio2 pfRets bmkRets x  =
    let top = excessReturns2 pfRets bmkRets
    let bottom  = volatilty pfRets false x
    let result = top / bottom
    result

sharpeRatio2 ret1 ret2 12.

Some comments:

  1. Try defining and posting the functions in order as the F# compiler goes left to right and top to bottom. So activeReturn has to come before excessreturn and the top and bottom functions before the sharperatio.

  2. There is an error in your excessReturns2 function, at the very end you have a Seq.zip you are piping into. I assume that is actually either a Seq.sum or Seq.average (you want the total active return for the period or an average daily/monthly active return). Either you want one number.

  3. This line (and also the next one): excessReturns2 pfRets bmkRets: here excessReturns2 is a function that takes two arguments the portfolio and the benchmark return. This function will return one number, which is top, so you can just say let top = excessReturns2 pfRets bmkRets, ditto for bottom.

  4. You are better off, using Mathdotnet, and calling the StandardDeviation functions from there. No need to define your own.

Let me know if you have any questions.

On Mathdotnet

This is a great library and if you can have a dependency on it you should be able to just say:

open MathNet.Numerics
open MathNet.Numerics.Statistics

Statistics.StandardDeviation ret1

You also use the portfolio return standard deviation when dividing the active return. You should ideally use the active return's standard deviation if you need to look at the Information Ratio.