[Libreoffice-commits] .: postprocess/packcomponents Repository.mk scaddins/AllLangResTarget_pricing.mk scaddins/idl scaddins/InternalUnoApi_scaddins.mk scaddins/Library_pricing.mk scaddins/Module_scaddins.mk scaddins/source scp2/source solenv/gbuild

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Dec 4 04:24:04 PST 2012


 Repository.mk                                               |    1 
 postprocess/packcomponents/makefile.mk                      |    1 
 scaddins/AllLangResTarget_pricing.mk                        |   46 
 scaddins/InternalUnoApi_scaddins.mk                         |    2 
 scaddins/Library_pricing.mk                                 |   56 
 scaddins/Module_scaddins.mk                                 |    2 
 scaddins/idl/com/sun/star/sheet/addin/PricingFunctions.idl  |   49 
 scaddins/idl/com/sun/star/sheet/addin/XPricingFunctions.idl |   80 +
 scaddins/source/pricing/black_scholes.cxx                   |  960 ++++++++++++
 scaddins/source/pricing/black_scholes.hxx                   |  153 +
 scaddins/source/pricing/pricing.component                   |   26 
 scaddins/source/pricing/pricing.cxx                         |  739 +++++++++
 scaddins/source/pricing/pricing.hrc                         |   54 
 scaddins/source/pricing/pricing.hxx                         |  418 +++++
 scaddins/source/pricing/pricing.src                         |  436 +++++
 scp2/source/calc/file_calc.scp                              |    4 
 scp2/source/calc/module_calc.scp                            |    3 
 solenv/gbuild/extensions/pre_MergedLibsList.mk              |    1 
 18 files changed, 3030 insertions(+), 1 deletion(-)

New commits:
commit e9f31eaa49f9494113e72deaf0fe079701844ea4
Author: tino <ttk448 at gmail.com>
Date:   Mon Dec 3 21:49:04 2012 +0000

    adding calc add-in for option pricing
    
    Change-Id: Ica4b621a7ae7e5ab447192ae3fe7b8911295bef2
    Reviewed-on: https://gerrit.libreoffice.org/1232
    Reviewed-by: Fridrich Strba <fridrich at documentfoundation.org>
    Tested-by: Fridrich Strba <fridrich at documentfoundation.org>

diff --git a/Repository.mk b/Repository.mk
index d4e4308..9c3310e 100755
--- a/Repository.mk
+++ b/Repository.mk
@@ -323,6 +323,7 @@ $(eval $(call gb_Helper_register_libraries,OOOLIBS, \
     pcr \
     pdffilter \
     placeware \
+    pricing \
     protocolhandler \
     qstart_gtk \
     res \
diff --git a/postprocess/packcomponents/makefile.mk b/postprocess/packcomponents/makefile.mk
index 2758f25..cd9db06 100644
--- a/postprocess/packcomponents/makefile.mk
+++ b/postprocess/packcomponents/makefile.mk
@@ -77,6 +77,7 @@ my_components = \
     component/sc/util/scfilt \
     component/scaddins/source/analysis/analysis \
     component/scaddins/source/datefunc/date \
+    component/scaddins/source/pricing/pricing \
     component/sd/util/sd \
     component/sd/util/sdd \
     component/sd/util/sdfilt \
diff --git a/scaddins/AllLangResTarget_pricing.mk b/scaddins/AllLangResTarget_pricing.mk
new file mode 100644
index 0000000..d2646ab
--- /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 6be0201..a347e82 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 0000000..d8ef4bb
--- /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 2e0bb19..6558faf 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 0000000..b002ee6
--- /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 0000000..495891a
--- /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 0000000..f99906e
--- /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 at 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 0000000..5e665c5
--- /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 at 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 0000000..d50ee37
--- /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 0000000..ba4cb31
--- /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 0000000..bf4df21
--- /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 0000000..66d2d26
--- /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 0000000..c85a5d5
--- /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";
+        };
+

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list