18#include <rtl/math.hxx>
86static double sqr(
double x) {
92 return 0.39894228040143268*exp(-0.5*
x*
x);
96 return 0.5 * std::erfc(-
x * M_SQRT1_2);
102double bincash(
double S,
double vol,
double rd,
double rf,
103 double tau,
double K,
148 double d1 = (
log(
S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
149 double d2 = d1 - vol*sqrt(tau);
157 val = pm*
dnorm(d2)/(
S*vol*sqrt(tau));
163 val = rd*
pnorm(pm*d2)
164 + pm*
dnorm(d2)*(
log(
S/K)/(vol*sqrt(tau))-0.5*d2)/tau;
167 val = -pm*
dnorm(d2)*d1/vol;
170 val = pm*
dnorm(d2)/(vol*vol)*(-d1*d1*d2+d1+d2);
173 val = pm*
dnorm(d2)/(
S*vol*vol*sqrt(tau))*(d1*d2-1.0);
176 val = -tau*
pnorm(pm*d2) + pm*
dnorm(d2)*sqrt(tau)/vol;
179 val = -pm*
dnorm(d2)*sqrt(tau)/vol;
182 printf(
"bincash: greek %d not implemented\n", greeks );
186 return exp(-rd*tau)*val;
192double binasset(
double S,
double vol,
double rd,
double rf,
193 double tau,
double K,
247 double d1 = (
log(
S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
248 double d2 = d1 - vol*sqrt(tau);
256 val =
pnorm(pm*d1) + pm*
dnorm(d1)/(vol*sqrt(tau));
263 + pm*
S*
dnorm(d1)*(
log(
S/K)/(vol*sqrt(tau))-0.5*d1)/tau;
266 val = -pm*
S*
dnorm(d1)*d2/vol;
269 val = pm*
S*
dnorm(d1)/(vol*vol)*(-d1*d2*d2+d1+d2);
272 val = pm*
dnorm(d1)/(vol*vol*sqrt(tau))*(d2*d2-1.0);
275 val = pm*
S*
dnorm(d1)*sqrt(tau)/vol;
278 val = -tau*
S*
pnorm(pm*d1) - pm*
S*
dnorm(d1)*sqrt(tau)/vol;
281 printf(
"binasset: greek %d not implemented\n", greeks );
285 return exp(-rf*tau)*val;
292static double binary(
double S,
double vol,
double rd,
double rf,
293 double tau,
double K,
315static double binary(
double S,
double vol,
double rd,
double rf,
316 double tau,
double B1,
double B2,
324 if(B1<=0.0 && B2<=0.0) {
327 }
else if(B1<=0.0 && B2>0.0) {
330 }
else if(B1>0.0 && B2<=0.0) {
333 }
else if(B1>0.0 && B2>0.0) {
353double putcall(
double S,
double vol,
double rd,
double rf,
354 double tau,
double K,
365 if(K==0 || tau==0.0) {
374 double d1 = (
log(
S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
375 double d2 = d1 - vol*sqrt(tau);
379 val = pm * ( exp(-rf*tau)*
S*
pnorm(pm*d1)-exp(-rd*tau)*K*
pnorm(pm*d2) );
382 val = pm*exp(-rf*tau)*
pnorm(pm*d1);
385 val = exp(-rf*tau)*
dnorm(d1)/(
S*vol*sqrt(tau));
403 double tau,
double K,
double B,
450 double tau,
double K,
double B1,
double B2,
460 if(B1<=0.0 && B2<=0.0) {
463 }
else if(B1<=0.0 && B2>0.0) {
470 }
else if(B1>0.0 && B2<=0.0) {
477 }
else if(B1>0.0 && B2>0.0) {
502static double vanilla(
double S,
double vol,
double rd,
double rf,
503 double tau,
double K,
double B1,
double B2,
509 val =
binary(
S,vol,rd,rf,tau,B1,B2,fd,greek);
516 double tau,
double K,
double B1,
double B2,
523 val =
binary(
S,vol,rd,rf,tau,B1,B2,fd,greek);
546 double tau,
double K,
double B1,
double B2,
double sc,
556 double B = (B1>0.0) ? B1 : B2;
557 double a = 2.0*(rd-rf)/(vol*vol)-1.0;
558 double b = 4.0*(rd-rf)/(vol*vol*vol);
559 double c = 12.0*(rd-rf)/(vol*vol*vol*vol);
562 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
564 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
567 val =
sc*
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
570 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
572 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
576 val =
sc*
sc*
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
579 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
581 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Delta)
583 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Gamma)
587 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
589 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
592 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
595 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
597 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
601 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
604 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
606 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Vega)
608 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Volga)
612 val =
sc*
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
615 vanilla_trunc(
B*
B/
S*
sc,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
617 vanilla_trunc(
B*
B/
S*
sc,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Delta)
619 vanilla_trunc(
B*
B/
S*
sc,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Vega)
621 vanilla_trunc(
B*
B/
S*
sc,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Vanna)
625 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
627 2.0*
log(
B/
S)/(vol*vol)*
628 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
630 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
634 val =
vanilla_trunc(
sc*
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
636 - 2.0*
log(
B/
S)/(vol*vol)*
637 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,
types::Value)
639 vanilla_trunc(
sc*
B*
B/
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
643 printf(
"barrier_term: greek %d not implemented\n", greek );
651 double tau,
double K,
double B1,
double B2,
652 double fac,
double sc,
int i,
656 double b = 4.0*
i*(rd-rf)/(vol*vol*vol);
657 double c = 12.0*
i*(rd-rf)/(vol*vol*vol*vol);
660 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek);
663 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek);
666 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek);
669 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek);
672 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek)
674 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Value);
677 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek)
679 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Vega)
681 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Value);
684 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek)
686 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Delta);
689 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek)
690 + 2.0*
i/(vol*vol)*
log(B2/B1)*
fac *
691 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Value);
694 val =
fac*
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,greek)
695 - 2.0*
i/(vol*vol)*
log(B2/B1)*
fac *
696 barrier_term(
S,vol,rd,rf,tau,K,B1,B2,
sc,
pc,fd,
types::Value);
699 printf(
"barrier_double_term: greek %d not implemented\n", greek );
708static double barrier_ko(
double S,
double vol,
double rd,
double rf,
709 double tau,
double K,
double B1,
double B2,
719 if(B1<=0.0 && B2<=0.0) {
721 val =
vanilla(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
722 }
else if(B1>0.0 && B2<=0.0) {
727 val =
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,1.0,
pc,fd,greek);
729 }
else if(B1<=0.0 && B2>0.0) {
734 val =
barrier_term(
S,vol,rd,rf,tau,K,B1,B2,1.0,
pc,fd,greek);
736 }
else if(B1>0.0 && B2>0.0) {
744 double a = 2.0*(rd-rf)/(vol*vol)-1.0;
745 double BB2=
sqr(B2/B1);
746 double BBa=pow(B2/B1,
a);
747 double BB2inv=1.0/BB2;
748 double BBainv=1.0/BBa;
755 val=
barrier_double_term(
S,vol,rd,rf,tau,K,B1,B2,
fac,
sc,0,
pc,fd,greek);
757 for(
int i=1;
i<10;
i++) {
763 barrier_double_term(
S,vol,rd,rf,tau,K,B1,B2,
fac,
sc,
i,
pc,fd,greek) +
764 barrier_double_term(
S,vol,rd,rf,tau,K,B1,B2,facinv,scinv,-
i,
pc,fd,greek);
767 if(fabs(add) <= 1e-12*fabs(val)) {
783static double barrier_ki(
double S,
double vol,
double rd,
double rf,
784 double tau,
double K,
double B1,
double B2,
787 return vanilla(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
788 -
barrier_ko(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
792static double barrier(
double S,
double vol,
double rd,
double rf,
793 double tau,
double K,
double B1,
double B2,
801 val =
vanilla_trunc(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
804 val =
barrier_ko(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
807 val =
vanilla(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek)
808 -
vanilla_trunc(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
811 val =
barrier_ki(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
823double touch(
double S,
double vol,
double rd,
double rf,
833 val =
internal::vanilla_trunc(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
836 val =
internal::barrier_ko(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
839 val =
internal::vanilla(
S,vol,rd,rf,tau,K,-1.0,-1.0,
pc,fd,greek)
840 -
internal::vanilla_trunc(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
843 val =
internal::vanilla(
S,vol,rd,rf,tau,K,-1.0,-1.0,
pc,fd,greek)
844 -
internal::barrier_ko(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,greek);
853double barrier(
double S,
double vol,
double rd,
double rf,
854 double tau,
double K,
double B1,
double B2,
864 double val=
internal::barrier(
S,vol,rd,rf,tau,K,B1,B2,
pc,fd,kio,bcont,greek);
869 val += rebate*
touch(
S,vol,rd,rf,tau,B1,B2,fd,kio2,bcont,greek);
879 double tau,
double B1,
double B2) {
891 double tau,
double B1,
double B2) {
896 if( B1<B2 || B1<=0.0 || B2<=0.0 ) {
902 double tau,
double K,
double B1,
double B2,
916 if( (B1>B2 && B1>0.0 && B2>0.0) ||
927 BM2= (B2>0.0) ? std::min(B2,K) : K;
static double barrier_ko(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double barrier_double_term(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, double fac, double sc, int i, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double barrier(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, types::PutCall pc, types::ForDom fd, types::BarrierKIO kio, types::BarrierActive bcont, types::Greeks greek)
static double vanilla(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double vanilla_trunc(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double barrier_ki(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double barrier_term(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, double sc, types::PutCall pc, types::ForDom fd, types::Greeks greek)
static double sqr(double x)
static double binary(double S, double vol, double rd, double rf, double tau, double K, types::PutCall pc, types::ForDom fd, types::Greeks greek)
double touch(double S, double vol, double rd, double rf, double tau, double B1, double B2, types::ForDom fd, types::BarrierKIO kio, types::BarrierActive bcont, types::Greeks greek)
double putcalltrunc(double S, double vol, double rd, double rf, double tau, double K, double B, types::PutCall pc, types::KOType kotype, types::Greeks greeks)
static double pnorm(double x)
double prob_in_money(double S, double vol, double mu, double tau, double B1, double B2)
double binasset(double S, double vol, double rd, double rf, double tau, double K, types::PutCall pc, types::Greeks greeks)
double barrier(double S, double vol, double rd, double rf, double tau, double K, double B1, double B2, double rebate, types::PutCall pc, types::BarrierKIO kio, types::BarrierActive bcont, types::Greeks greek)
double putcall(double S, double vol, double rd, double rf, double tau, double K, types::PutCall putcall, types::Greeks greeks)
static double dnorm(double x)
double prob_hit(double S, double vol, double mu, double tau, double B1, double B2)
double bincash(double S, double vol, double rd, double rf, double tau, double K, types::PutCall pc, types::Greeks greeks)