2016-04-26 24 views
4

私は、同じ入力を使って計算したいたくさんの関数を持っています。私が下で選んだ方法よりも出力を見るための良い方法がありますか?同じパラメータを複数の関数に渡す方法は?

open MathNet.Numerics.Distributions 

// The functions 
let EuVanillaPut S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    let d2 = d1 - sqrt(T)*sigma 
    K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1) 

let BSMdelta S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    Normal.CDF(0.0,1.0,d1) 

let BSMgamma S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    Normal.PDF(0.0,1.0,d1)/(S0 * sigma * sqrt(T)) 

let BSMvega S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    Normal.PDF(0.0,1.0,d1) * S0 * sqrt(T) 

let BSMthetacall S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    let d2 = d1 - sqrt(T)*sigma 
    -S0 * Normal.PDF(0.0,1.0,d1) * sigma/(2.0*sqrt(T)) - r*K*exp(-r*T)*Normal.CDF(0.0,1.0,d2) 

let BSMthetaput S0 K T r sigma = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    let d2 = d1 - sqrt(T)*sigma 
    -S0 * Normal.PDF(0.0,1.0,d1) * sigma/(2.0*sqrt(T)) + r*K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) 

// Calling them all at once on the same inputs 
// So ugly! Is there a better way? 
(30.0, 25.0, 5.0, 0.02, 0.05) 
|> fun (S0, K, T, r, sigma) -> [EuVanillaPut S0 K T r sigma; 
           BSMdelta S0 K T r sigma; 
           BSMgamma S0 K T r sigma; 
           BSMvega S0 K T r sigma; 
           BSMthetacall S0 K T r sigma; 
           BSMthetaput S0 K T r sigma] 

私はこのタイプを作成する必要がありますか?関数の入力として別のデータ構造を使用すべきですか?すべてのポインタは大いに感謝しています。

+2

これはおそらくcodereview.seに適していますが、関数のリストを作成してList.mapを使用することもできます –

+1

また、5つの要素を持つタプルを扱う場合は、レコードタイプがおそらく全体的に読んで扱うのがよかった。 – TeaDrivenDev

+0

+1レコードの使用。後でリファクタリングが容易になります(たとえば、パラメータの追加など)。あなたは議論が混ざり合う機会を減らすこともできます。彼らはすべて現時点では浮動しています。 –

答えて

9

コメントで示唆したように、1つのオプション機能のリストを作成し、すべての機能を反復処理し、それらを呼び出すためにList.mapを使用することです:

let results = 
    [ EuVanillaPut; BSMdelta; BSMgamma ] 
    |> List.map (fun f -> f 30.0 25.0 5.0 0.02 0.05) 

私はあなたがしても抽出したいと思います仮定個々の結果は - (コンパイラは、リスト内の要素の数が正確であることを知ることができないので、しかし、あなたは警告が表示されます)それを行うために、あなたはパターンマッチングを使用することができます。

let [euVanillaPut; bsmdelta; bsmgamma] = results 

を警告を回避するには、あなたは書いてください:

match results with 
| [euVanillaPut; bsmdelta; bsmgamma] -> // all good 
| _ -> failwith "This should not happen..." 

また、あなたはタプル(またはレコード)を使用する関数定義を変更することができます:

let EuVanillaPut (S0, K, T, r, sigma) = 
    let d1 = (log(S0/K) + (r + sigma ** 2.0/2.0) * T)/(sqrt(T)*sigma) 
    let d2 = d1 - sqrt(T)*sigma 
    K*exp(-r*T)*Normal.CDF(0.0,1.0,-d2) - S0*Normal.CDF(0.0,1.0,-d1) 

その後、あなたはパラメータを保持し、複数の引数としてそれを使用する単一のタプルを定義することができます機能:

let ps = (30.0, 25.0, 5.0, 0.02, 0.05) 

let euVanillaPut = EuVanillaPut ps 
let bsmdelta = BSMdelta ps 
let bsmgamma = BSMgamma ps 

最初のアプローチは、巧妙なトリックですが、多くの場合、これをやっている場合は、リストから個々の結果を抽出することは少し醜いとなります。第2のアプローチは、同じグループのパラメータで多くの機能を使用する方が簡単であり、より意味があります。

関連する問題