Approximation der kum. Normalverteilung in Borland C++
-
Hallo,
ich bin zwar neu hier, aber dafür habe ich gleich mal eine knifflige Frage bei der ich alleine nicht mehr weiterkomme und hoffe dass hier jemand eine Antwort hat...
Also zum Problem:
Ich muß für meine Diplomarbeit ein Programm schreiben, dass u.a. in einer Subroutine mit den Werten der kum. (Standard-) Normalverteilung umgehen muß. Dazu habe ich eine Polynomial-Approximation in C++ implementiert, die soweit auch funktioniert, allerdings habe ich leider das Problem dass diese Approximation in einem bestimmten Bereich für meine Verhältnisse zu ungenau rechnet.
Scheinbar funktioniert die Approximation im Bereich von ~2 Standardabweichungen um den Erwartunsgwert recht genau (ewta auf fünf Stellen) rechnet, speziell aber am linken Ende der Verteilung (ab dem 5%-Quantil) sinkt die Genauigkeit auf zwei Stellen hinter dem Komma.
Nun meine Frage: kennt jemand eine alternative Approximation für die Verteilungsfunktion der Standardnormalverteilung? Ich habe mal etwas von einer sinus/ cosinus Methode gehört, konnte dazu aber bisher (auch über Google nichts) finden?
Danke & Gruß
mr_woo
-
Google mal nach (diskreter) Gaußapproximation.
Eine Möglichkeit wäre es auch z. B., die zu approximierenden Punkte mit Gewichten zu versehen.
Vielleicht könntest du ja mal genauere Informationen liefern: Welchen Grad haben die Polynome? Wieviele Punkte hast du zur Verfügung? Wie sieht deine Implementierung der Polynomapproximation aus? Usw.
-
Hallo,
danke erstmal für Deine Antwort. Werde gleich mal nach diskreter Gaußapproximation goglen, danke für den Tipp. Die Approximation die ich benutze arbeitet übrigens mit Polynomen 5. Grades, sollte eigentlich schon ganz gut sein, nur eben in dem beschriebenen Bereich nicht.
Ich glaube ich sollte mein Problem aber noch mal ein wenig genauer umschreiben: in meiner Diplomarbeit geht es um ein alternatives Optionspreismodell, desten Leistungsfähigkeit ich im Vergleich zum Standardoptionspreismodell beurteilen muß. Der Preis in dem Standardmodell ist eine Funktion aus mehreren Parametern, von denen 2 einer Standardnormalverteilung folgen. Bewertet man eine Option in diesem Modell "auf dem Papier", so berechnet man zunächst die zwei Parameter, die eine Wahrscheinlichkeit darstellen, und schlägt dann in einer tabellierten kummulierten Normalverteilungstabelle das dazu gehörige Quantil nach - und genau hier liegt mein Problem, denn die Approximation der zu einer bestimmten Wahrscheinlichkeit gehörenden Quantile ist ab dem 5%-Quantil abwärts zu ungenau.
Was meinst Du wie meine Implementierung aussieht, soll ich den Code posten?
Gruß mr_woo
-
Ich weiß nicht genau, ob ich das Problem richtig verstanden habe, aber suchst du eine Funktion, die diese Quantile möglichst genau approximiert? Sind diese Werte fest (d.h. eine Kurvenapproximation würde reichen) oder sind sie abhängig von irgendwelchen Parametern?
Wie hast du es denn bis jetzt gemacht, welche Punkte hast du durch das Polynom 5. Grades approximiert (und wie)? Und wie sieht die Funktion genau aus? Code wäre natürlich auch interessant, vielleicht liegt der Fehler da?
-
Hallo,
ja Du hast es richtig verstanden, ich berechne zunächst 2 Werte, die normalverteilt sind. Also stellen diese Werte (vereinfacht gesagt) Wahrscheinlichkeiten dar, und ich möchte zu diesen Wahrscheinlichkeiten das entsprechende Quantil (=also den kummulierten Wert der Dichtefunktion) der Standardnormalverteilung berechnen. Diese Routine ist allerdings nur ein Sub-Bestandteil einer Schleife, in der die Wahrscheinlichkeiten fortlaufend angepasst werden (es geht um ein Newton-Verfahren), möglicherweise (das habe ich bis jetzt noch gar nicht bedacht...) kummuliert sich also der Fehler.
Das Verfahren, dass ich zur Approximation der Quantile verwende, lautet wie folgt:
N(x) = 1-N´(x)*(a1*k+a2*k2+a3*k3+a4*k4+a5*k5 für alle x>0 und
1-N(-x) für alle x<0Die Parameter kappa, a1 bis a5 sind gegeben (kappa ist abhängig von x, a1-a5r sind Konstanten), N´(x) bedeutet die Ableitung der Dichtefunktion der Normalverteilung an der Stelle x. Den Code kann ich später posten, aber bitte nicht lachen denn ich bin C++ Anfänger und man kann das bestimmt auch viel besser & effizienter machen :D, aber dennoch glaube ich nicht dass der Fehler im Code liegt da ja im Bereich der mittleren Quantile die Ergebnisse sehr gut sind.
Gruß mr_woo
-
Hallo,
ich habe mal ein kleines Maple-Worksheet gesbastelt, um zu zeigen, wie man es z. B. machen könnte:
restart; with(LinearAlgebra): with(plots): randomize(); # Anzahl der Punkte N := 10; # zu approximierende Punkte x := ['i/10'$'i'=1..N]; y := ['0.1*i + cos(0.1*i) + 0.01*(rand() mod 100)'$'i'=1..N]; omega := [1$N]; # Gewichte # Anzahl der Ansatzfunktionen n := 3; # Ansatzfunktionen phi[1] := t -> cos(t); phi[2] := t -> sin(t); phi[3] := t -> t; # Skalarprodukt p := (phi, psi) -> sum('phi(x[i])*conjugate(psi(x[i]))*omega[i]', 'i'=1..N); q := (phi) -> sum('phi(x[i])*y[i]*omega[i]', 'i'=1..N); A := Matrix(n): b := Vector(n): for i from 1 to n do for j from 1 to n do A[i, j] := p(phi[i], phi[j]); od; b[i] := q(phi[i]); od: alpha := LinearSolve(A, b); g := t -> sum('alpha[i]*phi[i](t)', 'i'=1..n); P[1] := pointplot(['[x[i],y[i]]'$'i'=1..10]): P[2] := plot(g(t), t=0..1): display(P[1], P[2]);
Vielleicht hilft dir das?
-
@furbar
meine Güte Du bist ja krass und hast gleich den ganzen Code gepostet; also nur um das mal klarzustellen: ich bin nicht hier, damit mir jemand von euch den Code erstellt den ich brauche und ich nichts mehr machen muß... Vielen Dank natürlich trotzdem an Dich dass Du Dir die Mühe gemacht hast
Gib´ mir bitte noch einen Tag um das ganze zu checken. Sieht mir allerdings auf den ersten Blick aus wie eine sinus/ cosinus-Methode.
Gruß mr_woo
-
Keine Sorge, das ist nur ein (konstruiertes) Beispiel, wenn du das Ganze in C++ programmieren willst, bleibt dir noch viel Arbeit
Ist aber nicht die "sinus/cosinus-Methode" sondern diskrete Gaußapproximation, kannst du mit (nahezu) bel. Funktionen durchführen. Wollte dir aber btw. nicht den fertigen Code liefern, sondern nur zeigen, wie dieses Verfahren funktioniert ...