1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 // pricing functions add in
22 // all of the UNO add-in technical details have been copied from
23 // ../datefunc/datefunc.cxx
25 #include "pricing.hxx"
26 #include "black_scholes.hxx"
27 #include "pricing.hrc"
29 #include <cppuhelper/factory.hxx>
30 #include <cppuhelper/supportsservice.hxx>
32 #include <osl/diagnose.h>
33 #include <rtl/math.hxx>
34 #include <rtl/ustrbuf.hxx>
35 #include <tools/rcid.h>
36 #include <tools/resmgr.hxx>
38 using namespace ::com::sun::star
;
39 using namespace sca::pricing
;
42 #define ADDIN_SERVICE "com.sun.star.sheet.AddIn"
43 #define MY_SERVICE "com.sun.star.sheet.addin.PricingFunctions"
44 #define MY_IMPLNAME "com.sun.star.sheet.addin.PricingFunctionsImpl"
46 #define STR_FROM_ANSI( s ) OUString( s, strlen( s ), RTL_TEXTENCODING_MS_1252 )
48 const sal_uInt32
ScaList::nStartSize
= 16;
49 const sal_uInt32
ScaList::nIncrSize
= 16;
52 pData( new void*[ nStartSize
] ),
68 void** pNewData
= new void*[ nSize
];
69 memcpy( pNewData
, pData
, nCount
* sizeof( void* ) );
75 ScaStringList::~ScaStringList()
77 for( OUString
* pStr
= First(); pStr
; pStr
= Next() )
81 ScaResId::ScaResId( sal_uInt16 nId
, ResMgr
& rResMgr
) :
86 #define UNIQUE false // function name does not exist in Calc
88 #define STDPAR false // all parameters are described
90 #define FUNCDATA( FuncName, ParamCount, Category, Double, IntPar ) \
91 { "get" #FuncName, PRICING_FUNCNAME_##FuncName, PRICING_FUNCDESC_##FuncName, PRICING_DEFFUNCNAME_##FuncName, ParamCount, Category, Double, IntPar }
93 const ScaFuncDataBase pFuncDataArr
[] =
95 FUNCDATA( OptBarrier
, 13, ScaCat_Finance
, UNIQUE
, STDPAR
),
96 FUNCDATA( OptTouch
, 11, ScaCat_Finance
, UNIQUE
, STDPAR
),
97 FUNCDATA( OptProbHit
, 6, ScaCat_Finance
, UNIQUE
, STDPAR
),
98 FUNCDATA( OptProbInMoney
, 8, ScaCat_Finance
, UNIQUE
, STDPAR
)
103 ScaFuncData::ScaFuncData( const ScaFuncDataBase
& rBaseData
, ResMgr
& rResMgr
) :
104 aIntName( OUString::createFromAscii( rBaseData
.pIntName
) ),
105 nUINameID( rBaseData
.nUINameID
),
106 nDescrID( rBaseData
.nDescrID
),
107 nCompListID( rBaseData
.nCompListID
),
108 nParamCount( rBaseData
.nParamCount
),
109 eCat( rBaseData
.eCat
),
110 bDouble( rBaseData
.bDouble
),
111 bWithOpt( rBaseData
.bWithOpt
)
113 ScaResStringArrLoader
aArrLoader( RID_PRICING_DEFFUNCTION_NAMES
, nCompListID
, rResMgr
);
114 const ResStringArray
& rArr
= aArrLoader
.GetStringArray();
116 for( sal_uInt16 nIndex
= 0; nIndex
< rArr
.Count(); nIndex
++ )
117 aCompList
.Append( rArr
.GetString( nIndex
) );
120 ScaFuncData::~ScaFuncData()
124 sal_uInt16
ScaFuncData::GetStrIndex( sal_uInt16 nParam
) const
128 return (nParam
> nParamCount
) ? (nParamCount
* 2) : (nParam
* 2);
131 ScaFuncDataList::ScaFuncDataList( ResMgr
& rResMgr
) :
134 for( sal_uInt16 nIndex
= 0; nIndex
< SAL_N_ELEMENTS(pFuncDataArr
); nIndex
++ )
135 Append( new ScaFuncData( pFuncDataArr
[ nIndex
], rResMgr
) );
138 ScaFuncDataList::~ScaFuncDataList()
140 for( ScaFuncData
* pFData
= First(); pFData
; pFData
= Next() )
144 const ScaFuncData
* ScaFuncDataList::Get( const OUString
& rProgrammaticName
) const
146 if( aLastName
== rProgrammaticName
){
150 for( sal_uInt32 nIndex
= 0; nIndex
< Count(); nIndex
++ )
152 const ScaFuncData
* pCurr
= Get( nIndex
);
153 if( pCurr
->Is( rProgrammaticName
) )
155 const_cast< ScaFuncDataList
* >( this )->aLastName
= rProgrammaticName
;
156 const_cast< ScaFuncDataList
* >( this )->nLast
= nIndex
;
163 ScaFuncRes::ScaFuncRes( ResId
& rResId
, ResMgr
& rResMgr
, sal_uInt16 nIndex
, OUString
& rRet
) :
166 rRet
= ScaResId(nIndex
, rResMgr
).toString();
170 // entry points for service registration / instantiation
171 uno::Reference
< uno::XInterface
> SAL_CALL
ScaPricingAddIn_CreateInstance(
172 const uno::Reference
< lang::XMultiServiceFactory
>& )
174 return (cppu::OWeakObject
*) new ScaPricingAddIn();
179 SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
pricing_component_getFactory(
180 const sal_Char
* pImplName
, void * pServiceManager
, void * /*pRegistryKey*/ )
184 if ( pServiceManager
&&
185 OUString::createFromAscii( pImplName
) == ScaPricingAddIn::getImplementationName_Static() )
187 uno::Reference
< lang::XSingleServiceFactory
> xFactory( cppu::createOneInstanceFactory(
188 static_cast< lang::XMultiServiceFactory
* >( pServiceManager
),
189 ScaPricingAddIn::getImplementationName_Static(),
190 ScaPricingAddIn_CreateInstance
,
191 ScaPricingAddIn::getSupportedServiceNames_Static() ) );
196 pRet
= xFactory
.get();
205 // "normal" service implementation
206 ScaPricingAddIn::ScaPricingAddIn() :
209 pFuncDataList( NULL
)
213 ScaPricingAddIn::~ScaPricingAddIn()
215 delete pFuncDataList
;
217 delete[] pDefLocales
;
220 static const sal_Char
* pLang
[] = { "de", "en" };
221 static const sal_Char
* pCoun
[] = { "DE", "US" };
222 static const sal_uInt32 nNumOfLoc
= SAL_N_ELEMENTS( pLang
);
224 void ScaPricingAddIn::InitDefLocales()
226 pDefLocales
= new lang::Locale
[ nNumOfLoc
];
228 for( sal_uInt32 nIndex
= 0; nIndex
< nNumOfLoc
; nIndex
++ )
230 pDefLocales
[ nIndex
].Language
= OUString::createFromAscii( pLang
[ nIndex
] );
231 pDefLocales
[ nIndex
].Country
= OUString::createFromAscii( pCoun
[ nIndex
] );
235 const lang::Locale
& ScaPricingAddIn::GetLocale( sal_uInt32 nIndex
)
240 return (nIndex
< sizeof( pLang
)) ? pDefLocales
[ nIndex
] : aFuncLoc
;
243 ResMgr
& ScaPricingAddIn::GetResMgr() throw( uno::RuntimeException
)
247 InitData(); // try to get resource manager
249 throw uno::RuntimeException();
254 void ScaPricingAddIn::InitData()
257 pResMgr
= ResMgr::CreateResMgr("pricing", LanguageTag( aFuncLoc
) );
258 delete pFuncDataList
;
260 pFuncDataList
= pResMgr
? new ScaFuncDataList( *pResMgr
) : NULL
;
269 OUString
ScaPricingAddIn::GetDisplFuncStr( sal_uInt16 nResId
) throw( uno::RuntimeException
)
271 return ScaResStringLoader( RID_PRICING_FUNCTION_NAMES
, nResId
, GetResMgr() ).GetString();
274 OUString
ScaPricingAddIn::GetFuncDescrStr( sal_uInt16 nResId
, sal_uInt16 nStrIndex
) throw( uno::RuntimeException
)
278 ScaResPublisher
aResPubl( ScaResId( RID_PRICING_FUNCTION_DESCRIPTIONS
, GetResMgr() ) );
279 ScaResId
aResId( nResId
, GetResMgr() );
280 aResId
.SetRT( RSC_RESOURCE
);
282 if( aResPubl
.IsAvailableRes( aResId
) )
283 ScaFuncRes
aSubRes( aResId
, GetResMgr(), nStrIndex
, aRet
);
285 aResPubl
.FreeResource();
289 OUString
ScaPricingAddIn::getImplementationName_Static()
291 return OUString( MY_IMPLNAME
);
294 uno::Sequence
< OUString
> ScaPricingAddIn::getSupportedServiceNames_Static()
296 uno::Sequence
< OUString
> aRet( 2 );
297 OUString
* pArray
= aRet
.getArray();
298 pArray
[0] = ADDIN_SERVICE
;
299 pArray
[1] = MY_SERVICE
;
304 OUString SAL_CALL
ScaPricingAddIn::getServiceName() throw( uno::RuntimeException
, std::exception
)
306 // name of specific AddIn service
307 return OUString( MY_SERVICE
);
311 OUString SAL_CALL
ScaPricingAddIn::getImplementationName() throw( uno::RuntimeException
, std::exception
)
313 return getImplementationName_Static();
316 sal_Bool SAL_CALL
ScaPricingAddIn::supportsService( const OUString
& aServiceName
) throw( uno::RuntimeException
, std::exception
)
318 return cppu::supportsService(this, aServiceName
);
321 uno::Sequence
< OUString
> SAL_CALL
ScaPricingAddIn::getSupportedServiceNames() throw( uno::RuntimeException
, std::exception
)
323 return getSupportedServiceNames_Static();
327 void SAL_CALL
ScaPricingAddIn::setLocale( const lang::Locale
& eLocale
) throw( uno::RuntimeException
, std::exception
)
330 InitData(); // change of locale invalidates resources!
333 lang::Locale SAL_CALL
ScaPricingAddIn::getLocale() throw( uno::RuntimeException
, std::exception
)
338 // function descriptions start here
340 OUString SAL_CALL
ScaPricingAddIn::getProgrammaticFuntionName( const OUString
& ) throw( uno::RuntimeException
, std::exception
)
343 // (but should be implemented for other uses of the AddIn service)
347 OUString SAL_CALL
ScaPricingAddIn::getDisplayFunctionName( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
351 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
354 aRet
= GetDisplFuncStr( pFData
->GetUINameID() );
355 if( pFData
->IsDouble() )
356 aRet
+= STR_FROM_ANSI( "_ADD" );
360 aRet
= STR_FROM_ANSI( "UNKNOWNFUNC_" );
361 aRet
+= aProgrammaticName
;
367 OUString SAL_CALL
ScaPricingAddIn::getFunctionDescription( const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
371 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
373 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), 1 );
378 OUString SAL_CALL
ScaPricingAddIn::getDisplayArgumentName(
379 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
, std::exception
)
383 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
384 if( pFData
&& (nArgument
<= 0xFFFF) )
386 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
388 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
);
390 aRet
= STR_FROM_ANSI( "internal" );
396 OUString SAL_CALL
ScaPricingAddIn::getArgumentDescription(
397 const OUString
& aProgrammaticName
, sal_Int32 nArgument
) throw( uno::RuntimeException
, std::exception
)
401 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
402 if( pFData
&& (nArgument
<= 0xFFFF) )
404 sal_uInt16 nStr
= pFData
->GetStrIndex( static_cast< sal_uInt16
>( nArgument
) );
406 aRet
= GetFuncDescrStr( pFData
->GetDescrID(), nStr
+ 1 );
408 aRet
= STR_FROM_ANSI( "for internal use only" );
414 OUString SAL_CALL
ScaPricingAddIn::getProgrammaticCategoryName(
415 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
419 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
422 switch( pFData
->GetCategory() )
424 case ScaCat_DateTime
: aRet
= STR_FROM_ANSI( "Date&Time" ); break;
425 case ScaCat_Text
: aRet
= STR_FROM_ANSI( "Text" ); break;
426 case ScaCat_Finance
: aRet
= STR_FROM_ANSI( "Financial" ); break;
427 case ScaCat_Inf
: aRet
= STR_FROM_ANSI( "Information" ); break;
428 case ScaCat_Math
: aRet
= STR_FROM_ANSI( "Mathematical" ); break;
429 case ScaCat_Tech
: aRet
= STR_FROM_ANSI( "Technical" ); break;
430 // coverity[dead_error_begin] - following conditions exist to avoid compiler warning
437 aRet
= STR_FROM_ANSI( "Add-In" );
441 OUString SAL_CALL
ScaPricingAddIn::getDisplayCategoryName(
442 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
444 return getProgrammaticCategoryName( aProgrammaticName
);
447 // XCompatibilityNames
448 uno::Sequence
< sheet::LocalizedName
> SAL_CALL
ScaPricingAddIn::getCompatibilityNames(
449 const OUString
& aProgrammaticName
) throw( uno::RuntimeException
, std::exception
)
451 const ScaFuncData
* pFData
= pFuncDataList
->Get( aProgrammaticName
);
453 return uno::Sequence
< sheet::LocalizedName
>( 0 );
455 const ScaStringList
& rStrList
= pFData
->GetCompNameList();
456 sal_uInt32 nCount
= rStrList
.Count();
458 uno::Sequence
< sheet::LocalizedName
> aRet( nCount
);
459 sheet::LocalizedName
* pArray
= aRet
.getArray();
461 for( sal_uInt32 nIndex
= 0; nIndex
< nCount
; nIndex
++ )
462 pArray
[ nIndex
] = sheet::LocalizedName( GetLocale( nIndex
), *rStrList
.Get( nIndex
) );
467 // actual function implementation starts here
468 // auxiliary input handling functions
471 bool getinput_putcall(bs::types::PutCall
& pc
, const OUString
& str
) {
472 if(str
.startsWith("c")) {
474 } else if(str
.startsWith("p")) {
482 bool getinput_putcall(bs::types::PutCall
& pc
, const uno::Any
& anyval
) {
484 if(anyval
.getValueTypeClass() == uno::TypeClass_STRING
) {
486 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
487 str
="c"; // call as default
491 return getinput_putcall(pc
, str
);
494 bool getinput_strike(double& strike
, const uno::Any
& anyval
) {
495 if(anyval
.getValueTypeClass() == uno::TypeClass_DOUBLE
) {
497 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
498 strike
=-1.0; // -1 as default (means not set)
505 bool getinput_inout(bs::types::BarrierKIO
& kio
, const OUString
& str
) {
506 if(str
.startsWith("i")) {
507 kio
=bs::types::KnockIn
;
508 } else if(str
.startsWith("o")) {
509 kio
=bs::types::KnockOut
;
516 bool getinput_barrier(bs::types::BarrierActive
& cont
, const OUString
& str
) {
517 if(str
.startsWith("c")) {
518 cont
=bs::types::Continuous
;
519 } else if(str
.startsWith("e")) {
520 cont
=bs::types::Maturity
;
527 bool getinput_fordom(bs::types::ForDom
& fd
, const OUString
& str
) {
528 if(str
.startsWith("f")) {
529 fd
=bs::types::Foreign
;
530 } else if(str
.startsWith("d")) {
531 fd
=bs::types::Domestic
;
538 bool getinput_greek(bs::types::Greeks
& greek
, const uno::Any
& anyval
) {
540 if(anyval
.getValueTypeClass() == uno::TypeClass_STRING
) {
542 } else if(anyval
.getValueTypeClass() == uno::TypeClass_VOID
) {
548 if(str
== "value" || str
== "price" || str
== "v" || str
== "p") {
549 greek
=bs::types::Value
;
550 } else if(str
== "delta" || str
== "d") {
551 greek
=bs::types::Delta
;
552 } else if(str
== "gamma" || str
== "g") {
553 greek
=bs::types::Gamma
;
554 } else if(str
== "theta" || str
== "t") {
555 greek
=bs::types::Theta
;
556 } else if(str
== "vega" || str
== "e") {
557 greek
=bs::types::Vega
;
558 } else if(str
== "volga" || str
== "o") {
559 greek
=bs::types::Volga
;
560 } else if(str
== "vanna" || str
== "a") {
561 greek
=bs::types::Vanna
;
562 } else if(str
== "rho" || str
== "r") {
563 greek
=bs::types::Rho_d
;
564 } else if(str
== "rhof" || str
== "f") {
565 greek
=bs::types::Rho_f
;
572 } // namespace for auxiliary functions
575 double SAL_CALL
ScaPricingAddIn::getOptBarrier( double spot
, double vol
,
576 double r
, double rf
, double T
, double strike
,
577 double barrier_low
, double barrier_up
, double rebate
,
578 const OUString
& put_call
, const OUString
& in_out
,
579 const OUString
& barriercont
, const uno::Any
& greekstr
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
581 bs::types::PutCall pc
;
582 bs::types::BarrierKIO kio
;
583 bs::types::BarrierActive bcont
;
584 bs::types::Greeks greek
;
585 // read and check input values
586 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 || strike
<0.0 ||
587 !getinput_putcall(pc
,put_call
) ||
588 !getinput_inout(kio
,in_out
) ||
589 !getinput_barrier(bcont
,barriercont
) ||
590 !getinput_greek(greek
,greekstr
) ){
591 throw lang::IllegalArgumentException();
594 double fRet
=bs::barrier(spot
,vol
,r
,rf
,T
,strike
, barrier_low
,barrier_up
,
595 rebate
,pc
,kio
,bcont
,greek
);
597 RETURN_FINITE( fRet
);
601 double SAL_CALL
ScaPricingAddIn::getOptTouch( double spot
, double vol
,
602 double r
, double rf
, double T
,
603 double barrier_low
, double barrier_up
,
604 const OUString
& for_dom
, const OUString
& in_out
,
605 const OUString
& barriercont
, const uno::Any
& greekstr
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
607 bs::types::ForDom fd
;
608 bs::types::BarrierKIO kio
;
609 bs::types::BarrierActive bcont
;
610 bs::types::Greeks greek
;
611 // read and check input values
612 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ||
613 !getinput_fordom(fd
,for_dom
) ||
614 !getinput_inout(kio
,in_out
) ||
615 !getinput_barrier(bcont
,barriercont
) ||
616 !getinput_greek(greek
,greekstr
) ){
617 throw lang::IllegalArgumentException();
620 double fRet
=bs::touch(spot
,vol
,r
,rf
,T
,barrier_low
,barrier_up
,
623 RETURN_FINITE( fRet
);
627 double SAL_CALL
ScaPricingAddIn::getOptProbHit( double spot
, double vol
,
629 double barrier_low
, double barrier_up
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
631 // read and check input values
632 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ) {
633 throw lang::IllegalArgumentException();
636 double fRet
=bs::prob_hit(spot
,vol
,mu
,T
,barrier_low
,barrier_up
);
638 RETURN_FINITE( fRet
);
641 // OPT_PROB_INMONEY(...)
642 double SAL_CALL
ScaPricingAddIn::getOptProbInMoney( double spot
, double vol
,
644 double barrier_low
, double barrier_up
,
645 const uno::Any
& strikeval
, const uno::Any
& put_call
) throw( uno::RuntimeException
, lang::IllegalArgumentException
, std::exception
)
647 bs::types::PutCall pc
=bs::types::Call
;
650 // read and check input values
651 if( spot
<=0.0 || vol
<=0.0 || T
<0.0 ||
652 !getinput_putcall(pc
,put_call
) ||
653 !getinput_strike(K
,strikeval
) ) {
654 throw lang::IllegalArgumentException();
657 double fRet
=bs::prob_in_money(spot
,vol
,mu
,T
,K
,barrier_low
,barrier_up
,pc
);
659 RETURN_FINITE( fRet
);
663 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */