Skip to content

Instantly share code, notes, and snippets.

@cbilson
Created December 27, 2008 23:10
Show Gist options
  • Save cbilson/40330 to your computer and use it in GitHub Desktop.
Save cbilson/40330 to your computer and use it in GitHub Desktop.
#light
type Currency = { Code : string; Name : string; }
type Money = { Amount : float; Currency : Currency }
type Asset =
| Equity of string * Money
| FixedIncome of string * Money
| Cash of Money
| Future of string * Money
| Portfolio of string * Asset list
let usd = { Code = "usd"; Name = "US Dollars" }
let gbp = { Code = "gbp"; Name = "British Pounds" }
let eur = { Code = "eur"; Name = "Euros" }
let cad = { Code = "cad"; Name = "Canadian Dollars" }
let jpy = { Code = "jpy"; Name = "Japenese Yen" }
let chf = { Code = "chf"; Name = "Swiss Francs" }
let cny = { Code = "cny"; Name = "Chinese Renminbi" }
let sgd = { Code = "sgd"; Name = "Singapore Dollars" }
let krw = { Code = "krw"; Name = "Korean Won" }
let egp = { Code = "egp"; Name = "Egyptian Pound" }
let currencies = [usd; gbp; eur; cad; jpy; chf; cny; sgd; krw; egp];
let portfolio =
Portfolio("ABC Corp Reirement Plan",
[
Portfolio("US Large Cap Equity Fund",
[
Equity("IBM", { Amount = 5000.0; Currency = usd });
Equity("Microsoft", { Amount = 2000.0; Currency = usd });
Equity("Northern Telecom", { Amount = 2000.0; Currency = cad });
]);
Portfolio("Global Bond Fund",
[
FixedIncome("Lehman Brothers 5y 6.0%", { Amount = 0.05; Currency = usd });
FixedIncome("Fed Farm Credit Bank 15y 5.9%", { Amount = 3400.00; Currency = usd });
FixedIncome("Buoni del Tesoro Poliennali 10y 5.25%", { Amount = 6200.00; Currency = eur });
]);
Portfolio("Eurozone Equity Fund",
[
Equity("Virgin", { Amount = 5000.0; Currency = gbp });
Equity("France Telecom", { Amount = 2000.0; Currency = eur });
Equity("Total S.A.", { Amount = 6000.0; Currency = eur });
]);
Portfolio("Japanese Equity Fund",
[
Equity("Asahi", { Amount = 600000.0; Currency = jpy });
Equity("Fujifilm", { Amount = 400000.0; Currency = jpy });
Equity("Chiba Bank", { Amount = 500000.0; Currency = jpy });
]);
Portfolio("Emerging Markets Equity Fund",
[
Equity("Samsung", { Amount = 8000000.0; Currency = krw });
Equity("Industrial & Commercial Bank of China", { Amount = 50000.0; Currency = cny });
Equity("Upper Egypt Contracting", { Amount = 8000.00; Currency = egp });
]);
])
let rawRates =
[|
(* usd gbp eur cad jpy chf cny sgd krw egp *)
(* usd *) 1.0000; 0.6803; 0.7111; 1.2207; 90.650; 1.0700; 6.8409; 1.4494; 1298.9; 5.5250;
(* gbp *) 1.4700; 1.0000; 1.0454; 1.7944; 133.26; 1.5729; 10.056; 2.1306; 1909.3; 8.1110;
(* eur *) 1.4062; 0.9566; 1.0000; 1.7166; 127.47; 1.5046; 9.6197; 2.0382; 1826.5; 7.7720;
(* cad *) 0.8192; 0.5573; 0.5826; 1.0000; 74.261; 0.8765; 5.6041; 1.1874; 1064.0; 4.5210;
(* jpy *) 0.0110; 0.0075; 0.0078; 0.0135; 1.0000; 0.0118; 0.0755; 0.0160; 14.329; 0.0610;
(* chf *) 0.9346; 0.6358; 0.6646; 1.1408; 84.720; 1.0000; 6.3934; 1.3546; 1213.9; 5.1770;
(* cny *) 0.1462; 0.0994; 0.1040; 0.1784; 13.251; 0.1564; 1.0000; 0.2119; 189.87; 0.8080;
(* sgd *) 0.6899; 0.4693; 0.4906; 0.8422; 62.543; 0.7382; 4.7198; 1.0000; 896.16; 3.8140;
(* krw *) 0.0008; 0.0005; 0.0005; 0.0009; 0.0698; 0.0008; 0.0053; 0.0011; 1.0000; 0.0040;
(* egp *) 0.1810; 0.1230; 0.1290; 0.2210; 16.391; 0.1930; 1.2380; 0.2620; 235.09; 1.0000;
|]
let rateMatrix =
let l = List.length currencies
Array2.init l l <| fun x y -> Array.get rawRates (x + (y * l))
let mapOfMatrix (ordinals : 'a seq) (matrix : 'b [,]) : Map<('a * 'a), 'b> =
ordinals
|> Seq.mapi (fun i x -> ordinals |> Seq.mapi (fun j y -> [(y, x), matrix.[i, j]]))
|> Seq.concat
|> Seq.concat
|> Map.of_seq
let rateMap = mapOfMatrix currencies rateMatrix
let fxConvert b a = {Amount = rateMap.[a.Currency, b] * a.Amount; Currency = b}
let rec getCurrencyExposure ccy asset =
match asset with
| Cash(_) -> { Amount = 0.0; Currency = ccy }
| Future(_, _) -> { Amount = 0.0; Currency = ccy }
| Equity(_, value)
| FixedIncome(_, value) -> if ccy = value.Currency then { Amount = value.Amount; Currency = ccy }
else { Amount = 0.0; Currency = ccy }
| Portfolio(_, assets) -> let amount = assets
|> Seq.sum_by (fun x -> let exposure = getCurrencyExposure ccy x
exposure.Amount)
{ Amount = amount; Currency = ccy }
let exposureByCurrency portfolio =
currencies
|> List.map (fun ccy -> (ccy, getCurrencyExposure ccy portfolio |> fxConvert usd))
|> List.filter (fun x -> (snd x).Amount <> 0.0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment