summaryrefslogtreecommitdiff
path: root/scaddins
diff options
context:
space:
mode:
authortino <ttk448@gmail.com>2012-12-03 21:49:04 +0000
committerFridrich Strba <fridrich@documentfoundation.org>2012-12-04 12:23:42 +0000
commite9f31eaa49f9494113e72deaf0fe079701844ea4 (patch)
tree379588c7cfc12b666cc3a8103d39fb5d31961de8 /scaddins
parent4feaf5a8a05016e596f78244b2e0b69e35205de9 (diff)
adding calc add-in for option pricing
Change-Id: Ica4b621a7ae7e5ab447192ae3fe7b8911295bef2 Reviewed-on: https://gerrit.libreoffice.org/1232 Reviewed-by: Fridrich Strba <fridrich@documentfoundation.org> Tested-by: Fridrich Strba <fridrich@documentfoundation.org>
Diffstat (limited to 'scaddins')
-rw-r--r--scaddins/AllLangResTarget_pricing.mk46
-rw-r--r--scaddins/InternalUnoApi_scaddins.mk2
-rw-r--r--scaddins/Library_pricing.mk56
-rw-r--r--scaddins/Module_scaddins.mk2
-rw-r--r--scaddins/idl/com/sun/star/sheet/addin/PricingFunctions.idl49
-rw-r--r--scaddins/idl/com/sun/star/sheet/addin/XPricingFunctions.idl80
-rw-r--r--scaddins/source/pricing/black_scholes.cxx960
-rw-r--r--scaddins/source/pricing/black_scholes.hxx153
-rw-r--r--scaddins/source/pricing/pricing.component26
-rw-r--r--scaddins/source/pricing/pricing.cxx739
-rw-r--r--scaddins/source/pricing/pricing.hrc54
-rw-r--r--scaddins/source/pricing/pricing.hxx418
-rw-r--r--scaddins/source/pricing/pricing.src436
13 files changed, 3021 insertions, 0 deletions
diff --git a/scaddins/AllLangResTarget_pricing.mk b/scaddins/AllLangResTarget_pricing.mk
new file mode 100644
index 000000000000..d2646ab739b1
--- /dev/null
+++ b/scaddins/AllLangResTarget_pricing.mk
@@ -0,0 +1,46 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+$(eval $(call gb_AllLangResTarget_AllLangResTarget,pricing))
+
+$(eval $(call gb_AllLangResTarget_add_srs,pricing,\
+ scaddins/pricing \
+))
+
+$(eval $(call gb_SrsTarget_SrsTarget,scaddins/pricing))
+
+$(eval $(call gb_SrsTarget_set_include,scaddins/pricing,\
+ $$(INCLUDE) \
+ -I$(SRCDIR)/scaddins/source/pricing \
+))
+
+$(eval $(call gb_SrsTarget_add_files,scaddins/pricing,\
+ scaddins/source/pricing/pricing.src \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/scaddins/InternalUnoApi_scaddins.mk b/scaddins/InternalUnoApi_scaddins.mk
index 6be02012c2b8..a347e8241b1b 100644
--- a/scaddins/InternalUnoApi_scaddins.mk
+++ b/scaddins/InternalUnoApi_scaddins.mk
@@ -45,9 +45,11 @@ $(eval $(call gb_InternalUnoApi_set_include,scaddins,\
$(eval $(call gb_InternalUnoApi_add_idlfiles,scaddins,scaddins/idl/com/sun/star/sheet/addin,\
Analysis \
DateFunctions \
+ PricingFunctions \
XAnalysis \
XCompatibilityNames \
XDateFunctions \
+ XPricingFunctions \
XMiscFunctions \
))
diff --git a/scaddins/Library_pricing.mk b/scaddins/Library_pricing.mk
new file mode 100644
index 000000000000..d8ef4bb55931
--- /dev/null
+++ b/scaddins/Library_pricing.mk
@@ -0,0 +1,56 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2011 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+$(eval $(call gb_Library_Library,pricing))
+
+$(eval $(call gb_Library_set_componentfile,pricing,scaddins/source/pricing/pricing))
+
+$(eval $(call gb_Library_use_internal_comprehensive_api,pricing,\
+ offapi \
+ scaddins \
+ udkapi \
+))
+
+$(eval $(call gb_Library_use_libraries,pricing,\
+ cppu \
+ cppuhelper \
+ sal \
+ tl \
+ $(gb_UWINAPI) \
+))
+
+$(eval $(call gb_Library_add_exception_objects,pricing,\
+ scaddins/source/pricing/pricing \
+ scaddins/source/pricing/black_scholes \
+))
+
+# Runtime dependency for unit-tests
+$(call gb_LinkTarget_get_target,$(call gb_Library_get_linktargetname,pricing)) :| \
+ $(call gb_AllLangResTarget_get_target,pricing)
+
+# vim: set noet sw=4 ts=4:
diff --git a/scaddins/Module_scaddins.mk b/scaddins/Module_scaddins.mk
index 2e0bb1969129..6558fafde01e 100644
--- a/scaddins/Module_scaddins.mk
+++ b/scaddins/Module_scaddins.mk
@@ -31,9 +31,11 @@ $(eval $(call gb_Module_Module,scaddins))
$(eval $(call gb_Module_add_targets,scaddins,\
AllLangResTarget_analysis \
AllLangResTarget_date \
+ AllLangResTarget_pricing \
InternalUnoApi_scaddins \
Library_analysis \
Library_date \
+ Library_pricing \
))
# vim: set noet sw=4 ts=4:
diff --git a/scaddins/idl/com/sun/star/sheet/addin/PricingFunctions.idl b/scaddins/idl/com/sun/star/sheet/addin/PricingFunctions.idl
new file mode 100644
index 000000000000..b002ee6ef0c9
--- /dev/null
+++ b/scaddins/idl/com/sun/star/sheet/addin/PricingFunctions.idl
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef com_sun_star_sheet_addin_PricingFunctions_idl
+#define com_sun_star_sheet_addin_PricingFunctions_idl
+
+#include <com/sun/star/sheet/addin/XPricingFunctions.idl>
+
+module com
+{
+module sun
+{
+module star
+{
+module sheet
+{
+module addin
+{
+ service PricingFunctions
+ {
+ // exported interfaces:
+ interface XPricingFunctions;
+
+ };
+};
+};
+};
+};
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/idl/com/sun/star/sheet/addin/XPricingFunctions.idl b/scaddins/idl/com/sun/star/sheet/addin/XPricingFunctions.idl
new file mode 100644
index 000000000000..495891a6dd93
--- /dev/null
+++ b/scaddins/idl/com/sun/star/sheet/addin/XPricingFunctions.idl
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef com_sun_star_sheet_addin_XPricingFunctions_idl
+#define com_sun_star_sheet_addin_XPricingFunctions_idl
+
+#include <com/sun/star/uno/XInterface.idl>
+#include <com/sun/star/beans/XPropertySet.idl>
+
+module com
+{
+module sun
+{
+module star
+{
+module sheet
+{
+module addin
+{
+ /**
+ * Interface with pricing functions.
+ */
+ interface XPricingFunctions : com::sun::star::uno::XInterface
+ {
+ /// opt_barrier()
+ double getOpt_barrier( [in] double spot, [in] double vol,
+ [in] double r, [in] double rf, [in] double T, [in] double strike,
+ [in] double barrier_low, [in] double barrier_up,
+ [in] double rebate,
+ [in] string put_call, [in] string in_out,
+ [in] string continuous, [in] any greek )
+ raises( com::sun::star::lang::IllegalArgumentException );
+
+ /// opt_touch()
+ double getOpt_touch( [in] double spot, [in] double vol,
+ [in] double r, [in] double rf, [in] double T,
+ [in] double barrier_low, [in] double barrier_up,
+ [in] string for_dom, [in] string in_out,
+ [in] string continuous, [in] any greek )
+ raises( com::sun::star::lang::IllegalArgumentException );
+
+ /// opt_prob_hit()
+ double getOpt_prob_hit( [in] double spot, [in] double vol,
+ [in] double mu, [in] double T,
+ [in] double barrier_low, [in] double barrier_up )
+ raises( com::sun::star::lang::IllegalArgumentException );
+
+ /// opt_prob_inmoney()
+ double getOpt_prob_inmoney( [in] double spot, [in] double vol,
+ [in] double mu, [in] double T,
+ [in] double barrier_low, [in] double barrier_up,
+ [in] any strike, [in] any put_call )
+ raises( com::sun::star::lang::IllegalArgumentException );
+
+ };
+};
+};
+};
+};
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/source/pricing/black_scholes.cxx b/scaddins/source/pricing/black_scholes.cxx
new file mode 100644
index 000000000000..f99906e03fdb
--- /dev/null
+++ b/scaddins/source/pricing/black_scholes.cxx
@@ -0,0 +1,960 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (C) 2012 Tino Kluge <tino.kluge@hrz.tu-chemnitz.de>
+ *
+ */
+
+#include <cstdio>
+#include <cstdlib>
+#include <cmath>
+#include <cassert>
+#include <algorithm>
+#include <rtl/math.hxx>
+#include "black_scholes.hxx"
+
+// options prices and greeks in the Black-Scholes model
+// also known as TV (theoretical value)
+//
+// the code is structured as follows:
+//
+// (1) basic assets
+// - cash-or-nothing option: bincash()
+// - asset-or-nothing option: binasset()
+//
+// (2) derived basic assets, can all be priced based on (1)
+// - vanilla put/call: putcall() = +/- ( binasset() - K*bincash() )
+// - truncated put/call (barriers active at maturity only)
+//
+// (3) write a wrapper function to include all vanilla pricers
+// - this is so we don't duplicate code when pricing barriers
+// as this is derived from vanillas
+//
+// (4) single barrier options (knock-out), priced based on truncated vanillas
+// - it follows from the reflection principle that the price W(S) of a
+// single barrier option is given by
+// W(S) = V(S) - (B/S)^a V(B^2/S), a = 2(rd-rf)/vol^2 - 1
+// where V(S) is the price of the corresponding truncated vanilla
+// option
+// - to reduce code duplication and in anticipation of double barrier
+// options we write the following function
+// barrier_term(S,c) = V(c*S) - (B/S)^a V(c*B^2/S)
+//
+// (5) double barrier options (knock-out)
+// - value is an infinite sum over option prices of the corresponding
+// truncated vanillas (truncated at both barriers):
+//
+// W(S)=sum (B2/B1)^(i*a) (V(S(B2/B1)^(2i)) - (B1/S)^a V(B1^2/S (B2/B1)^(2i))
+//
+// (6) write routines for put/call barriers and touch options which
+// mainly call the general double barrier pricer
+// the main routines are touch() and barrier()
+// both can price in/out barriers, double/single barriers as well as
+// vanillas
+//
+//
+// the framework allows any barriers to be priced as long as we define
+// the value/greek functions for the corresponding truncated vanilla
+// and wrap them into internal::vanilla() and internal::vanilla_trunc()
+//
+// disadvantage of that approach is that due to the rules of
+// differentiations the formulas for greeks become long and possible
+// simplifications in the formulas won't be made
+//
+// other code inefficiency due to multiplication with pm (+/- 1)
+// cvtsi2sd: int-->double, 6/3 cycles
+// mulsd: double-double multiplication, 5/1 cycles
+// with -O3, however, it compiles 2 versions with pm=1, and pm=-1
+// which are efficient
+// note this is tiny anyway as compared to exp/log (100 cycles),
+// pow (200 cycles), erf (70 cycles)
+//
+// this code is not tested for numerical instability, ie overruns,
+// underruns, accuracy, etc
+
+
+namespace sca {
+namespace pricing {
+
+namespace bs {
+
+
+// helper functions
+// ----------------
+inline double sqr(double x) {
+ return x*x;
+}
+// normal density (see also ScInterpreter::phi)
+inline double dnorm(double x) {
+ //return (1.0/sqrt(2.0*M_PI))*exp(-0.5*x*x); // windows may not have M_PI
+ return 0.39894228040143268*exp(-0.5*x*x);
+}
+// cumulative normal distribution (see also ScInterpreter::integralPhi)
+inline double pnorm(double x) {
+ //return 0.5*(erf(sqrt(0.5)*x)+1.0); // windows may not have erf
+ return 0.5 * ::rtl::math::erfc(-x * 0.7071067811865475);
+}
+
+
+
+// binary option cash (domestic)
+// call - pays 1 if S_T is above strike K
+// put - pays 1 if S_T is below strike K
+double bincash(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall pc, types::Greeks greeks) {
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+
+ double val=0.0;
+
+ if(tau<=0.0) {
+ // special case tau=0 (expiry)
+ switch(greeks) {
+ case types::Value:
+ if( (pc==types::Call && S>=K) || (pc==types::Put && S<=K) ) {
+ val = 1.0;
+ } else {
+ val = 0.0;
+ }
+ break;
+ default:
+ val = 0.0;
+ }
+ } else if(K==0.0) {
+ // special case with zero strike
+ if(pc==types::Put) {
+ // up-and-out (put) with K=0
+ val=0.0;
+ } else {
+ // down-and-out (call) with K=0 (zero coupon bond)
+ switch(greeks) {
+ case types::Value:
+ val = 1.0;
+ break;
+ case types::Theta:
+ val = rd;
+ break;
+ case types::Rho_d:
+ val = -tau;
+ break;
+ default:
+ val = 0.0;
+ }
+ }
+ } else {
+ // standard case with K>0, tau>0
+ double d1 = ( log(S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
+ double d2 = d1 - vol*sqrt(tau);
+ int pm = (pc==types::Call) ? 1 : -1;
+
+ switch(greeks) {
+ case types::Value:
+ val = pnorm(pm*d2);
+ break;
+ case types::Delta:
+ val = pm*dnorm(d2)/(S*vol*sqrt(tau));
+ break;
+ case types::Gamma:
+ val = -pm*dnorm(d2)*d1/(sqr(S*vol)*tau);
+ break;
+ case types::Theta:
+ val = rd*pnorm(pm*d2)
+ + pm*dnorm(d2)*(log(S/K)/(vol*sqrt(tau))-0.5*d2)/tau;
+ break;
+ case types::Vega:
+ val = -pm*dnorm(d2)*d1/vol;
+ break;
+ case types::Volga:
+ val = pm*dnorm(d2)/(vol*vol)*(-d1*d1*d2+d1+d2);
+ break;
+ case types::Vanna:
+ val = pm*dnorm(d2)/(S*vol*vol*sqrt(tau))*(d1*d2-1.0);
+ break;
+ case types::Rho_d:
+ val = -tau*pnorm(pm*d2) + pm*dnorm(d2)*sqrt(tau)/vol;
+ break;
+ case types::Rho_f:
+ val = -pm*dnorm(d2)*sqrt(tau)/vol;
+ break;
+ default:
+ printf("bincash: greek %ui not implemented\n", greeks );
+ abort();
+ }
+ }
+ return exp(-rd*tau)*val;
+}
+
+
+
+// binary option asset (foreign)
+// call - pays S_T if S_T is above strike K
+// put - pays S_T if S_T is below strike K
+double binasset(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall pc, types::Greeks greeks) {
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+
+ double val=0.0;
+ if(tau<=0.0) {
+ // special case tau=0 (expiry)
+ switch(greeks) {
+ case types::Value:
+ if( (pc==types::Call && S>=K) || (pc==types::Put && S<=K) ) {
+ val = S;
+ } else {
+ val = 0.0;
+ }
+ break;
+ case types::Delta:
+ if( (pc==types::Call && S>=K) || (pc==types::Put && S<=K) ) {
+ val = 1.0;
+ } else {
+ val = 0.0;
+ }
+ break;
+ default:
+ val = 0.0;
+ }
+ } else if(K==0.0) {
+ // special case with zero strike (forward with zero strike)
+ if(pc==types::Put) {
+ // up-and-out (put) with K=0
+ val = 0.0;
+ } else {
+ // down-and-out (call) with K=0 (type of forward)
+ switch(greeks) {
+ case types::Value:
+ val = S;
+ break;
+ case types::Delta:
+ val = 1.0;
+ break;
+ case types::Theta:
+ val = rf*S;
+ break;
+ case types::Rho_f:
+ val = -tau*S;
+ break;
+ default:
+ val = 0.0;
+ }
+ }
+ } else {
+ // normal case
+ double d1 = ( log(S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
+ double d2 = d1 - vol*sqrt(tau);
+ int pm = (pc==types::Call) ? 1 : -1;
+
+ switch(greeks) {
+ case types::Value:
+ val = S*pnorm(pm*d1);
+ break;
+ case types::Delta:
+ val = pnorm(pm*d1) + pm*dnorm(d1)/(vol*sqrt(tau));
+ break;
+ case types::Gamma:
+ val = -pm*dnorm(d1)*d2/(S*sqr(vol)*tau);
+ break;
+ case types::Theta:
+ val = rf*S*pnorm(pm*d1)
+ + pm*S*dnorm(d1)*(log(S/K)/(vol*sqrt(tau))-0.5*d1)/tau;
+ break;
+ case types::Vega:
+ val = -pm*S*dnorm(d1)*d2/vol;
+ break;
+ case types::Volga:
+ val = pm*S*dnorm(d1)/(vol*vol)*(-d1*d2*d2+d1+d2);
+ break;
+ case types::Vanna:
+ val = pm*dnorm(d1)/(vol*vol*sqrt(tau))*(d2*d2-1.0);
+ break;
+ case types::Rho_d:
+ val = pm*S*dnorm(d1)*sqrt(tau)/vol;
+ break;
+ case types::Rho_f:
+ val = -tau*S*pnorm(pm*d1) - pm*S*dnorm(d1)*sqrt(tau)/vol;
+ break;
+ default:
+ printf("binasset: greek %ui not implemented\n", greeks );
+ abort();
+ }
+ }
+ return exp(-rf*tau)*val;
+}
+
+// just for convenience we can combine bincash and binasset into
+// one function binary
+// using bincash() if fd==types::Domestic
+// using binasset() if fd==types::Foreign
+double binary(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall pc, types::ForDom fd,
+ types::Greeks greek) {
+ double val=0.0;
+ switch(fd) {
+ case types::Domestic:
+ val = bincash(S,vol,rd,rf,tau,K,pc,greek);
+ break;
+ case types::Foreign:
+ val = binasset(S,vol,rd,rf,tau,K,pc,greek);
+ break;
+ default:
+ // never get here
+ assert(false);
+ }
+ return val;
+}
+
+// further wrapper to combine single/double barrier binary options
+// into one function
+// B1<=0 - it is assumed lower barrier not set
+// B2<=0 - it is assumed upper barrier not set
+double binary(double S, double vol, double rd, double rf,
+ double tau, double B1, double B2,
+ types::ForDom fd, types::Greeks greek) {
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+
+ double val=0.0;
+
+ if(B1<=0.0 && B2<=0.0) {
+ // no barriers set, payoff 1.0 (domestic) or S_T (foreign)
+ val = binary(S,vol,rd,rf,tau,0.0,types::Call,fd,greek);
+ } else if(B1<=0.0 && B2>0.0) {
+ // upper barrier (put)
+ val = binary(S,vol,rd,rf,tau,B2,types::Put,fd,greek);
+ } else if(B1>0.0 && B2<=0.0) {
+ // lower barrier (call)
+ val = binary(S,vol,rd,rf,tau,B1,types::Call,fd,greek);
+ } else if(B1>0.0 && B2>0.0) {
+ // double barrier
+ if(B2<=B1) {
+ val = 0.0;
+ } else {
+ val = binary(S,vol,rd,rf,tau,B2,types::Put,fd,greek)
+ - binary(S,vol,rd,rf,tau,B1,types::Put,fd,greek);
+ }
+ } else {
+ // never get here
+ assert(false);
+ }
+
+ return val;
+}
+
+
+
+// vanilla put/call option
+// call pays (S_T-K)^+
+// put pays (K-S_T)^+
+// this is the same as: +/- (binasset - K*bincash)
+double putcall(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall putcall, types::Greeks greeks) {
+
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+
+ double val = 0.0;
+ int pm = (putcall==types::Call) ? 1 : -1;
+
+ if(K==0 || tau==0.0) {
+ // special cases, simply refer to binasset() and bincash()
+ val = pm * ( binasset(S,vol,rd,rf,tau,K,putcall,greeks)
+ - K*bincash(S,vol,rd,rf,tau,K,putcall,greeks) );
+ } else {
+ // general case
+ // we could just use pm*(binasset-K*bincash), however
+ // since the formula for delta and gamma simplify we write them
+ // down here
+ double d1 = ( log(S/K)+(rd-rf+0.5*vol*vol)*tau ) / (vol*sqrt(tau));
+ double d2 = d1 - vol*sqrt(tau);
+
+ switch(greeks) {
+ case types::Value:
+ val = pm * ( exp(-rf*tau)*S*pnorm(pm*d1)-exp(-rd*tau)*K*pnorm(pm*d2) );
+ break;
+ case types::Delta:
+ val = pm*exp(-rf*tau)*pnorm(pm*d1);
+ break;
+ case types::Gamma:
+ val = exp(-rf*tau)*dnorm(d1)/(S*vol*sqrt(tau));
+ break;
+ default:
+ // too lazy for the other greeks, so simply refer to binasset/bincash
+ val = pm * ( binasset(S,vol,rd,rf,tau,K,putcall,greeks)
+ - K*bincash(S,vol,rd,rf,tau,K,putcall,greeks) );
+ }
+ }
+ return val;
+}
+
+// truncated put/call option, single barrier
+// need to specify whether it's down-and-out or up-and-out
+// regular (keeps monotonicity): down-and-out for call, up-and-out for put
+// reverse (destroys monoton): up-and-out for call, down-and-out for put
+// call pays (S_T-K)^+
+// put pays (K-S_T)^+
+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) {
+
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+ assert(B>=0.0);
+
+ int pm = (pc==types::Call) ? 1 : -1;
+ double val = 0.0;
+
+ switch(kotype) {
+ case types::Regular:
+ if( (pc==types::Call && B<=K) || (pc==types::Put && B>=K) ) {
+ // option degenerates to standard plain vanilla call/put
+ val = putcall(S,vol,rd,rf,tau,K,pc,greeks);
+ } else {
+ // normal case with truncation
+ val = pm * ( binasset(S,vol,rd,rf,tau,B,pc,greeks)
+ - K*bincash(S,vol,rd,rf,tau,B,pc,greeks) );
+ }
+ break;
+ case types::Reverse:
+ if( (pc==types::Call && B<=K) || (pc==types::Put && B>=K) ) {
+ // option degenerates to zero payoff
+ val = 0.0;
+ } else {
+ // normal case with truncation
+ val = binasset(S,vol,rd,rf,tau,K,types::Call,greeks)
+ - binasset(S,vol,rd,rf,tau,B,types::Call,greeks)
+ - K * ( bincash(S,vol,rd,rf,tau,K,types::Call,greeks)
+ - bincash(S,vol,rd,rf,tau,B,types::Call,greeks) );
+ }
+ break;
+ default:
+ assert(false);
+ }
+ return val;
+}
+
+// wrapper function for put/call option which combines
+// double/single/no truncation barrier
+// B1<=0 - assume no lower barrier
+// B2<=0 - assume no upper barrier
+double putcalltrunc(double S, double vol, double rd, double rf,
+ double tau, double K, double B1, double B2,
+ types::PutCall pc, types::Greeks greek) {
+
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+
+ double val=0.0;
+
+ if(B1<=0.0 && B2<=0.0) {
+ // no barriers set, plain vanilla
+ val = putcall(S,vol,rd,rf,tau,K,pc,greek);
+ } else if(B1<=0.0 && B2>0.0) {
+ // upper barrier: reverse barrier for call, regular barrier for put
+ if(pc==types::Call) {
+ val = putcalltrunc(S,vol,rd,rf,tau,K,B2,pc,types::Reverse,greek);
+ } else {
+ val = putcalltrunc(S,vol,rd,rf,tau,K,B2,pc,types::Regular,greek);
+ }
+ } else if(B1>0.0 && B2<=0.0) {
+ // lower barrier: regular barrier for call, reverse barrier for put
+ if(pc==types::Call) {
+ val = putcalltrunc(S,vol,rd,rf,tau,K,B1,pc,types::Regular,greek);
+ } else {
+ val = putcalltrunc(S,vol,rd,rf,tau,K,B1,pc,types::Reverse,greek);
+ }
+ } else if(B1>0.0 && B2>0.0) {
+ // double barrier
+ if(B2<=B1) {
+ val = 0.0;
+ } else {
+ int pm = (pc==types::Call) ? 1 : -1;
+ val = pm * (
+ putcalltrunc(S,vol,rd,rf,tau,K,B1,pc,types::Regular,greek)
+ - putcalltrunc(S,vol,rd,rf,tau,K,B2,pc,types::Regular,greek)
+ );
+ }
+ } else {
+ // never get here
+ assert(false);
+ }
+ return val;
+}
+
+namespace internal {
+
+// wrapper function for all non-path dependent options
+// this is only an internal function, used to avoid code duplication when
+// going to path-dependent barrier options,
+// K<0 - assume binary option
+// K>=0 - assume put/call option
+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) {
+ double val = 0.0;
+ if(K<0.0) {
+ // binary option if K<0
+ val = binary(S,vol,rd,rf,tau,B1,B2,fd,greek);
+ } else {
+ val = putcall(S,vol,rd,rf,tau,K,pc,greek);
+ }
+ return val;
+}
+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) {
+ double val = 0.0;
+ if(K<0.0) {
+ // binary option if K<0
+ // truncated is actually the same as the vanilla binary
+ val = binary(S,vol,rd,rf,tau,B1,B2,fd,greek);
+ } else {
+ val = putcalltrunc(S,vol,rd,rf,tau,K,B1,B2,pc,greek);
+ }
+ return val;
+}
+
+} // namespace internal
+
+
+// ---------------------------------------------------------------------
+// path dependent options
+// ---------------------------------------------------------------------
+
+namespace internal {
+
+// helper term for any type of options with continuously monitored barriers,
+// internal, should not be called from outside
+// calculates value and greeks based on
+// V(S) = V1(sc*S) - (B/S)^a V1(sc*B^2/S)
+// (a=2 mu/vol^2, mu drift in logspace, ie. mu=(rd-rf-1/2vol^2))
+// with sc=1 and V1() being the price of the respective truncated
+// vanilla option, V() would be the price of the respective barrier
+// option if only one barrier is present
+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) {
+
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+
+ // V(S) = V1(sc*S) - (B/S)^a V1(sc*B^2/S)
+ double val = 0.0;
+ double B = (B1>0.0) ? B1 : B2;
+ double a = 2.0*(rd-rf)/(vol*vol)-1.0; // helper variable
+ double b = 4.0*(rd-rf)/(vol*vol*vol); // helper variable -da/dvol
+ double c = 12.0*(rd-rf)/(vol*vol*vol*vol); // helper -db/dvol
+ switch(greek) {
+ case types::Value:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ break;
+ case types::Delta:
+ val = sc*vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ + pow(B/S,a) * (
+ a/S*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + sqr(B/S)*sc*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ );
+ break;
+ case types::Gamma:
+ val = sc*sc*vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ a*(a+1.0)/(S*S)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + (2.0*a+2.0)*B*B/(S*S*S)*sc*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Delta)
+ + sqr(sqr(B/S))*sc*sc*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Gamma)
+ );
+ break;
+ case types::Theta:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ break;
+ case types::Vega:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ - b*log(B/S)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + 1.0*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ );
+ break;
+ case types::Volga:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ log(B/S)*(b*b*log(B/S)+c)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ - 2.0*b*log(B/S)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Vega)
+ + 1.0*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Volga)
+ );
+ break;
+ case types::Vanna:
+ val = sc*vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ b/S*(log(B/S)*a+1.0)*
+ vanilla_trunc(B*B/S*sc,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + b*log(B/S)*sqr(B/S)*sc*
+ vanilla_trunc(B*B/S*sc,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Delta)
+ - a/S*
+ vanilla_trunc(B*B/S*sc,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Vega)
+ - sqr(B/S)*sc*
+ vanilla_trunc(B*B/S*sc,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Vanna)
+ );
+ break;
+ case types::Rho_d:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ 2.0*log(B/S)/(vol*vol)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + 1.0*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ );
+ break;
+ case types::Rho_f:
+ val = vanilla_trunc(sc*S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - pow(B/S,a) * (
+ - 2.0*log(B/S)/(vol*vol)*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,types::Value)
+ + 1.0*
+ vanilla_trunc(sc*B*B/S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ );
+ break;
+ default:
+ printf("barrier_term: greek %ui not implemented\n", greek );
+ abort();
+ }
+ return val;
+}
+
+// one term of the infinite sum for the valuation of double barriers
+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) {
+
+ double val = 0.0;
+ double b = 4.0*i*(rd-rf)/(vol*vol*vol); // helper variable -da/dvol
+ double c = 12.0*i*(rd-rf)/(vol*vol*vol*vol); // helper -db/dvol
+ switch(greek) {
+ case types::Value:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek);
+ break;
+ case types::Delta:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek);
+ break;
+ case types::Gamma:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek);
+ break;
+ case types::Theta:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek);
+ break;
+ case types::Vega:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek)
+ - b*log(B2/B1)*fac *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Value);
+ break;
+ case types::Volga:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek)
+ - 2.0*b*log(B2/B1)*fac *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Vega)
+ + log(B2/B1)*fac*(c+b*b*log(B2/B1)) *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Value);
+ break;
+ case types::Vanna:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek)
+ - b*log(B2/B1)*fac *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Delta);
+ break;
+ case types::Rho_d:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek)
+ + 2.0*i/(vol*vol)*log(B2/B1)*fac *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Value);
+ break;
+ case types::Rho_f:
+ val = fac*barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,greek)
+ - 2.0*i/(vol*vol)*log(B2/B1)*fac *
+ barrier_term(S,vol,rd,rf,tau,K,B1,B2,sc,pc,fd,types::Value);
+ break;
+ default:
+ printf("barrier_double_term: greek %ui not implemented\n", greek );
+ abort();
+ }
+ return val;
+}
+
+// general pricer for any type of options with continuously monitored barriers
+// allows two, one or zero barriers, only knock-out style
+// payoff profiles allowed based on vanilla_trunc()
+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) {
+
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+
+ double val = 0.0;
+
+ if(B1<=0.0 && B2<=0.0) {
+ // no barriers --> vanilla case
+ val = vanilla(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if(B1>0.0 && B2<=0.0) {
+ // lower barrier
+ if(S<=B1) {
+ val = 0.0; // knocked out
+ } else {
+ val = barrier_term(S,vol,rd,rf,tau,K,B1,B2,1.0,pc,fd,greek);
+ }
+ } else if(B1<=0.0 && B2>0.0) {
+ // upper barrier
+ if(S>=B2) {
+ val = 0.0; // knocked out
+ } else {
+ val = barrier_term(S,vol,rd,rf,tau,K,B1,B2,1.0,pc,fd,greek);
+ }
+ } else if(B1>0.0 && B2>0.0) {
+ // double barrier
+ if(S<=B1 || S>=B2) {
+ val = 0.0; // knocked out (always true if wrong input B1>B2)
+ } else {
+ // more complex calculation as we have to evaluate an infinite
+ // sum
+ // to reduce very costly pow() calls we define some variables
+ double a = 2.0*(rd-rf)/(vol*vol)-1.0; // 2 (mu-1/2vol^2)/sigma^2
+ double BB2=sqr(B2/B1);
+ double BBa=pow(B2/B1,a);
+ double BB2inv=1.0/BB2;
+ double BBainv=1.0/BBa;
+ double fac=1.0;
+ double facinv=1.0;
+ double sc=1.0;
+ double scinv=1.0;
+
+ // initial term i=0
+ val=barrier_double_term(S,vol,rd,rf,tau,K,B1,B2,fac,sc,0,pc,fd,greek);
+ // infinite loop, 10 should be plenty, normal would be 2
+ for(int i=1; i<10; i++) {
+ fac*=BBa;
+ facinv*=BBainv;
+ sc*=BB2;
+ scinv*=BB2inv;
+ double add =
+ barrier_double_term(S,vol,rd,rf,tau,K,B1,B2,fac,sc,i,pc,fd,greek) +
+ barrier_double_term(S,vol,rd,rf,tau,K,B1,B2,facinv,scinv,-i,pc,fd,greek);
+ val += add;
+ //printf("%i: val=%e (add=%e)\n",i,val,add);
+ if(fabs(add) <= 1e-12*fabs(val)) {
+ break;
+ }
+ }
+ // not knocked-out double barrier end
+ }
+ // double barrier end
+ } else {
+ // no such barrier combination exists
+ assert(false);
+ }
+
+ return val;
+}
+
+// knock-in style barrier
+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) {
+ return vanilla(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ -barrier_ko(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+}
+
+// general barrier
+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) {
+
+ double val = 0.0;
+ if( kio==types::KnockOut && bcont==types::Maturity ) {
+ // truncated vanilla option
+ val = vanilla_trunc(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockOut && bcont==types::Continuous ) {
+ // standard knock-out barrier
+ val = barrier_ko(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockIn && bcont==types::Maturity ) {
+ // inverse truncated vanilla
+ val = vanilla(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek)
+ - vanilla_trunc(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockIn && bcont==types::Continuous ) {
+ // standard knock-in barrier
+ val = barrier_ki(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else {
+ // never get here
+ assert(false);
+ }
+ return val;
+}
+
+} // namespace internal
+
+
+
+
+// touch/no-touch options (cash/asset or nothing payoff profile)
+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 K=-1.0; // dummy
+ types::PutCall pc = types::Call; // dummy
+ double val = 0.0;
+ if( kio==types::KnockOut && bcont==types::Maturity ) {
+ // truncated vanilla option
+ val = internal::vanilla_trunc(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockOut && bcont==types::Continuous ) {
+ // standard knock-out barrier
+ val = internal::barrier_ko(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockIn && bcont==types::Maturity ) {
+ // inverse truncated vanilla
+ val = internal::vanilla(S,vol,rd,rf,tau,K,-1.0,-1.0,pc,fd,greek)
+ - internal::vanilla_trunc(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else if ( kio==types::KnockIn && bcont==types::Continuous ) {
+ // standard knock-in barrier
+ val = internal::vanilla(S,vol,rd,rf,tau,K,-1.0,-1.0,pc,fd,greek)
+ - internal::barrier_ko(S,vol,rd,rf,tau,K,B1,B2,pc,fd,greek);
+ } else {
+ // never get here
+ assert(false);
+ }
+ return val;
+}
+
+// barrier option (put/call payoff profile)
+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) {
+ assert(tau>=0.0);
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(K>=0.0);
+ types::ForDom fd = types::Domestic;
+ double val=internal::barrier(S,vol,rd,rf,tau,K,B1,B2,pc,fd,kio,bcont,greek);
+ if(rebate!=0.0) {
+ // opposite of barrier knock-in/out type
+ types::BarrierKIO kio2 = (kio==types::KnockIn) ? types::KnockOut
+ : types::KnockIn;
+ val += rebate*touch(S,vol,rd,rf,tau,B1,B2,fd,kio2,bcont,greek);
+ }
+ return val;
+}
+
+
+
+// probability of hitting a barrier
+// this is almost the same as the price of a touch option (domestic)
+// as it pays one if a barrier is hit; we only have to offset the
+// discounting and we get the probability
+double prob_hit(double S, double vol, double mu,
+ double tau, double B1, double B2) {
+ double rd=0.0;
+ double rf=-mu;
+ return 1.0 - touch(S,vol,rd,rf,tau,B1,B2,types::Domestic,types::KnockOut,
+ types::Continuous, types::Value);
+}
+
+// probability of being in-the-money, ie payoff is greater zero,
+// assuming payoff(S_T) > 0 iff S_T in [B1, B2]
+// this the same as the price of a cash or nothing option
+// with no discounting
+double prob_in_money(double S, double vol, double mu,
+ double tau, double B1, double B2) {
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(tau>=0.0);
+ double val = 0.0;
+ if( B1<B2 || B1<=0.0 || B2<=0.0 ) {
+ val = binary(S,vol,0.0,-mu,tau,B1,B2,types::Domestic,types::Value);
+ }
+ return val;
+}
+double prob_in_money(double S, double vol, double mu,
+ double tau, double K, double B1, double B2,
+ types::PutCall pc) {
+ assert(S>0.0);
+ assert(vol>0.0);
+ assert(tau>=0.0);
+
+ // if K<0 we assume a binary option is given
+ if(K<0.0) {
+ return prob_in_money(S,vol,mu,tau,B1,B2);
+ }
+
+ double val = 0.0;
+ double BM1, BM2; // range of in the money [BM1, BM2]
+ // non-sense parameters with no positive payoff
+ if( (B1>B2 && B1>0.0 && B2>0.0) ||
+ (K>=B2 && B2>0.0 && pc==types::Call) ||
+ (K<=B1 && pc==types::Put) ) {
+ val = 0.0;
+ // need to figure out between what barriers payoff is greater 0
+ } else if(pc==types::Call) {
+ BM1=std::max(B1, K);
+ BM2=B2;
+ val = prob_in_money(S,vol,mu,tau,BM1,BM2);
+ } else if (pc==types::Put) {
+ BM1=B1;
+ BM2= (B2>0.0) ? std::min(B2,K) : K;
+ val = prob_in_money(S,vol,mu,tau,BM1,BM2);
+ } else {
+ // don't get here
+ assert(false);
+ }
+ return val;
+}
+
+
+
+} // namespace bs
+
+} // namespace pricing
+} // namespace sca
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/source/pricing/black_scholes.hxx b/scaddins/source/pricing/black_scholes.hxx
new file mode 100644
index 000000000000..5e665c535471
--- /dev/null
+++ b/scaddins/source/pricing/black_scholes.hxx
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * Copyright (C) 2012 Tino Kluge <tino.kluge@hrz.tu-chemnitz.de>
+ *
+ */
+
+
+#ifndef BLACK_SCHOLES_HXX
+#define BLACK_SCHOLES_HXX
+
+// options prices and greeks in the Black-Scholes model
+// also known as TV (theoretical value)
+
+namespace sca {
+namespace pricing {
+
+namespace bs {
+
+namespace types {
+enum Greeks {
+ Value = 0, //
+ Delta = 1, // d/dS
+ Gamma = 2, // d^2/dS^2
+ Theta = 3, // d/dt
+ Vega = 4, // d/dsigma
+ Volga = 5, // d^2/dsigma^2
+ Vanna = 6, // d^2/dsigma dS
+ Rho_d = 7, // d/dr_d
+ Rho_f = 8 // d/dr_f
+};
+
+enum PutCall {
+ Call = 1,
+ Put = -1
+};
+
+enum KOType {
+ Regular = 0,
+ Reverse = 1
+};
+
+enum BarrierKIO {
+ KnockIn = -1,
+ KnockOut = 1
+};
+
+// barrier observed continuously or just at maturity (truncated payoff)
+enum BarrierActive {
+ Continuous = 0,
+ Maturity = 1
+};
+
+enum ForDom {
+ Domestic = 0,
+ Foreign = 1
+};
+
+} // namespace types
+
+
+// binary option cash (domestic)
+// call - pays 1 if S_T is above strike K
+// put - pays 1 if S_T is below strike K
+double bincash(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall pc, types::Greeks greeks);
+
+// binary option asset (foreign)
+// call - pays S_T if S_T is above strike K
+// put - pays S_T if S_T is below strike K
+double binasset(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall pc, types::Greeks greeks);
+
+
+
+// vanilla put/call option
+// call pays (S_T-K)^+
+// put pays (K-S_T)^+
+// this is the same as: +/- (binasset - K*bincash)
+double putcall(double S, double vol, double rd, double rf,
+ double tau, double K,
+ types::PutCall putcall, types::Greeks greeks);
+
+
+// truncated put/call option, single barrier
+// need to specify whether it's down-and-out or up-and-out
+// regular (keeps monotonicity): down-and-out for call, up-and-out for put
+// reverse (destroys monoton): up-and-out for call, down-and-out for put
+// call pays (S_T-K)^+
+// put pays (K-S_T)^+
+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);
+
+
+// wrapper function for put/call option which combines
+// double/single/no truncation barrier
+// B1<=0 - assume no lower barrier
+// B2<=0 - assume no upper barrier
+double putcalltrunc(double S, double vol, double rd, double rf,
+ double tau, double K, double B1, double B2,
+ types::PutCall pc, types::Greeks greek);
+
+
+
+// barrier
+// touch/no-touch options (cash/asset or nothing payoff profile)
+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);
+
+// barrier
+// barrier option (put/call payoff profile)
+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);
+
+
+// probability of hitting a barrier
+double prob_hit(double S, double vol, double mu,
+ double tau, double B1, double B2);
+
+
+// probability of being in-the-money, ie payoff is greater zero,
+// assuming payoff(S_T) > 0 iff S_T in [B1, B2]
+double prob_in_money(double S, double vol, double mu,
+ double tau, double B1, double B2);
+double prob_in_money(double S, double vol, double mu,
+ double tau, double K, double B1, double B2,
+ types::PutCall pc);
+
+
+} // namespace bs
+
+} // namespace pricing
+} // namespace sca
+
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/source/pricing/pricing.component b/scaddins/source/pricing/pricing.component
new file mode 100644
index 000000000000..d50ee37d7117
--- /dev/null
+++ b/scaddins/source/pricing/pricing.component
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ -->
+
+<component loader="com.sun.star.loader.SharedLibrary" prefix="pricing"
+ xmlns="http://openoffice.org/2010/uno-components">
+ <implementation name="com.sun.star.sheet.addin.PricingFunctionsImpl">
+ <service name="com.sun.star.sheet.AddIn"/>
+ <service name="com.sun.star.sheet.addin.PricingFunctions"/>
+ </implementation>
+</component>
diff --git a/scaddins/source/pricing/pricing.cxx b/scaddins/source/pricing/pricing.cxx
new file mode 100644
index 000000000000..ba4cb31a9e4d
--- /dev/null
+++ b/scaddins/source/pricing/pricing.cxx
@@ -0,0 +1,739 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+//------------------------------------------------------------------
+//
+// pricing functions add in
+//
+// all of the UNO add-in technical details have been copied from
+// ../datefunc/datefunc.cxx
+//
+//------------------------------------------------------------------
+
+#include "pricing.hxx"
+#include "black_scholes.hxx"
+#include "pricing.hrc"
+#include <cppuhelper/factory.hxx>
+#include <osl/diagnose.h>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/math.hxx>
+#include <tools/resmgr.hxx>
+#include <tools/rcid.h>
+
+#include <iostream>
+
+using namespace ::com::sun::star;
+using namespace sca::pricing;
+
+
+//------------------------------------------------------------------
+
+#define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
+#define MY_SERVICE "com.sun.star.sheet.addin.PricingFunctions"
+#define MY_IMPLNAME "com.sun.star.sheet.addin.PricingFunctionsImpl"
+
+//------------------------------------------------------------------
+
+#define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
+
+//------------------------------------------------------------------
+
+const sal_uInt32 ScaList::nStartSize = 16;
+const sal_uInt32 ScaList::nIncrSize = 16;
+
+ScaList::ScaList() :
+ pData( new void*[ nStartSize ] ),
+ nSize( nStartSize ),
+ nCount( 0 ),
+ nCurr( 0 )
+{
+}
+
+ScaList::~ScaList()
+{
+ delete[] pData;
+}
+
+void ScaList::_Grow()
+{
+ nSize += nIncrSize;
+
+ void** pNewData = new void*[ nSize ];
+ memcpy( pNewData, pData, nCount * sizeof( void* ) );
+
+ delete[] pData;
+ pData = pNewData;
+}
+
+//------------------------------------------------------------------
+
+ScaStringList::~ScaStringList()
+{
+ for( OUString* pStr = First(); pStr; pStr = Next() )
+ delete pStr;
+}
+
+//------------------------------------------------------------------
+
+ScaResId::ScaResId( sal_uInt16 nId, ResMgr& rResMgr ) :
+ ResId( nId, rResMgr )
+{
+}
+
+
+//------------------------------------------------------------------
+
+#define UNIQUE sal_False // function name does not exist in Calc
+#define DOUBLE sal_True // function name exists in Calc
+
+#define STDPAR sal_False // all parameters are described
+#define INTPAR sal_True // first parameter is internal
+
+#define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
+ { "get" #FuncName, PRICING_FUNCNAME_##FuncName, PRICING_FUNCDESC_##FuncName, PRICING_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
+
+const ScaFuncDataBase pFuncDataArr[] =
+{
+ FUNCDATA( Opt_barrier, 13, ScaCat_Finance, UNIQUE, STDPAR),
+ FUNCDATA( Opt_touch, 11, ScaCat_Finance, UNIQUE, STDPAR),
+ FUNCDATA( Opt_prob_hit, 6, ScaCat_Finance, UNIQUE, STDPAR),
+ FUNCDATA( Opt_prob_inmoney, 8, ScaCat_Finance, UNIQUE, STDPAR)
+};
+
+#undef FUNCDATA
+
+
+//------------------------------------------------------------------
+
+ScaFuncData::ScaFuncData( const ScaFuncDataBase& rBaseData, ResMgr& rResMgr ) :
+ aIntName( OUString::createFromAscii( rBaseData.pIntName ) ),
+ nUINameID( rBaseData.nUINameID ),
+ nDescrID( rBaseData.nDescrID ),
+ nCompListID( rBaseData.nCompListID ),
+ nParamCount( rBaseData.nParamCount ),
+ eCat( rBaseData.eCat ),
+ bDouble( rBaseData.bDouble ),
+ bWithOpt( rBaseData.bWithOpt )
+{
+ ScaResStringArrLoader aArrLoader( RID_PRICING_DEFFUNCTION_NAMES, nCompListID, rResMgr );
+ const ResStringArray& rArr = aArrLoader.GetStringArray();
+
+ for( sal_uInt16 nIndex = 0; nIndex < rArr.Count(); nIndex++ )
+ aCompList.Append( rArr.GetString( nIndex ) );
+}
+
+ScaFuncData::~ScaFuncData()
+{
+}
+
+sal_uInt16 ScaFuncData::GetStrIndex( sal_uInt16 nParam ) const
+{
+ if( !bWithOpt )
+ nParam++;
+ return (nParam > nParamCount) ? (nParamCount * 2) : (nParam * 2);
+}
+
+
+//------------------------------------------------------------------
+
+ScaFuncDataList::ScaFuncDataList( ResMgr& rResMgr ) :
+ nLast( 0xFFFFFFFF )
+{
+ for( sal_uInt16 nIndex = 0; nIndex < SAL_N_ELEMENTS(pFuncDataArr); nIndex++ )
+ Append( new ScaFuncData( pFuncDataArr[ nIndex ], rResMgr ) );
+}
+
+ScaFuncDataList::~ScaFuncDataList()
+{
+ for( ScaFuncData* pFData = First(); pFData; pFData = Next() )
+ delete pFData;
+}
+
+const ScaFuncData* ScaFuncDataList::Get( const OUString& rProgrammaticName ) const
+{
+ OUString aTestName;
+
+ if( aLastName == rProgrammaticName ){
+ return Get( nLast );
+ }
+
+ for( sal_uInt32 nIndex = 0; nIndex < Count(); nIndex++ )
+ {
+ const ScaFuncData* pCurr = Get( nIndex );
+ if( pCurr->Is( rProgrammaticName ) )
+ {
+ const_cast< ScaFuncDataList* >( this )->aLastName = rProgrammaticName;
+ const_cast< ScaFuncDataList* >( this )->nLast = nIndex;
+ return pCurr;
+ }
+ }
+ return NULL;
+}
+
+
+//------------------------------------------------------------------
+
+ScaFuncRes::ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, OUString& rRet ) :
+ Resource( rResId )
+{
+ rRet = String( ScaResId( nIndex, rResMgr ) );
+ FreeResource();
+}
+
+
+//------------------------------------------------------------------
+//
+// entry points for service registration / instantiation
+//
+//------------------------------------------------------------------
+
+uno::Reference< uno::XInterface > SAL_CALL ScaPricingAddIn_CreateInstance(
+ const uno::Reference< lang::XMultiServiceFactory >& )
+{
+ static uno::Reference< uno::XInterface > xInst = (cppu::OWeakObject*) new ScaPricingAddIn();
+ return xInst;
+}
+
+
+//------------------------------------------------------------------------
+
+extern "C" {
+
+SAL_DLLPUBLIC_EXPORT void * SAL_CALL pricing_component_getFactory(
+ const sal_Char * pImplName, void * pServiceManager, void * /*pRegistryKey*/ )
+{
+ void* pRet = 0;
+
+ if ( pServiceManager &&
+ OUString::createFromAscii( pImplName ) == ScaPricingAddIn::getImplementationName_Static() )
+ {
+ uno::Reference< lang::XSingleServiceFactory > xFactory( cppu::createOneInstanceFactory(
+ reinterpret_cast< lang::XMultiServiceFactory* >( pServiceManager ),
+ ScaPricingAddIn::getImplementationName_Static(),
+ ScaPricingAddIn_CreateInstance,
+ ScaPricingAddIn::getSupportedServiceNames_Static() ) );
+
+ if (xFactory.is())
+ {
+ xFactory->acquire();
+ pRet = xFactory.get();
+ }
+ }
+
+ return pRet;
+}
+
+} // extern C
+
+//------------------------------------------------------------------------
+//
+// "normal" service implementation
+//
+//------------------------------------------------------------------------
+
+ScaPricingAddIn::ScaPricingAddIn() :
+ pDefLocales( NULL ),
+ pResMgr( NULL ),
+ pFuncDataList( NULL )
+{
+}
+
+ScaPricingAddIn::~ScaPricingAddIn()
+{
+ if( pFuncDataList )
+ delete pFuncDataList;
+ if( pDefLocales )
+ delete[] pDefLocales;
+
+ // pResMgr already deleted (_all_ resource managers are deleted _before_ this dtor is called)
+}
+
+static const sal_Char* pLang[] = { "de", "en" };
+static const sal_Char* pCoun[] = { "DE", "US" };
+static const sal_uInt32 nNumOfLoc = SAL_N_ELEMENTS( pLang );
+
+void ScaPricingAddIn::InitDefLocales()
+{
+ pDefLocales = new lang::Locale[ nNumOfLoc ];
+
+ for( sal_uInt32 nIndex = 0; nIndex < nNumOfLoc; nIndex++ )
+ {
+ pDefLocales[ nIndex ].Language = OUString::createFromAscii( pLang[ nIndex ] );
+ pDefLocales[ nIndex ].Country = OUString::createFromAscii( pCoun[ nIndex ] );
+ }
+}
+
+const lang::Locale& ScaPricingAddIn::GetLocale( sal_uInt32 nIndex )
+{
+ if( !pDefLocales )
+ InitDefLocales();
+
+ return (nIndex < sizeof( pLang )) ? pDefLocales[ nIndex ] : aFuncLoc;
+}
+
+ResMgr& ScaPricingAddIn::GetResMgr() throw( uno::RuntimeException )
+{
+ if( !pResMgr )
+ {
+ InitData(); // try to get resource manager
+ if( !pResMgr )
+ throw uno::RuntimeException();
+ }
+ return *pResMgr;
+}
+
+void ScaPricingAddIn::InitData()
+{
+
+ if( pResMgr )
+ delete pResMgr;
+
+ OString aModName( "pricing" );
+ pResMgr = ResMgr::CreateResMgr( aModName.getStr(), aFuncLoc );
+
+ if( pFuncDataList )
+ delete pFuncDataList;
+
+ pFuncDataList = pResMgr ? new ScaFuncDataList( *pResMgr ) : NULL;
+
+ if( pDefLocales )
+ {
+ delete pDefLocales;
+ pDefLocales = NULL;
+ }
+}
+
+OUString ScaPricingAddIn::GetDisplFuncStr( sal_uInt16 nResId ) throw( uno::RuntimeException )
+{
+ return ScaResStringLoader( RID_PRICING_FUNCTION_NAMES, nResId, GetResMgr() ).GetString();
+}
+
+OUString ScaPricingAddIn::GetFuncDescrStr( sal_uInt16 nResId, sal_uInt16 nStrIndex ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ ScaResPublisher aResPubl( ScaResId( RID_PRICING_FUNCTION_DESCRIPTIONS, GetResMgr() ) );
+ ScaResId aResId( nResId, GetResMgr() );
+ aResId.SetRT( RSC_RESOURCE );
+
+ if( aResPubl.IsAvailableRes( aResId ) )
+ ScaFuncRes aSubRes( aResId, GetResMgr(), nStrIndex, aRet );
+
+ aResPubl.FreeResource();
+ return aRet;
+}
+
+
+//------------------------------------------------------------------------
+
+OUString ScaPricingAddIn::getImplementationName_Static()
+{
+ return OUString(RTL_CONSTASCII_USTRINGPARAM( MY_IMPLNAME ));
+}
+
+uno::Sequence< OUString > ScaPricingAddIn::getSupportedServiceNames_Static()
+{
+ uno::Sequence< OUString > aRet( 2 );
+ OUString* pArray = aRet.getArray();
+ pArray[0] = OUString(RTL_CONSTASCII_USTRINGPARAM( ADDIN_SERVICE ));
+ pArray[1] = OUString(RTL_CONSTASCII_USTRINGPARAM( MY_SERVICE ));
+ return aRet;
+}
+
+// XServiceName
+
+OUString SAL_CALL ScaPricingAddIn::getServiceName() throw( uno::RuntimeException )
+{
+ // name of specific AddIn service
+ return OUString(RTL_CONSTASCII_USTRINGPARAM( MY_SERVICE ));
+}
+
+// XServiceInfo
+
+OUString SAL_CALL ScaPricingAddIn::getImplementationName() throw( uno::RuntimeException )
+{
+ return getImplementationName_Static();
+}
+
+sal_Bool SAL_CALL ScaPricingAddIn::supportsService( const OUString& aServiceName ) throw( uno::RuntimeException )
+{
+ return aServiceName == ADDIN_SERVICE || aServiceName == MY_SERVICE;
+}
+
+uno::Sequence< OUString > SAL_CALL ScaPricingAddIn::getSupportedServiceNames() throw( uno::RuntimeException )
+{
+ return getSupportedServiceNames_Static();
+}
+
+// XLocalizable
+
+void SAL_CALL ScaPricingAddIn::setLocale( const lang::Locale& eLocale ) throw( uno::RuntimeException )
+{
+ aFuncLoc = eLocale;
+ InitData(); // change of locale invalidates resources!
+}
+
+lang::Locale SAL_CALL ScaPricingAddIn::getLocale() throw( uno::RuntimeException )
+{
+ return aFuncLoc;
+}
+
+//------------------------------------------------------------------
+//
+// function descriptions start here
+//
+//------------------------------------------------------------------
+
+// XAddIn
+OUString SAL_CALL ScaPricingAddIn::getProgrammaticFuntionName( const OUString& ) throw( uno::RuntimeException )
+{
+ // not used by calc
+ // (but should be implemented for other uses of the AddIn service)
+ return OUString();
+}
+
+OUString SAL_CALL ScaPricingAddIn::getDisplayFunctionName( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( pFData )
+ {
+ aRet = GetDisplFuncStr( pFData->GetUINameID() );
+ if( pFData->IsDouble() )
+ aRet += STR_FROM_ANSI( "_ADD" );
+ }
+ else
+ {
+ aRet = STR_FROM_ANSI( "UNKNOWNFUNC_" );
+ aRet += aProgrammaticName;
+ }
+
+ return aRet;
+}
+
+OUString SAL_CALL ScaPricingAddIn::getFunctionDescription( const OUString& aProgrammaticName ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( pFData )
+ aRet = GetFuncDescrStr( pFData->GetDescrID(), 1 );
+
+ return aRet;
+}
+
+OUString SAL_CALL ScaPricingAddIn::getDisplayArgumentName(
+ const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( pFData && (nArgument <= 0xFFFF) )
+ {
+ sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
+ if( nStr )
+ aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr );
+ else
+ aRet = STR_FROM_ANSI( "internal" );
+ }
+
+ return aRet;
+}
+
+OUString SAL_CALL ScaPricingAddIn::getArgumentDescription(
+ const OUString& aProgrammaticName, sal_Int32 nArgument ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( pFData && (nArgument <= 0xFFFF) )
+ {
+ sal_uInt16 nStr = pFData->GetStrIndex( static_cast< sal_uInt16 >( nArgument ) );
+ if( nStr )
+ aRet = GetFuncDescrStr( pFData->GetDescrID(), nStr + 1 );
+ else
+ aRet = STR_FROM_ANSI( "for internal use only" );
+ }
+
+ return aRet;
+}
+
+OUString SAL_CALL ScaPricingAddIn::getProgrammaticCategoryName(
+ const OUString& aProgrammaticName ) throw( uno::RuntimeException )
+{
+ OUString aRet;
+
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( pFData )
+ {
+ switch( pFData->GetCategory() )
+ {
+ case ScaCat_DateTime: aRet = STR_FROM_ANSI( "Date&Time" ); break;
+ case ScaCat_Text: aRet = STR_FROM_ANSI( "Text" ); break;
+ case ScaCat_Finance: aRet = STR_FROM_ANSI( "Financial" ); break;
+ case ScaCat_Inf: aRet = STR_FROM_ANSI( "Information" ); break;
+ case ScaCat_Math: aRet = STR_FROM_ANSI( "Mathematical" ); break;
+ case ScaCat_Tech: aRet = STR_FROM_ANSI( "Technical" ); break;
+ default: // to prevent compiler warnings
+ break;
+ }
+ }
+
+ if( aRet.isEmpty() )
+ aRet = STR_FROM_ANSI( "Add-In" );
+ return aRet;
+}
+
+OUString SAL_CALL ScaPricingAddIn::getDisplayCategoryName(
+ const OUString& aProgrammaticName ) throw( uno::RuntimeException )
+{
+ return getProgrammaticCategoryName( aProgrammaticName );
+}
+
+
+// XCompatibilityNames
+
+uno::Sequence< sheet::LocalizedName > SAL_CALL ScaPricingAddIn::getCompatibilityNames(
+ const OUString& aProgrammaticName ) throw( uno::RuntimeException )
+{
+ const ScaFuncData* pFData = pFuncDataList->Get( aProgrammaticName );
+ if( !pFData )
+ return uno::Sequence< sheet::LocalizedName >( 0 );
+
+ const ScaStringList& rStrList = pFData->GetCompNameList();
+ sal_uInt32 nCount = rStrList.Count();
+
+ uno::Sequence< sheet::LocalizedName > aRet( nCount );
+ sheet::LocalizedName* pArray = aRet.getArray();
+
+ for( sal_uInt32 nIndex = 0; nIndex < nCount; nIndex++ )
+ pArray[ nIndex ] = sheet::LocalizedName( GetLocale( nIndex ), *rStrList.Get( nIndex ) );
+
+ return aRet;
+}
+
+
+
+// ---------------------------------------------------------------------
+// ---------------------------------------------------------------------
+// actual function implementation starts here
+//
+
+// auxillary input handling functions
+namespace {
+
+bool getinput_putcall(bs::types::PutCall& pc, const STRING& str) {
+ if(str.compareToAscii("c",1)==0) {
+ pc=bs::types::Call;
+ } else if(str.compareToAscii("p",1)==0) {
+ pc=bs::types::Put;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool getinput_putcall(bs::types::PutCall& pc, const ANY& anyval) {
+ STRING str;
+ if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_STRING) {
+ anyval >>= str;
+ } else if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_VOID) {
+ str="c"; // call as default
+ } else {
+ return false;
+ }
+ return getinput_putcall(pc, str);
+}
+
+bool getinput_strike(double& strike, const ANY& anyval) {
+ if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_DOUBLE) {
+ anyval >>= strike;
+ } else if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_VOID) {
+ strike=-1.0; // -1 as default (means not set)
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool getinput_inout(bs::types::BarrierKIO& kio, const STRING& str) {
+ if(str.compareToAscii("i",1)==0) {
+ kio=bs::types::KnockIn;
+ } else if(str.compareToAscii("o",1)==0) {
+ kio=bs::types::KnockOut;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool getinput_barrier(bs::types::BarrierActive& cont, const STRING& str) {
+ if(str.compareToAscii("c",1)==0) {
+ cont=bs::types::Continuous;
+ } else if(str.compareToAscii("e",1)==0) {
+ cont=bs::types::Maturity;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool getinput_fordom(bs::types::ForDom& fd, const STRING& str) {
+ if(str.compareToAscii("f",1)==0) {
+ fd=bs::types::Foreign;
+ } else if(str.compareToAscii("d",1)==0) {
+ fd=bs::types::Domestic;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+bool getinput_greek(bs::types::Greeks& greek, const ANY& anyval) {
+ STRING str;
+ if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_STRING) {
+ anyval >>= str;
+ } else if(anyval.getValueTypeClass() == ::com::sun::star::uno::TypeClass_VOID) {
+ str="value";
+ } else {
+ return false;
+ }
+
+ if(str.compareToAscii("value")==0 || str.compareToAscii("price")==0 ||
+ str.compareToAscii("v")==0 || str.compareToAscii("p")==0 ) {
+ greek=bs::types::Value;
+ } else if(str.compareToAscii("delta")==0||str.compareToAscii("d")==0) {
+ greek=bs::types::Delta;
+ } else if(str.compareToAscii("gamma")==0||str.compareToAscii("g")==0) {
+ greek=bs::types::Gamma;
+ } else if(str.compareToAscii("theta")==0||str.compareToAscii("t")==0) {
+ greek=bs::types::Theta;
+ } else if(str.compareToAscii("vega")==0||str.compareToAscii("e")==0) {
+ greek=bs::types::Vega;
+ } else if(str.compareToAscii("volga")==0||str.compareToAscii("o")==0) {
+ greek=bs::types::Volga;
+ } else if(str.compareToAscii("vanna")==0||str.compareToAscii("a")==0) {
+ greek=bs::types::Vanna;
+ } else if(str.compareToAscii("rho")==0||str.compareToAscii("r")==0) {
+ greek=bs::types::Rho_d;
+ } else if(str.compareToAscii("rhof")==0||str.compareToAscii("f")==0) {
+ greek=bs::types::Rho_f;
+ } else {
+ return false;
+ }
+ return true;
+}
+
+} // namespace for auxillary functions
+
+
+// OPT_BARRIER(...)
+double SAL_CALL ScaPricingAddIn::getOpt_barrier( double spot, double vol,
+ double r, double rf, double T, double strike,
+ double barrier_low, double barrier_up, double rebate,
+ const STRING& put_call, const STRING& in_out,
+ const STRING& barriercont, const ANY& greekstr ) THROWDEF_RTE_IAE
+{
+ bs::types::PutCall pc;
+ bs::types::BarrierKIO kio;
+ bs::types::BarrierActive bcont;
+ bs::types::Greeks greek;
+ // read and check input values
+ if( spot<=0.0 || vol<=0.0 || T<0.0 || strike<0.0 ||
+ !getinput_putcall(pc,put_call) ||
+ !getinput_inout(kio,in_out) ||
+ !getinput_barrier(bcont,barriercont) ||
+ !getinput_greek(greek,greekstr) ){
+ THROW_IAE;
+ }
+
+ double fRet=bs::barrier(spot,vol,r,rf,T,strike, barrier_low,barrier_up,
+ rebate,pc,kio,bcont,greek);
+
+ RETURN_FINITE( fRet );
+}
+
+// OPT_TOUCH(...)
+double SAL_CALL ScaPricingAddIn::getOpt_touch( double spot, double vol,
+ double r, double rf, double T,
+ double barrier_low, double barrier_up,
+ const STRING& for_dom, const STRING& in_out,
+ const STRING& barriercont, const ANY& greekstr ) THROWDEF_RTE_IAE
+{
+ bs::types::ForDom fd;
+ bs::types::BarrierKIO kio;
+ bs::types::BarrierActive bcont;
+ bs::types::Greeks greek;
+ // read and check input values
+ if( spot<=0.0 || vol<=0.0 || T<0.0 ||
+ !getinput_fordom(fd,for_dom) ||
+ !getinput_inout(kio,in_out) ||
+ !getinput_barrier(bcont,barriercont) ||
+ !getinput_greek(greek,greekstr) ){
+ THROW_IAE;
+ }
+
+ double fRet=bs::touch(spot,vol,r,rf,T,barrier_low,barrier_up,
+ fd,kio,bcont,greek);
+
+ RETURN_FINITE( fRet );
+}
+
+// OPT_PRB_HIT(...)
+double SAL_CALL ScaPricingAddIn::getOpt_prob_hit( double spot, double vol,
+ double mu, double T,
+ double barrier_low, double barrier_up ) THROWDEF_RTE_IAE
+{
+ // read and check input values
+ if( spot<=0.0 || vol<=0.0 || T<0.0 ) {
+ THROW_IAE;
+ }
+
+ double fRet=bs::prob_hit(spot,vol,mu,T,barrier_low,barrier_up);
+
+ RETURN_FINITE( fRet );
+}
+
+// OPT_PRB_INMONEY(...)
+double SAL_CALL ScaPricingAddIn::getOpt_prob_inmoney( double spot, double vol,
+ double mu, double T,
+ double barrier_low, double barrier_up,
+ const ANY& strikeval, const ANY& put_call ) THROWDEF_RTE_IAE
+{
+ bs::types::PutCall pc;
+ double K;
+
+ // read and check input values
+ if( spot<=0.0 || vol<=0.0 || T<0.0 ||
+ !getinput_putcall(pc,put_call) ||
+ !getinput_strike(K,strikeval) ) {
+ THROW_IAE;
+ }
+
+ double fRet=bs::prob_in_money(spot,vol,mu,T,K,barrier_low,barrier_up,pc);
+
+ RETURN_FINITE( fRet );
+}
+
+
+
+//------------------------------------------------------------------
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/source/pricing/pricing.hrc b/scaddins/source/pricing/pricing.hrc
new file mode 100644
index 000000000000..bf4df2183847
--- /dev/null
+++ b/scaddins/source/pricing/pricing.hrc
@@ -0,0 +1,54 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#ifndef _SCA_PRICING_HRC
+#define _SCA_PRICING_HRC
+
+
+#define PRICING_RESOURCE_START 1000
+
+#define RID_PRICING_FUNCTION_DESCRIPTIONS PRICING_RESOURCE_START
+#define RID_PRICING_FUNCTION_NAMES (PRICING_RESOURCE_START+1000)
+#define RID_PRICING_DEFFUNCTION_NAMES (PRICING_RESOURCE_START+2000)
+
+
+#define PRICING_FUNCDESC_START (RID_PRICING_FUNCTION_DESCRIPTIONS+1)
+
+#define PRICING_FUNCDESC_Opt_barrier (PRICING_FUNCDESC_START)
+#define PRICING_FUNCDESC_Opt_touch (PRICING_FUNCDESC_START+1)
+#define PRICING_FUNCDESC_Opt_prob_hit (PRICING_FUNCDESC_START+2)
+#define PRICING_FUNCDESC_Opt_prob_inmoney (PRICING_FUNCDESC_START+3)
+
+
+#define PRICING_FUNCNAME_START (RID_PRICING_FUNCTION_NAMES+1)
+
+#define PRICING_FUNCNAME_Opt_barrier (PRICING_FUNCNAME_START)
+#define PRICING_FUNCNAME_Opt_touch (PRICING_FUNCNAME_START+1)
+#define PRICING_FUNCNAME_Opt_prob_hit (PRICING_FUNCNAME_START+2)
+#define PRICING_FUNCNAME_Opt_prob_inmoney (PRICING_FUNCNAME_START+3)
+
+
+#define PRICING_DEFFUNCNAME_START (RID_PRICING_DEFFUNCTION_NAMES+1)
+
+#define PRICING_DEFFUNCNAME_Opt_barrier (PRICING_DEFFUNCNAME_START)
+#define PRICING_DEFFUNCNAME_Opt_touch (PRICING_DEFFUNCNAME_START+1)
+#define PRICING_DEFFUNCNAME_Opt_prob_hit (PRICING_DEFFUNCNAME_START+2)
+#define PRICING_DEFFUNCNAME_Opt_prob_inmoney (PRICING_DEFFUNCNAME_START+3)
+
+
+#endif
diff --git a/scaddins/source/pricing/pricing.hxx b/scaddins/source/pricing/pricing.hxx
new file mode 100644
index 000000000000..66d2d26618b0
--- /dev/null
+++ b/scaddins/source/pricing/pricing.hxx
@@ -0,0 +1,418 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+//------------------------------------------------------------------
+//
+// option pricing functions add in
+//
+// most parts of this files are technical UNO details which are
+// all copied from ../datefunc/datefunc.hxx
+// to avoid having to rename all classes to do with UNO
+// technicalities we use our own namespace
+//
+//------------------------------------------------------------------
+
+#ifndef _SCA_PRICING_HXX
+#define _SCA_PRICING_HXX
+
+
+#include <string.h>
+#include <com/sun/star/lang/XServiceName.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/sheet/XAddIn.hpp>
+#include <com/sun/star/sheet/XCompatibilityNames.hpp>
+#include <com/sun/star/sheet/addin/XPricingFunctions.hpp>
+#include <cppuhelper/implbase5.hxx> // helper for implementations
+#include <tools/resid.hxx>
+#include <tools/rc.hxx>
+#include <tools/resary.hxx>
+
+#define ANY ::com::sun::star::uno::Any
+#define STRING ::rtl::OUString
+#define THROWDEF_RTE_IAE throw(::com::sun::star::uno::RuntimeException,::com::sun::star::lang::IllegalArgumentException)
+#define THROW_IAE throw ::com::sun::star::lang::IllegalArgumentException()
+#define RETURN_FINITE(d) if( ::rtl::math::isFinite( d ) ) return d; else THROW_IAE
+
+
+
+//------------------------------------------------------------------
+
+namespace sca {
+namespace pricing {
+
+class ScaList
+{
+private:
+ static const sal_uInt32 nStartSize;
+ static const sal_uInt32 nIncrSize;
+
+ void** pData; // pointer array
+ sal_uInt32 nSize; // array size
+ sal_uInt32 nCount; // next index to be inserted at
+ sal_uInt32 nCurr; // current pos for iterations
+
+ void _Grow();
+ inline void Grow();
+
+public:
+ ScaList();
+ virtual ~ScaList();
+
+ inline sal_uInt32 Count() const { return nCount; }
+
+ inline const void* GetObject( sal_uInt32 nIndex ) const
+ { return (nIndex < nCount) ? pData[ nIndex ] : NULL; }
+
+ inline void* First() { return nCount ? pData[ nCurr = 0 ] : NULL; }
+ inline void* Next() { return (nCurr + 1 < nCount) ? pData[ ++nCurr ] : NULL; }
+
+ inline void Append( void* pNew );
+};
+
+
+inline void ScaList::Grow()
+{
+ if( nCount >= nSize )
+ _Grow();
+}
+
+inline void ScaList::Append( void* pNew )
+{
+ Grow();
+ pData[ nCount++ ] = pNew;
+}
+
+
+//------------------------------------------------------------------
+
+class ScaStringList : protected ScaList
+{
+public:
+ inline ScaStringList() : ScaList() {};
+ virtual ~ScaStringList();
+
+ using ScaList::Count;
+
+ inline const ::rtl::OUString* Get( sal_uInt32 nIndex ) const;
+
+ inline ::rtl::OUString* First();
+ inline ::rtl::OUString* Next();
+
+ using ScaList::Append;
+ inline void Append( ::rtl::OUString* pNew );
+ inline void Append( const ::rtl::OUString& rNew );
+};
+
+
+inline const ::rtl::OUString* ScaStringList::Get( sal_uInt32 nIndex ) const
+{
+ return static_cast< const ::rtl::OUString* >( ScaList::GetObject( nIndex ) );
+}
+
+inline ::rtl::OUString* ScaStringList::First()
+{
+ return static_cast< ::rtl::OUString* >( ScaList::First() );
+}
+
+inline ::rtl::OUString* ScaStringList::Next()
+{
+ return static_cast< ::rtl::OUString* >( ScaList::Next() );
+}
+
+inline void ScaStringList::Append( ::rtl::OUString* pNew )
+{
+ ScaList::Append( pNew );
+}
+
+inline void ScaStringList::Append( const ::rtl::OUString& rNew )
+{
+ ScaList::Append( new ::rtl::OUString( rNew ) );
+}
+
+
+//------------------------------------------------------------------
+
+class ScaResId : public ResId
+{
+public:
+ ScaResId( sal_uInt16 nResId, ResMgr& rResMgr );
+};
+
+
+//------------------------------------------------------------------
+
+class ScaResStringLoader : public Resource
+{
+private:
+ String aStr;
+
+public:
+ inline ScaResStringLoader( sal_uInt16 nResId, sal_uInt16 nStrId, ResMgr& rResMgr );
+
+ inline const String& GetString() const { return aStr; }
+
+};
+
+
+inline ScaResStringLoader::ScaResStringLoader( sal_uInt16 nResId, sal_uInt16 nStrId, ResMgr& rResMgr ) :
+ Resource( ScaResId( nResId, rResMgr ) ),
+ aStr( ScaResId( nStrId, rResMgr ) )
+{
+ FreeResource();
+}
+
+
+//------------------------------------------------------------------
+
+class ScaResStringArrLoader : public Resource
+{
+private:
+ ResStringArray aStrArray;
+
+public:
+ inline ScaResStringArrLoader( sal_uInt16 nResId, sal_uInt16 nArrayId, ResMgr& rResMgr );
+
+ inline const ResStringArray& GetStringArray() const { return aStrArray; }
+};
+
+
+
+inline ScaResStringArrLoader::ScaResStringArrLoader( sal_uInt16 nResId, sal_uInt16 nArrayId, ResMgr& rResMgr ) :
+ Resource( ScaResId( nResId, rResMgr ) ),
+ aStrArray( ScaResId( nArrayId, rResMgr ) )
+{
+ FreeResource();
+}
+
+
+//------------------------------------------------------------------
+
+class ScaResPublisher : public Resource
+{
+public:
+ inline ScaResPublisher( const ScaResId& rResId ) : Resource( rResId ) {}
+
+ inline sal_Bool IsAvailableRes( const ResId& rResId ) const
+ { return Resource::IsAvailableRes( rResId ); }
+ inline void FreeResource()
+ { Resource::FreeResource(); }
+};
+
+
+//------------------------------------------------------------------
+
+class ScaFuncRes : public Resource
+{
+public:
+ ScaFuncRes( ResId& rResId, ResMgr& rResMgr, sal_uInt16 nIndex, ::rtl::OUString& rRet );
+};
+
+
+//------------------------------------------------------------------
+
+enum ScaCategory
+{
+ ScaCat_AddIn,
+ ScaCat_DateTime,
+ ScaCat_Text,
+ ScaCat_Finance,
+ ScaCat_Inf,
+ ScaCat_Math,
+ ScaCat_Tech
+};
+
+struct ScaFuncDataBase
+{
+ const sal_Char* pIntName; // internal name (get***)
+ sal_uInt16 nUINameID; // resource ID to UI name
+ sal_uInt16 nDescrID; // resource ID to description, parameter names and ~ description
+ sal_uInt16 nCompListID; // resource ID to list of valid names
+ sal_uInt16 nParamCount; // number of named / described parameters
+ ScaCategory eCat; // function category
+ sal_Bool bDouble; // name already exist in Calc
+ sal_Bool bWithOpt; // first parameter is internal
+};
+
+class ScaFuncData
+{
+private:
+ ::rtl::OUString aIntName; // internal name (get***)
+ sal_uInt16 nUINameID; // resource ID to UI name
+ sal_uInt16 nDescrID; // leads also to parameter descriptions!
+ sal_uInt16 nCompListID; // resource ID to list of valid names
+ sal_uInt16 nParamCount; // num of parameters
+ ScaStringList aCompList; // list of all valid names
+ ScaCategory eCat; // function category
+ sal_Bool bDouble; // name already exist in Calc
+ sal_Bool bWithOpt; // first parameter is internal
+
+public:
+ ScaFuncData( const ScaFuncDataBase& rBaseData, ResMgr& rRscMgr );
+ virtual ~ScaFuncData();
+
+ inline sal_uInt16 GetUINameID() const { return nUINameID; }
+ inline sal_uInt16 GetDescrID() const { return nDescrID; }
+ inline ScaCategory GetCategory() const { return eCat; }
+ inline sal_Bool IsDouble() const { return bDouble; }
+ inline sal_Bool HasIntParam() const { return bWithOpt; }
+
+ sal_uInt16 GetStrIndex( sal_uInt16 nParam ) const;
+ inline sal_Bool Is( const ::rtl::OUString& rCompare ) const
+ { return aIntName == rCompare; }
+
+ inline const ScaStringList& GetCompNameList() const { return aCompList; }
+};
+
+
+//------------------------------------------------------------------
+
+class ScaFuncDataList : private ScaList
+{
+ ::rtl::OUString aLastName;
+ sal_uInt32 nLast;
+
+public:
+ ScaFuncDataList( ResMgr& rResMgr );
+ virtual ~ScaFuncDataList();
+
+ using ScaList::Count;
+
+ inline const ScaFuncData* Get( sal_uInt32 nIndex ) const;
+ const ScaFuncData* Get( const ::rtl::OUString& rProgrammaticName ) const;
+ inline ScaFuncData* First();
+ inline ScaFuncData* Next();
+
+ using ScaList::Append;
+ inline void Append( ScaFuncData* pNew ) { ScaList::Append( pNew ); }
+};
+
+
+inline const ScaFuncData* ScaFuncDataList::Get( sal_uInt32 nIndex ) const
+{
+ return static_cast< const ScaFuncData* >( ScaList::GetObject( nIndex ) );
+}
+
+inline ScaFuncData* ScaFuncDataList::First()
+{
+ return static_cast< ScaFuncData* >( ScaList::First() );
+}
+
+inline ScaFuncData* ScaFuncDataList::Next()
+{
+ return static_cast< ScaFuncData* >( ScaList::Next() );
+}
+
+} // namespace pricing
+} // namespace sca
+
+
+
+//------------------------------------------------------------------
+//------------------------------------------------------------------
+
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL PricingFunctionAddIn_CreateInstance(
+ const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& );
+
+
+// AddIn class for pricing functions
+
+class ScaPricingAddIn : public ::cppu::WeakImplHelper5<
+ ::com::sun::star::sheet::XAddIn,
+ ::com::sun::star::sheet::XCompatibilityNames,
+ ::com::sun::star::sheet::addin::XPricingFunctions,
+ ::com::sun::star::lang::XServiceName,
+ ::com::sun::star::lang::XServiceInfo >
+{
+private:
+ ::com::sun::star::lang::Locale aFuncLoc;
+ ::com::sun::star::lang::Locale* pDefLocales;
+ ResMgr* pResMgr;
+ sca::pricing::ScaFuncDataList* pFuncDataList;
+
+
+ void InitDefLocales();
+ const ::com::sun::star::lang::Locale& GetLocale( sal_uInt32 nIndex );
+ ResMgr& GetResMgr() throw( ::com::sun::star::uno::RuntimeException );
+ void InitData();
+
+ ::rtl::OUString GetDisplFuncStr( sal_uInt16 nResId ) throw( ::com::sun::star::uno::RuntimeException );
+ ::rtl::OUString GetFuncDescrStr( sal_uInt16 nResId, sal_uInt16 nStrIndex ) throw( ::com::sun::star::uno::RuntimeException );
+
+public:
+ ScaPricingAddIn();
+ virtual ~ScaPricingAddIn();
+
+ static ::rtl::OUString getImplementationName_Static();
+ static ::com::sun::star::uno::Sequence< ::rtl::OUString > getSupportedServiceNames_Static();
+
+ // XAddIn
+ virtual ::rtl::OUString SAL_CALL getProgrammaticFuntionName( const ::rtl::OUString& aDisplayName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getDisplayFunctionName( const ::rtl::OUString& aProgrammaticName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getFunctionDescription( const ::rtl::OUString& aProgrammaticName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getDisplayArgumentName( const ::rtl::OUString& aProgrammaticName, sal_Int32 nArgument ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getArgumentDescription( const ::rtl::OUString& aProgrammaticName, sal_Int32 nArgument ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getProgrammaticCategoryName( const ::rtl::OUString& aProgrammaticName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::rtl::OUString SAL_CALL getDisplayCategoryName( const ::rtl::OUString& aProgrammaticName ) throw( ::com::sun::star::uno::RuntimeException );
+
+ // XCompatibilityNames
+ virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::LocalizedName > SAL_CALL getCompatibilityNames( const ::rtl::OUString& aProgrammaticName ) throw( ::com::sun::star::uno::RuntimeException );
+
+ // XLocalizable
+ virtual void SAL_CALL setLocale( const ::com::sun::star::lang::Locale& eLocale ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::lang::Locale SAL_CALL getLocale() throw( ::com::sun::star::uno::RuntimeException );
+
+ // XServiceName
+ virtual ::rtl::OUString SAL_CALL getServiceName() throw( ::com::sun::star::uno::RuntimeException );
+
+ // XServiceInfo
+ virtual ::rtl::OUString SAL_CALL getImplementationName() throw( ::com::sun::star::uno::RuntimeException );
+ virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw( ::com::sun::star::uno::RuntimeException );
+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames() throw( ::com::sun::star::uno::RuntimeException );
+
+ // ----------------------------------------
+ // methods from own interfaces start here
+ // ----------------------------------------
+
+ virtual double SAL_CALL getOpt_barrier( double spot, double vol,
+ double r, double rf, double T, double strike,
+ double barrier_low, double barrier_up, double rebate,
+ const STRING& put_call, const STRING& in_out,
+ const STRING& continuous, const ANY& greek ) THROWDEF_RTE_IAE;
+
+ virtual double SAL_CALL getOpt_touch( double spot, double vol,
+ double r, double rf, double T,
+ double barrier_low, double barrier_up,
+ const STRING& for_dom, const STRING& in_out,
+ const STRING& barriercont, const ANY& greekstr ) THROWDEF_RTE_IAE;
+
+ virtual double SAL_CALL getOpt_prob_hit( double spot, double vol,
+ double mu, double T,
+ double barrier_low, double barrier_up ) THROWDEF_RTE_IAE;
+
+ virtual double SAL_CALL getOpt_prob_inmoney( double spot, double vol,
+ double mu, double T,
+ double barrier_low, double barrier_up,
+ const ANY& strikeval, const ANY& put_call ) THROWDEF_RTE_IAE;
+
+};
+//------------------------------------------------------------------
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/scaddins/source/pricing/pricing.src b/scaddins/source/pricing/pricing.src
new file mode 100644
index 000000000000..c85a5d59aec5
--- /dev/null
+++ b/scaddins/source/pricing/pricing.src
@@ -0,0 +1,436 @@
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+
+#include "pricing.hrc"
+
+
+// function and parameter description
+Resource RID_PRICING_FUNCTION_DESCRIPTIONS
+{
+ Resource PRICING_FUNCDESC_Opt_barrier
+ {
+ String 1 // description
+ {
+ Text [ en-US ] = "pricing of a barrier option";
+ };
+
+ String 2 // name of parameter 1
+ {
+ Text [ en-US ] = "spot";
+ };
+ String 3 // description of parameter 1
+ {
+ Text [ en-US ] = "price/value of the underlying asset";
+ };
+
+ String 4 // name of parameter 2
+ {
+ Text [ en-US ] = "vol";
+ };
+ String 5 // description of parameter 2
+ {
+ Text [ en-US ] = "annual volatility of the underlying asset";
+ };
+
+ String 6 // name of parameter 3
+ {
+ Text [ en-US ] = "r";
+ };
+ String 7 // description of parameter 3
+ {
+ Text [ en-US ] = "interest rate (continuously compounded)";
+ };
+
+ String 8 // name of parameter 4
+ {
+ Text [ en-US ] = "rf";
+ };
+ String 9 // description of parameter 4
+ {
+ Text [ en-US ] = "foreign interest rate (continuously compounded)";
+ };
+
+ String 10 // name of parameter 5
+ {
+ Text [ en-US ] = "T";
+ };
+ String 11 // description of parameter 5
+ {
+ Text [ en-US ] = "time to maturity of the option in years";
+ };
+
+ String 12 // name of parameter 6
+ {
+ Text [ en-US ] = "strike";
+ };
+ String 13 // description of parameter 6
+ {
+ Text [ en-US ] = "strike level of the option";
+ };
+
+ String 14 // name of parameter 7
+ {
+ Text [ en-US ] = "barrier_low";
+ };
+ String 15 // description of parameter 7
+ {
+ Text [ en-US ] = "lower barrier (set to 0 for no lower barrier)";
+ };
+
+ String 16 // name of parameter 8
+ {
+ Text [ en-US ] = "barrier_up";
+ };
+ String 17 // description of parameter 8
+ {
+ Text [ en-US ] = "upper barrier (set to 0 for no upper barrier)";
+ };
+
+ String 18 // name of parameter 8
+ {
+ Text [ en-US ] = "rebate";
+ };
+ String 19 // description of parameter 8
+ {
+ Text [ en-US ] = "amount of money paid at maturity if barrier was hit";
+ };
+
+ String 20 // name of parameter 10
+ {
+ Text [ en-US ] = "put/call";
+ };
+ String 21 // description of parameter 10
+ {
+ Text [ en-US ] = "string to define if the option is a (p)ut or a (c)all";
+ };
+
+ String 22 // name of parameter 11
+ {
+ Text [ en-US ] = "knock in/out";
+ };
+ String 23 // description of parameter 11
+ {
+ Text [ en-US ] = "string to define if the option is of type knock-(i)n or knock-(o)ut";
+ };
+
+ String 24 // name of parameter 12
+ {
+ Text [ en-US ] = "barrier_type";
+ };
+ String 25 // description of parameter 12
+ {
+ Text [ en-US ] = "string to define whether the barrier is observed (c)ontinuously or only at the (e)nd/maturity";
+ };
+
+ String 26 // name of parameter 13
+ {
+ Text [ en-US ] = "greek";
+ };
+ String 27 // description of parameter 13
+ {
+ Text [ en-US ] = "optional parameter, if left out then the function simply returns the option price; if set, the function returns price sensitivities (Greeks) to one of the input parameters; possible values are (d)elta, (g)amma, (t)heta, v(e)ga, v(o)lga, v(a)nna, (r)ho, rho(f)";
+ };
+ };
+
+
+
+ Resource PRICING_FUNCDESC_Opt_touch
+ {
+ String 1 // description
+ {
+ Text [ en-US ] = "pricing of a touch/no-touch option";
+ };
+
+ String 2 // name of parameter 1
+ {
+ Text [ en-US ] = "spot";
+ };
+ String 3 // description of parameter 1
+ {
+ Text [ en-US ] = "price/value of the underlying asset";
+ };
+
+ String 4 // name of parameter 2
+ {
+ Text [ en-US ] = "vol";
+ };
+ String 5 // description of parameter 2
+ {
+ Text [ en-US ] = "annual volatility of the underlying asset";
+ };
+
+ String 6 // name of parameter 3
+ {
+ Text [ en-US ] = "r";
+ };
+ String 7 // description of parameter 3
+ {
+ Text [ en-US ] = "interest rate (continuously compounded)";
+ };
+
+ String 8 // name of parameter 4
+ {
+ Text [ en-US ] = "rf";
+ };
+ String 9 // description of parameter 4
+ {
+ Text [ en-US ] = "foreign interest rate (continuously compounded)";
+ };
+
+ String 10 // name of parameter 5
+ {
+ Text [ en-US ] = "T";
+ };
+ String 11 // description of parameter 5
+ {
+ Text [ en-US ] = "time to maturity of the option in years";
+ };
+
+ String 12 // name of parameter 6
+ {
+ Text [ en-US ] = "barrier_low";
+ };
+ String 13 // description of parameter 6
+ {
+ Text [ en-US ] = "lower barrier (set to 0 for no lower barrier)";
+ };
+
+ String 14 // name of parameter 7
+ {
+ Text [ en-US ] = "barrier_up";
+ };
+ String 15 // description of parameter 7
+ {
+ Text [ en-US ] = "upper barrier (set to 0 for no upper barrier)";
+ };
+
+ String 16 // name of parameter 8
+ {
+ Text [ en-US ] = "foreign/domestic";
+ };
+ String 17 // description of parameter 8
+ {
+ Text [ en-US ] = "string to define if the option pays one unit of (d)omestic currency (cash or nothing) or (f)oreign currency (asset or nothing)";
+ };
+
+ String 18 // name of parameter 9
+ {
+ Text [ en-US ] = "knock in/out";
+ };
+ String 19 // description of parameter 9
+ {
+ Text [ en-US ] = "string to define if the option is of type knock-(i)n (touch) or knock-(o)ut (no-touch)";
+ };
+
+ String 20 // name of parameter 10
+ {
+ Text [ en-US ] = "barrier_type";
+ };
+ String 21 // description of parameter 10
+ {
+ Text [ en-US ] = "string to define whether the barrier is observed (c)ontinuously or only at the (e)nd/maturity";
+ };
+
+ String 22 // name of parameter 11
+ {
+ Text [ en-US ] = "greek";
+ };
+ String 23 // description of parameter 11
+ {
+ Text [ en-US ] = "optional parameter, if left out then the function simply returns the option price; if set, the function returns price sensitivities (Greeks) to one of the input parameters; possible values are (d)elta, (g)amma, (t)heta, v(e)ga, v(o)lga, v(a)nna, (r)ho, rho(f)";
+ };
+ };
+
+
+ Resource PRICING_FUNCDESC_Opt_prob_hit
+ {
+ String 1 // description
+ {
+ Text [ en-US ] = "probability that an asset hits a barrier assuming it follows dS/S = mu dt + vol dW";
+ };
+
+ String 2 // name of parameter 1
+ {
+ Text [ en-US ] = "spot";
+ };
+ String 3 // description of parameter 1
+ {
+ Text [ en-US ] = "price/value S of the underlying asset";
+ };
+
+ String 4 // name of parameter 2
+ {
+ Text [ en-US ] = "vol";
+ };
+ String 5 // description of parameter 2
+ {
+ Text [ en-US ] = "annual volatility of the underlying asset";
+ };
+
+ String 6 // name of parameter 3
+ {
+ Text [ en-US ] = "drift";
+ };
+ String 7 // description of parameter 3
+ {
+ Text [ en-US ] = "parameter mu in dS/S = mu dt + vol dW";
+ };
+
+ String 8 // name of parameter 4
+ {
+ Text [ en-US ] = "T";
+ };
+ String 9 // description of parameter 4
+ {
+ Text [ en-US ] = "time to maturity";
+ };
+
+ String 10 // name of parameter 5
+ {
+ Text [ en-US ] = "barrier_low";
+ };
+ String 11 // description of parameter 5
+ {
+ Text [ en-US ] = "lower barrier (set to 0 for no lower barrier)";
+ };
+
+ String 12 // name of parameter 6
+ {
+ Text [ en-US ] = "barrier_up";
+ };
+ String 13 // description of parameter 6
+ {
+ Text [ en-US ] = "upper barrier (set to 0 for no upper barrier)";
+ };
+ };
+
+
+ Resource PRICING_FUNCDESC_Opt_prob_inmoney
+ {
+ String 1 // description
+ {
+ Text [ en-US ] = "probability that an asset will at maturity end up between two barrier levels, assuming it follows dS/S = mu dt + vol dW (if the last two optional parameters (strike, put/call) are specified, the probability of S_T in [strike, upper barrier] for a call and S_T in [lower barrier, strike] for a put will be returned)";
+ };
+
+ String 2 // name of parameter 1
+ {
+ Text [ en-US ] = "spot";
+ };
+ String 3 // description of parameter 1
+ {
+ Text [ en-US ] = "price/value of the asset";
+ };
+
+ String 4 // name of parameter 2
+ {
+ Text [ en-US ] = "vol";
+ };
+ String 5 // description of parameter 2
+ {
+ Text [ en-US ] = "annual volatility of the asset";
+ };
+
+ String 6 // name of parameter 3
+ {
+ Text [ en-US ] = "drift";
+ };
+ String 7 // description of parameter 3
+ {
+ Text [ en-US ] = "parameter mu from dS/S = mu dt + vol dW";
+ };
+
+ String 8 // name of parameter 4
+ {
+ Text [ en-US ] = "T";
+ };
+ String 9 // description of parameter 4
+ {
+ Text [ en-US ] = "time to maturity in years";
+ };
+
+ String 10 // name of parameter 5
+ {
+ Text [ en-US ] = "barrier_low";
+ };
+ String 11 // description of parameter 5
+ {
+ Text [ en-US ] = "lower barrier (set to 0 for no lower barrier)";
+ };
+
+ String 12 // name of parameter 6
+ {
+ Text [ en-US ] = "barrier_up";
+ };
+ String 13 // description of parameter 6
+ {
+ Text [ en-US ] = "upper barrier (set to 0 for no upper barrier)";
+ };
+
+ String 14 // name of parameter 7
+ {
+ Text [ en-US ] = "put/call";
+ };
+ String 15 // description of parameter 7
+ {
+ Text [ en-US ] = "optional (p)ut/(c)all indicator";
+ };
+
+ String 16 // name of parameter 8
+ {
+ Text [ en-US ] = "strike";
+ };
+ String 17 // description of parameter 8
+ {
+ Text [ en-US ] = "optional strike level";
+ };
+ };
+
+
+
+
+};
+
+
+// function names as accessible from cells
+Resource RID_PRICING_FUNCTION_NAMES
+{
+ String PRICING_FUNCNAME_Opt_barrier
+ {
+ Text [ en-US ] = "OPT_BARRIER";
+ };
+ String PRICING_FUNCNAME_Opt_touch
+ {
+ Text [ en-US ] = "OPT_TOUCH";
+ };
+ String PRICING_FUNCNAME_Opt_prob_hit
+ {
+ Text [ en-US ] = "OPT_PROB_HIT";
+ };
+ String PRICING_FUNCNAME_Opt_prob_inmoney
+ {
+ Text [ en-US ] = "OPT_PROB_INMONEY";
+ };
+
+};
+
+// for translating function names
+Resource RID_PRICING_DEFFUNCTION_NAMES
+{
+
+};