On moodle, there is a set of investment lecture notes called "Finance Review". Please review the Lecture-08-APT.pdf document, including the appendix.
In particular,
- What do we mean by a factor?
- The example showing how to hedge Barrick with GLD and SPY.
- Information ratios.
Imagine you have the below returns for IBM and SPY. IBM's factor beta on SPY and the (constant) risk-free rate are given below too.
type ReturnOb = { Time: int; Return : float }
let ibm =
[|
{ Time = 0; Return = 0.15 }
{ Time = 1; Return = 0.05 }
{ Time = 2; Return = 0.01 }
|]
let spy =
[|
{ Time = 0; Return = 0.1 }
{ Time = 1; Return = 0.05 }
{ Time = 2; Return = -0.02 }
|]
let riskFreeRate = 0.001
let ibmBetaOnSpy = 1.2
Question 1
What are the weights on the risk-free asset and SPY in the portfolio that hedges IBM's exposure to SPY?
- Report the weight on the risk-free asset as a value named
wRf
of typefloat
. - Report the weight on the SPY portfolio as a value named
wSpy
of typefloat
.
answerlet wSpy = ibmBetaOnSpy
let wRf = 1.0-wSpy
val wSpy: float = 1.2
val wRf: float = -0.2
Question 2
What are the returns for Times [0;1;2] on the portfolio that hedges IBM's factor exposure to SPY?
- Report results as a value named
hedgePortReturns
of typeReturnOb array
.
answerlet hedgePortReturns =
spy
|> Array.map(fun spy ->
{ Time = spy.Time
Return = wSpy*spy.Return + wRf*riskFreeRate })
val hedgePortReturns: ReturnOb array =
[|{ Time = 0
Return = 0.1198 }; { Time = 1
Return = 0.0598 }; { Time = 2
Return = -0.0242 }|]
Question 3
Call the portfolio that hedges IBM's factor exposure to SPY the hedge portfolio. What is the hedge portfolio's factor beta on SPY?
- Report the answer as a value named
hedgePortBetaOnSpy
of type float.
answer// 3. Hedge portfolio's factor beta on SPY
// See the lecture notes for a fuller explanation:
//
// From the portfolio return equation, the
// hedge portfolio return is
// r_hedgePort = wRf * rf + wSpy * Spy
// =>
// r_hedgePort - rf = (wSpy + wRf - 1) * rf + wSpy*(Spy -rf)
// r_hedgePort - rf = wSpy*(Spy - rf)
// So the beta is
let hedgePortBetaOnSpy = ibmBetaOnSpy
val hedgePortBetaOnSpy: float = 1.2
Question 4
What are the returns for Times [0;1;2] on the portfolio that is long IBM and short the portfolio that hedges IBM's factor exposre to SPY?
- Report results as a value named
longShortPortReturns
of typeReturnOb array
.
answerlet hedgePortMap =
// using map because it's efficient for lookups.
// you could use filter with such a small collection,
// but we'll use a Map collection so that we
// practice like it's the real thing.
hedgePortReturns
|> Array.map(fun x -> x.Time, x)
|> Map.ofArray
let longShortPortReturns =
ibm
|> Array.choose(fun ibmOb ->
// We're using Array.choose instead of Array.map
// because we plan to return Some hedgeOb or None, and we
// want to throw away all the None cases and return just
// an array of the valid hedgeObs.
let matchingHedgeReturn = Map.tryFind ibmOb.Time hedgePortMap
// in this example matchingHedgeReturn will always be Some hedgeOb.
// But, we're using Map.tryFind and dealing with the possibility
// that None could happen because it's good to practice
// as if this were real code where bad things could happen.
match matchingHedgeReturn with
| None -> None // if there's no hedge return for ibmOb.Time return None
| Some hedgeOb ->
// if there is a matching hedge return for ibmOb.Time return Some ReturnOb
let longShort = ibmOb.Return - hedgeOb.Return
Some { Time = ibmOb.Time; Return = longShort })
val hedgePortMap: Map<int,ReturnOb> =
map
[(0, { Time = 0
Return = 0.1198 }); (1, { Time = 1
Return = 0.0598 });
(2, { Time = 2
Return = -0.0242 })]
val longShortPortReturns: ReturnOb array =
[|{ Time = 0
Return = 0.0302 }; { Time = 1
Return = -0.0098 }; { Time = 2
Return = 0.0342 }|]
Question 5
What is the alpha of IBM from the perspective of a factor model that uses SPY as the only risk factor?
- Report the result as a value named
alpha
of type float.
answerlet alpha =
longShortPortReturns
|> Array.averageBy(fun x -> x.Return)
val alpha: float = 0.0182
Question 6
What is the information ratio of IBM from the perspective of a factor model that uses SPY as the only risk factor?
- Report the result as a value named
io
of type float.
answer#r "nuget: FSharp.Stats, 0.5.0"
open FSharp.Stats
let sdHedgeReturns =
longShortPortReturns
|> Array.map(fun x -> x.Return )
|> Seq.stDev
// Intuitively, you can think of it similar
// to the sharpe ratio of the portfolio after
// hedging out the factor risk.
let io = alpha / sdHedgeReturns
[Loading C:\Users\runneradmin\.packagemanagement\nuget\Cache\ec63001b4149383af67dc5083312da4ecf34b844b655d861ca5bad281c016ede.fsx]
module FSI_0035.
Ec63001b4149383af67dc5083312da4ecf34b844b655d861ca5bad281c016ede
val sdHedgeReturns: float = 0.02433105012
val io: float = 0.7480153922
val int: value: 'T -> int (requires member op_Explicit)
--------------------
type int = int32
--------------------
type int<'Measure> = int
val float: value: 'T -> float (requires member op_Explicit)
--------------------
type float = System.Double
--------------------
type float<'Measure> = float
module Map from Microsoft.FSharp.Collections
--------------------
type Map<'Key,'Value (requires comparison)> = interface IReadOnlyDictionary<'Key,'Value> interface IReadOnlyCollection<KeyValuePair<'Key,'Value>> interface IEnumerable interface IStructuralEquatable interface IComparable interface IEnumerable<KeyValuePair<'Key,'Value>> interface ICollection<KeyValuePair<'Key,'Value>> interface IDictionary<'Key,'Value> new: elements: ('Key * 'Value) seq -> Map<'Key,'Value> member Add: key: 'Key * value: 'Value -> Map<'Key,'Value> ...
--------------------
new: elements: ('Key * 'Value) seq -> Map<'Key,'Value>
namespace FSharp
--------------------
namespace Microsoft.FSharp
module Array from FSharp.Stats
<summary> Module to compute common statistical measure on array </summary>
--------------------
module Array from Microsoft.FSharp.Collections
--------------------
type Array = new: unit -> Array static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float array static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float array
--------------------
new: unit -> Array
module Seq from FSharp.Stats
<summary> Module to compute common statistical measure </summary>
--------------------
module Seq from Microsoft.FSharp.Collections
--------------------
type Seq = new: unit -> Seq static member geomspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float seq static member linspace: start: float * stop: float * num: int * ?IncludeEndpoint: bool -> float seq
--------------------
new: unit -> Seq
<summary> Computes the sample standard deviation </summary>
<param name="items">The input sequence.</param>
<remarks>Returns NaN if data is empty or if any entry is NaN.</remarks>
<returns>standard deviation of a sample (Bessel's correction by N-1)</returns>